/*
 * @(#) param.h $Date: 1998/12/15 09:20:49 $Revision: r11ros/cup_ros_ep1_pb/2 PATCH_11.00 (PHKL_17205)
 */

#ifndef _MACHINE_PARAM_INCLUDED /* allow multiple inclusions */
#define _MACHINE_PARAM_INCLUDED

#ifdef _KERNEL_BUILD
#include "../h/sysmacros.h"
#include "../machine/param_shm.h"
#else  /* ! _KERNEL_BUILD */
#include <sys/sysmacros.h>
#include <machine/param_shm.h>
#endif /* _KERNEL_BUILD */

/*	param.h	6.1	83/07/29	*/

/*
 * Machine dependent constants for HP Precision Architecture.
 */

#ifndef PGSHIFT			/* avoid redefining with assym.s */
#  ifdef KLUDGE_TLB_MP
#    define PGSHIFT  11			/* LOG2(NBPG = 4096) */
#    define HPGSHIFT 11
#  else 
#    define PGSHIFT  12			/* LOG2(NBPG = 2048) */
#    define HPGSHIFT 12
#  endif 
#  define NBPG		(1<<PGSHIFT)	/* bytes/page */
#  define NBHPG 	(1<<HPGSHIFT)   /* bytes/hardware page */
#  define PGOFSET	(NBPG-1)	/* byte offset into page */
#  define BYTESHIFT	2		/* LOG2(bytes/word) */
#  define PGNDXWDTH	(32-PGSHIFT)	/* bit width of a physical page no
				         * (page index)	*/
#  define NBPG_PA83 2048		/* 2k page size for PA-RISC 1.0 */
#endif /* not PGSHIFT */

#define	MAXPHYS	(256 * 1024)	/* Maximum size of physical I/O transfer */

#define	_BIG_ENDIAN		/* Memory storage (bytes in word) */

/*
 * At 8.0 on HP-PA when the address of a function is taken in a process that
 * uses shared libraries an indirect plabel is created.  The address points
 * to a two word entry; the actual address of the function followed by the
 * r19 value when executing in that function.  An indirect plabel is 
 * indicated by the 2nd least significant bit being set in a text pointer.
 */

#define INDIRECT_PLABEL	0x02

/*
 * Define the start of the various segments.  In HP Precision Architecture, 
 * a segment is equal to a quadrant. 
 */
# define KERN_ADDR		0x00000000L	/* system quadrant */
# define SEGSIZE_32BIT   	0x40000000L
# define QUAD1_32BIT_BEG_ADDR   0x00000000L
# define QUAD2_32BIT_BEG_ADDR   0x40000000L
# define QUAD3_32BIT_BEG_ADDR   0x80000000L
# define QUAD4_32BIT_BEG_ADDR   0xc0000000L


# define GVA_OFFSET_BITS        10
# define GVA_OFFSET_BITS_MASK   0x3ff

/*
 * By software convention, each 64-bit quadrant will only occupy
 * 42 bits (or 4Tb) worth of offset.
 */
#ifdef __LP64__
# define IO_64BIT_BEG_ADDR      0x0000000100000000L
# define PCXU_IOPAGES           ((0x0000000100000000L) / NBPG)
# define FOURGIG_PAGES          ((0x0000000100000000L) / NBPG)
# define QUAD1_64BIT_BEG_ADDR   0x0000000000000000L
# define QUAD1_64BIT_END_ADDR   0x0000040000000000L
# define QUAD2_64BIT_BEG_ADDR   0x4000000000000000L
# define QUAD2_64BIT_END_ADDR   0x4000040000000000L
# define QUAD3_64BIT_BEG_ADDR   0x8000000000000000L
# define QUAD3_64BIT_END_ADDR   0x8000040000000000L
# define QUAD4_64BIT_BEG_ADDR   0xc000000000000000L
# define QUAD4_64BIT_END_ADDR   0xc000040000000000L
# define SEGSIZE_64BIT  	0x0000040000000000L

/*
 * DATA_ADDR is *ONLY* defined for the "hand crafted" kernel process
 * creation path.  The kernel creates a user process image from the kernel
 * to launch processes such as "init".  These internal processes are created
 * as "32bit" processes.
 */
# define DATA_ADDR        0x8000000040000000L
# define LASTV_64BIT_FRSTQUAD   0x000003ffffffffffL
# define LASTV_32BIT_FRSTQUAD   0x3fffffffL
# define FIRSTV_THIRDQUAD 0x8000000000000000L
# define LASTV_THIRDQUAD  0x800003ffffffffffL
# define SIZEV_THIRDQUAD  SEGSIZE_64BIT
# define SEG_SIZE	  SEGSIZE_64BIT
#else
/*
 * The "64 bit" defines quiet the compiler "warnings".
 */
# define QUAD1_64BIT_BEG_ADDR   0x00000000L
# define QUAD1_64BIT_END_ADDR   0x3ffff000L
# define QUAD2_64BIT_BEG_ADDR   0x40000000L
# define QUAD2_64BIT_END_ADDR   0x7ffff000L
# define QUAD3_64BIT_BEG_ADDR   0x80000000L
# define QUAD3_64BIT_END_ADDR   0xbffff000L
# define QUAD4_64BIT_BEG_ADDR   0xc0000000L
# define QUAD4_64BIT_END_ADDR   0xeffff000L
# define DATA_ADDR        QUAD2_32BIT_BEG_ADDR /* user private data quadrant */
# define LASTV_32BIT_FRSTQUAD   0x3fffffff     /* last addr in system quad */
# define FIRSTV_THIRDQUAD 0x80000000    /* first addr in buffer cache quad */
# define LASTV_THIRDQUAD  0xbfffffff    /* last addr in buffer cache quad */
# define SIZEV_THIRDQUAD  SEGSIZE_32BIT
# define SEG_SIZE	  	SEGSIZE_32BIT
#endif /* __LP64__ */

/*
 * Parameters controlling pre-allocated memory in the shared memory
 * quadrant.
 *
 * The number of pages snipped off the beginning of quad 4 by the
 * gateway pages isn't really a constant.  It's just a very slowly
 * moving variable (the timescale has been years).  Far better than
 * using constants, the code that sets up the quad 4 resource map should
 * call a function to find out how many pages to snip off.  This
 * function could be supplied by the file that serves up the functions
 * that set up the gateway pages at boot since that code knows how many
 * there will be.  (XXX pdg 960716)
 */
#ifdef __LP64__
/*
 * 3 pages are used at the top of quad4 in the 32-bit address space for:
 * a 32-bit gateway page, a 64-bit gateway page, and a page for
 * 64-bit syscall vectors.
 */
#define QUAD4_32BIT_BEG_FREE (3*NBPG)
#else /* ! __LP64__ */
/*
 * 1 32-bit gateway page
 */
#define QUAD4_32BIT_BEG_FREE NBPG

#endif /* ! __LP64__ */

/*
 * The following definitions are used to determine the user's data, stack, and
 * u-area pregion virtual address offset boundaries.  The pregion skip list
 * routines (i.e. findpreg()) assume that pregion address offsets do not
 * overlap, except for the special case of multiple thread u-areas mapping to
 * the same offsets.  The u-area is fixed size, but the maximum data and
 * stack sizes are controlled with maxdsize and maxssize.  Depending on the OS
 * and binary type, the u-area may or may not be in the same quadrant as data
 * and stack.  Finally, the stack requires a buffer of "red zone" pages for
 * compatibility and standards purposes.
 *
 * First, let's describe 32-bit HP-UX.  For normal processes, data, stack, and
 * u-area are all in the 2nd quadrant.  U-area is fixed size at the end of the
 * quadrant.  The stack is adjacent to u-area.  Max stack size is determined in
 * p0init() and used to compute the stack starting address.  maxssize takes
 * precedence over maxdsize, however DATA_MINPAGES establishes the minimum
 * amount of data pregion address space in the 2nd quadrant and throttles the
 * maximum stack size.
 *
 * When computing maxssize, we also allow for a "red zone" at the
 * very end of the stack that cannot be accessed by the process.  This is used
 * in the event the stack is full and we need to kill the process; the signals
 * code uses these extra pages.  Past releases of HP-UX fixed the stack
 * starting address and limited maxssize so the maxssize limit was always less
 * than USRSTACK_MAXADDR().  Now that we "float" the stack starting address, we
 * need to take care to leave in a red zone "buffer".
 *
 * Here's the picture for normal SHARE_MAGIC binaries on 32-bit HP-UX:
 *
 *                    2nd quadrant
 *                    ------------
 *
 *        - USRDATA_STARTADDR()
 *       /
 *      |               - USRSTACK_ADDR()
 *      |              /
 *      |             |                - UAREA, USRSTACKMAX_ADDR()
 *      |             |               /
 *      |             |              |
 *      ------------------------------------------
 *      |         |   |          | r |           |
 *      |         |   |          | e |           |
 *      |         | . |          | d |  thread   |
 *      | data -> | . | stack -> |   | u-area(s) |
 *      |         | . |          | z |           |
 *      |         |   |          | o |           |
 *      |         |   |          | n |           |
 *      |         |   |          | e |           |
 *      ------------------------------------------
 *                    <---------><--><---------->
 *                      maxssize  |   UAREA_VIRT_PAGES
 *                                 \
 *                                  - RED_ZONE_PAGES
 *
 * For EXEC_MAGIC binaries the data pregion immediately follows the text
 * pregion and USRDATA_STARTADDR() is ignored.  Otherwise everything looks the
 * same. 
 *
 * For SHMEM_MAGIC binaries, data and stack are moved to the first quadrant to
 * make room for shared memory.  The u-area stays as-is.  In order to prevent
 * shared memory pregion offsets from overlapping the u-area, the offsets used
 * by the u-area are removed from quad2map.  Here's the picture for
 * SHMEM_MAGIC:
 *
 *                    1st quadrant
 *                    ------------
 *
 *                                 - USRSTACK_ADDR()
 *                                /
 *                               |                - USRSTACKMAX_ADDR()
 *                               |               /
 *                               |              |
 *      -----------------------------------------
 *      |      |   |         |   |          | r |
 *      |      |   |         |   |          | e |
 *      |      | . |         | . |          | d |
 *      | text | . | data -> | . | stack -> |   |
 *      |      | . |         | . |          | z |
 *      |      |   |         |   |          | o |
 *      |      |   |         |   |          | n |
 *      |      |   |         |   |          | e |
 *      -----------------------------------------
 *                               <---------><-->
 *                                maxssize   |
 *                                            \
 *                                             - RED_ZONE_PAGES
 *
 *                    2nd quadrant
 *                    ------------
 *
 *                                     - UAREA
 *                                    /
 *                                   |
 *      ------------------------------------------
 *      |                            |           |
 *      |                            |           |
 *      |        reserved            |  thread   |
 *      |           for              | u-area(s) |
 *      |          shmem             |           |
 *      |                            |           |
 *      |                            |           |
 *      |                            |           |
 *      ------------------------------------------
 *                                   <---------->
 *                                    UAREA_VIRT_PAGES
 *
 * For 64-bit HP-UX, all u-areas are at the end of the 64-bit 2nd quadrant,
 * for both 32- and 64-bit processes.  I.e. there's no longer reason to worry
 * about u-area overlap for 32-bit processes.  So for 32-bit SHARE_MAGIC and
 * EXEC_MAGIC processes running on 64-bit HP-UX, the picture looks like:
 *
 *                    2nd quadrant
 *                    ------------
 *
 *        - USRDATA_STARTADDR()
 *       /
 *      |               - USRSTACK_ADDR()
 *      |              /
 *      |             |                - USRSTACKMAX_ADDR()
 *      |             |               /
 *      |             |              |
 *      ------------------------------
 *      |         |   |          | r |
 *      |         |   |          | e |
 *      |         | . |          | d |
 *      | data -> | . | stack -> |   |
 *      |         | . |          | z |
 *      |         |   |          | o |
 *      |         |   |          | n |
 *      |         |   |          | e |
 *      ------------------------------
 *                    <---------><-->
 *                      maxssize  |
 *                                 \
 *                                  - RED_ZONE_PAGES
 *
 * For 32-bit SHMEM_MAGIC processes running on 64-bit HP-UX, the picture looks
 * the same as for SHMEM_MAGIC on 32-bit HP-UX, except the entire 32-bit 2nd
 * quadrant is reserved for shmem since the u-area is elsewhere, and no special
 * tinkering is done to quad2map.
 *
 * Finally, for 64-bit processes running on 64-bit HP-UX, we don't have any
 * EXEC_MAGIC, etc. to worry about.  The picture looks the same as for 32-bit
 * SHARE_MAGIC/EXEC_MAGIC, except the pregions live in the 64-bit 3rd quadrant
 * instead of the 32-bit 2nd quadrant.  However, the 64-bit stack starting
 * address ustk_addr_64bit is aligned for large pages.  So the effect is to
 * have more red zone pages than was asked for, but that's okay.
 *
 * P.S.  Also, just to be paranoid, we set KSTACKBYTES so that the
 * kernel stack ends on the last mapped u-area page like it always has.  Also,
 * the u-area is positioned so there is unmapped space between the end of the
 * mapped u-area pages and end of the quadrant, as there has been historically.
 */

#ifndef LOCORE
extern char *ustk_addr_q2_32bit;
extern char *ustk_addr_32bit;
#endif /* LOCORE */

#define UAREA_VIRT_PAGES			16
#define UAREA_SIZE				(UAREA_VIRT_PAGES << PGSHIFT)
#define USRSTACK_MAX32BIT_Q2SHARED_ADDR		QUAD2_32BIT_BEG_ADDR
#define RED_ZONE_PAGES				2
#define RED_ZONE_SIZE				(RED_ZONE_PAGES << PGSHIFT)
#define DATA_MINPAGES				16384
#define DATA_MINSIZE				(DATA_MINPAGES << PGSHIFT)

#ifdef __LP64__

#ifndef LOCORE
extern char *ustk_addr_64bit;
#endif /* LOCORE */

#define UAREA			(QUAD2_64BIT_END_ADDR - UAREA_SIZE)
#define USRSTACK_MAX32BIT_ADDR	QUAD3_32BIT_BEG_ADDR
#define USRSTACK_MAX64BIT_ADDR	QUAD3_64BIT_END_ADDR

# define USR_MAXSSIZ(vas)						\
	(is_64ASL(vas) ?						\
		(SEGSIZE_64BIT - (DATA_MINSIZE + RED_ZONE_SIZE)) :	\
		(SEGSIZE_32BIT - (DATA_MINSIZE + RED_ZONE_SIZE)))

# define USRSTACK_ADDR(vas)						\
	(is_64ASL(vas) ?						\
		ustk_addr_64bit :					\
	(is_q2shared(vas) ?						\
		ustk_addr_q2_32bit :					\
		ustk_addr_32bit))

# define USRSTACKMAX_ADDR(vas)						\
	(is_64ASL(vas) ?						\
		USRSTACK_MAX64BIT_ADDR :				\
        (is_q2shared(vas) ?						\
		USRSTACK_MAX32BIT_Q2SHARED_ADDR :         		\
		USRSTACK_MAX32BIT_ADDR))

# define USRDATA_STARTADDR(vas)						\
	(is_64ASL(vas) ?						\
		QUAD3_64BIT_BEG_ADDR :					\
		QUAD2_32BIT_BEG_ADDR)

#else /* !__LP64__ */

#define UAREA			(QUAD3_32BIT_BEG_ADDR - UAREA_SIZE)
#define USRSTACK_MAX32BIT_ADDR	UAREA

#define USR_MAXSSIZ(vas)						\
	(is_q2shared(vas) ?						\
		(SEGSIZE_32BIT - (DATA_MINSIZE + RED_ZONE_SIZE)) :	\
		(SEGSIZE_32BIT - (DATA_MINSIZE + RED_ZONE_SIZE + UAREA_SIZE)))

#define USRSTACK_ADDR(vas)						\
	(is_q2shared(vas) ?						\
		ustk_addr_q2_32bit :					\
		ustk_addr_32bit)

#define USRSTACKMAX_ADDR(vas)						\
	(is_q2shared(vas) ?						\
		USRSTACK_MAX32BIT_Q2SHARED_ADDR :			\
		USRSTACK_MAX32BIT_ADDR)

#define USRDATA_STARTADDR(vas)		(QUAD2_32BIT_BEG_ADDR)

#endif /* __LP64__ */

/*
 * LASTV_32BIT_ADDR is the last virtual address in the 32-bit address space 
 */
# define LASTV_32BIT_ADDR  	0xffffffffL

/*
 * KSTACKADDR is the base of the kernel stack, actually IN Uarea 
 */
#define TOPKSTACK (UAREA+UPAGES*NBPG)    /* top of kernel stack */

/* Shared 32-bit quad4 space begins after the gateway pages */
#define SHARED_32BIT_QUAD4_BEG (QUAD4_32BIT_BEG_ADDR + QUAD4_32BIT_BEG_FREE)
#define SHARED_32BIT_IO (SEGSIZE_32BIT/4)     /* Must not be > SEGSIZE/2 */

/* Shared 32-bit quad4 space ends before IO shared space */
#define SHARED_32BIT_QUAD4_END (QUAD4_32BIT_BEG_ADDR + \
                              (SEGSIZE_32BIT - SHARED_32BIT_IO))

#ifndef	LOCORE

#define KSTACKADDR (UAREA+sizeof(struct user)-sizeof(double))  

/*
 * Most of the machine dependent macros are now in ../h/sysmacros.h.
 */

/* bytes to word and backwards */
#define	btowr(x) (btow(((ulong_t)(x))+(WORD_SIZE-1))) /* round up # bytes to
					       		# words */
#define wtob(x) ( (ulong_t)(x) << BYTESHIFT )


#define	DELAY(n)	{ register int N = (n); while (--N > 0); }

/*
 * The following are parameters to lacc that indicate if lacc is to pfault
 * to try and resolve any lack of access. If LACC_PFAULT is specified, 
 * lacc will try to resolve the lack of access rights by calling
 * pfault. If LACC_NOPFAULT is specified lacc will just return 0, on a lack
 * of the specified access and it  will not call pfault.
 */
#define LACC_PFAULT	1
#define LACC_NOPFAULT	0

#define	lkernacc(sid, off, bcnt, rw)	\
	lacc((sid), (off), (bcnt), (rw), 0, LACC_PFAULT)
#define	luseracc(sid, off, bcnt, rw)	\
	lacc((sid), (off), (bcnt), (rw), 3, LACC_PFAULT)
#define	useracc(addr, bcnt, rw)		\
	lacc(ldusid(addr), (addr), (bcnt), (rw), 3, LACC_PFAULT)

#define	useracc_nopfault(addr, bcnt, rw)	\
		lacc(ldusid(addr), (addr), (bcnt), (rw), 3, LACC_NOPFAULT)

#define	kernacc(addr, bcnt, rw)		acc((addr), (bcnt), (rw), 0)

#define	fuibyte(base)		fubyte(base)
#define	fuiword(base)		fuword(base)

/* kernel bcopy does not support ovbcopy functionality */
#if !defined(_KERNEL) && !defined(_KERNEL_BUILD)
#define ovbcopy			bcopy
#endif

# ifdef _KERNEL
/* 64XXX:
 * This flag will indicate whether the kernel supports 64 bit user programs
 * built using BE2. Will be FALSE for now and can be changed to TRUE when
 * they become available. This variable will be removed a month after BE2
 * becomes available.
 */
extern int be2_convention;

#define IS_PLABEL(addr) \
		((((ulong_t)addr & INDIRECT_PLABEL) || \
		  (is_64bit(u.u_procp) && be2_convention)) ? TRUE : FALSE)


# ifdef __LP64__
/* 
 * Swizzle macro that will convert a 32 bit address to a
 * 64 bit address. Take the top 2 bits from the 32bit address and
 * propagate it to the top 2 bits of the 64bit address. The macro
 * returns a 64bit value when the kernel is in wide mode. When
 * the kernel is running in narrow mode, the macro is a no-op
 */
#  define SWIZZLE_VADDR(vaddr)                 \
                  ((uintptr_t)(vaddr) |        \
                  (((uintptr_t)(vaddr) & 0xC0000000L) << 32))
# else
#  define SWIZZLE_VADDR(vaddr)       (vaddr)
# endif /* __LP64__ */

/* 
 * Get the top 10 bits of the offset from the vaddr passed in.
 */
#  define OFFSET_BITS_FOR_SPACE(vaddr)                    \
                           (LP64_KERNEL ?                 \
                            (((uintptr_t)(vaddr) >> 32) &  \
                              GVA_OFFSET_BITS_MASK) : 0L)
/*
 * Retrieve the 10 bits of offset from the GVA space passed in.
 */
#  define OFFSET_BITS_FROM_SPACE(space)                    \
                           (LP64_KERNEL ? ((space) & GVA_OFFSET_BITS_MASK) : 0L)

/* 
 * Return the true space part of the space field by masking out the
 * offset part.
 */
#  define TRUE_SPACE(space)                                       \
                           (LP64_KERNEL ?                          \
                             ((space) & ~GVA_OFFSET_BITS_MASK): \
                             (space))
/*
 * Mask off the space register selection bits from a 64-bit offset
 */
#  define MASK_SR(vaddr)  ((ulong_t)vaddr & 0x3fffffffffffffffL)

# endif /* _KERNEL */
#endif /* not LOCORE */

#ifdef _KERNEL
/*
 * To be used by the trap code to convert the hardware generated space
 * and offset to something that the fault handlers can use.
 */
# define DATA_FAULT_ADDR  1
# define INSTR_FAULT_ADDR 2
#endif /* _KERNEL */

/* To be used by subsystems that needs to mark some pages as
 * certain types.
 * CLIC - Cluster Interconnect.
 */
#define CLIC 0

#endif /* _MACHINE_PARAM_INCLUDED */
