#define SCCSID  "@(#)pgdata.c   6.6 92/03/15"

/*
 *      IBM/Microsoft Confidential
 *
 *      Copyright (c) IBM Corporation 1987, 1989
 *      Copyright (c) Microsoft Corporation 1987, 1989
 *
 *      All Rights Reserved
 */

#define FNO_NUM FNO_PGDATA_C
#include <fnomem.h>
#include <osconst.h>
#include <ostypes.h>
#include <osmac.h>
#include <mi.h>
#include <dossymc.h>
#include <sigdef.h>
#include <except.h>
#include <pgexport.h>
#include <vmexport.h>
#include <tkexport.h>
#include <infoseg.h>
#include <curdir.h>
#include <dirent.h>
#include <find.h>
#include <screen.h>
#include <sem.h>
#include <tkptda.h>
#include <smexport.h>
#define  INCL_TYPES
#include <basedef.h>
#include <mvdmexp.h>
#include <pglocal.h>
#include <sched.h>

#define BITMAP(n)       (((n) + 31) / 32)

/***ED+ Exported page manager data variables */

// Moved to sdata.asm for System Anchor Block - f122427
extern int PGSwapEnabled;                      /* swapping enabled flag */

ulong_t  PGFaultCnt;                    /* page faults since last dispatch DCR 1203*/
#if     defined(PMDEBUG) && defined(PGSTRICT)
struct pfi_s apfi[NPFI];                /* array of page fault info structs */
#endif
/*end*/

/***LD+ Local page manager data variables */

// Moved to sdata.asm for System Anchor Block - f122427
extern struct vp_s *pgpVPBase;                 /* base address of vp array */
extern ulong_t pgVPBasePg;                     /* base page number for vp array */
extern struct vp_s *pgpVPEnd;                  /* requested end of vp array */
extern ulong_t pgVPEndPg;                      /* page number of end of vp array */
extern struct vp_s pgVPHead;                   /* head of vp free list */
extern struct vp_s pgListHeadVP;               /* fake VP for PF list heads */


VMHOB pgVPHob;                          /* handle to vp array's object */

struct vp_s *pgpZeroFillVP;             /* vp for discardable zerofill pages */
ulong_t pgZeroFillPte;                  /* pte image for a new disc-zfill pg */


laddr_t pgAliasLaddr;                   /* linear alias laddr */
struct pte_s *pgAliasPte;               /* pointer to pte for alias */
laddr_t PGSegBufLaddr;                  /* segment buffer laddr */
laddr_t pgLdrPageBufLaddr;              /* loader buffer laddr */
laddr_t pgSwapPageBufLaddr;             /* swapper buffer laddr */
int pgSwapAddrType;                     /* swapper interface address type */
ushort_t pgBufSels[BUFSELS];            /* for 16:16 swap alias selectors */
ushort_t pgAllocBufHob;                 /* hob for alloc bufs */
struct savePF_s *pgpSavePF = NULL;

/* context allocation data: */
ulong_t pgbmContext[BITMAP(TKCPTDAMAX)];/* page table context bitmap */

/* PGAllocBuf data */
ulong_t pgbmSegBuf[BITMAP(MAXSEGBUFS)];     /* segment load buffer bitmap */
ulong_t pgbmLdrPageBuf[BITMAP(MAXLDRFAULTS)];      /* loader buffer bitmap */
ulong_t pgbmSwapPageBuf[BITMAP(MAXSWAPPERFAULTS)]; /* swapper buffer bitmap */
ushort_t pgSegBufOwner[MAXSEGBUFS];
#ifdef PGSTRICT
ushort_t pgLdrBufOwner[MAXLDRFAULTS];
ushort_t pgSwapBufOwner[MAXSWAPPERFAULTS];
#endif
uchar_t pgSegBufWanted;
uchar_t pgLdrBufWanted;
uchar_t pgSwapBufWanted;
ulong_t pgSegBufPte[MAXSEGBUFS*16];     /* image of initial ptes for SegBufs */

struct pte_s *pgpPageDir;               /* global page directory lin address */
struct pte_s *pgpSysPageTables;         /* system page tables */
struct pte_s *pgpCRPageTables;          /* CR page tables */
struct pte_s *pgpShrCRPageTables;       /* global shared region pg tbls */
VMHOB   pgShrCRPtHOB;                   /* obj rec handle for GSR */
VMHOB   pgCRPtHOB;                      /* object record handle for cr pts */
VMHOB   pgSysPtHOB;                     /* object record handle for sys pts */
page_t pgSysPtpg;                       /* base page # of sys page tables */

/* system arena global data: */
struct pgdata_s pgData;                 /* global page directory data */
struct pgdata_s pgShrData;         /* GSR global shared page directory data */


/* system arena per-page-table data: */
ushort_t pgcPteAllocated[MAXSYSPDE];    /* count of allocated pages */
ushort_t pgcPtePresent[MAXSYSPDE];      /* count of present pages */
ushort_t pgcPteResident[MAXSYSPDE];     /* count of resident/locked pages */ //d25306

// GSR start
/* global shared arena per-page-table data: */
ushort_t pgcShrPteAllocated[MAXGLOBALSHRPDE];    /* count of allocated pages */
ushort_t pgcShrPtePresent[MAXGLOBALSHRPDE];      /* count of present pages */
ushort_t pgcShrPteResident[MAXGLOBALSHRPDE];     /* count of resident/locked pages */ // d25306
// GSR end

/* GSR LDT virtual address */
ulong_t pgLDTva;

/* overcommit info */
ulong_t pgPhysPages=0;                  /* total physical pages in system */
/*
 *  pgSwappablePages, pgResidentPages and pgDiscardable pages must be
 *  in this order, which can be accessed as an array indexed by
 *  the PG_ state flags shifted by PG_COMMITSHIFT
 */
ulong_t pgSwappablePages=0;             /* swappable pages committed */
ulong_t pgResidentPages=0;              /* resident physical pages */
ulong_t pgDiscardablePages=0;           /* discardable pages allocated */
ulong_t pgShortLockPages=0;             /* outstanding short term locked pgs */
ulong_t pgMaxResPages=0;                /* maximum allowable resident pages */
ulong_t pgResidentWanted=0;             /* to wait for resident mem */
int     pgResPT=0;                      /* number of resident page tables */

ulong_t pgDiscardableInmem= 0;

// Moved to sdata.asm for System Anchor Block - f122427
extern ulong_t PGGlobalFlags;


ulong_t pgcPageFaults = 0;              /* running count of all page faults */
ulong_t pgcPageFaultsActive = 0;        /* count of page faults in progress */
paddr_t pgPhysMax=0;                    /* top of physical memory */
uchar_t pgShortLockWanted;              /* someone is waiting for short lock */

struct list_s pgFreeList;               /* free list information structure */
struct list_s pgIdleList;               /* idle list information structure */
int pgListCount;                        /* number of pf's on both lists */
int pgErrCdMask;                        /* page fault error code mask */
int pg64Kerrata;                        /* low 64K errata flag on B1 */
int pgflPinFault;                       /* page fault pin flags */
struct physarena_s pgPageablePAI;       /* pageable physical arena structure */
struct physarena_s pgResidentPAI;       /* resident physical arena structure */
frame_t pgLoResBoundfr;                 /* low resident boundary frame */
struct pf_s *pgLoResBoundppf;           /* low resident boundary pf pointer */
frame_t pgHiResBoundfr;                 /* high resident boundary frame */
struct pf_s *pgHiResBoundppf;           /* high resident boundary pf pointer */
struct pf_s *pft;                       /* page frame table */
ulong_t pgFlagMask = -1;                /* mask for unneeded flags */

ulong_t pgAgerAsleep;                   /* flag and block id if ager sleeps */
struct tcb_s *pgpAgerTCB;               /* ager's tcb */
struct pte_s *pgTSDStart;               /* pointer to pte of first TSD */
struct pte_s *pgTSDEnd;                 /* pointer to pte of last TSD - 1 */

/* page aging rate parameter table with some default values */
struct agerate_s pgAgeRateTable[NRATES] ={
     /* minidle, maxidle, sleepms, prtyclass,           prtydelta, ntables*/
        {0     , 10     , 0      , CLASS_TIME_CRITICAL, LEVEL_MAX, 5},
        {5     , 20     , 0      , CLASS_REGULAR      , LEVEL_MAX, 5},
        {15    , 30     , 0      , CLASS_REGULAR      , LEVEL_MIN, 5},
        {25    , 40     , 0      , CLASS_IDLE_TIME    , 0        , 5},
        {35    , -1     , -1     , CLASS_IDLE_TIME    , 0        , 1}
};

struct agerate_s *pgCurAgeRate = &pgAgeRateTable[NRATES-1]; /* starting rate */

/*end*/

/*
 *  Structure for contiguity statistics
 */
#ifdef CONTIGSTAT
struct contigstat_s GlobalContigStat;
struct contigstat_s *pGlobalContigStat = &GlobalContigStat;
#endif
#ifdef MEMSTAT
struct memstat_s GlobalMemStat;
struct memstat_s *pGlobalMemStat = &GlobalMemStat;
#endif


/* Variables used by Dos32QueryPageUsage PROFILE */
QPUCONTROL ApuOwner = {NULL, 0, 0} ;   // PTDA and PID of app monitoring program
QPUCONTROL MonApp   = {NULL, 0, 0} ;   // PTDA and PID of monitored app
QPUCONTROL MonSys   = {NULL, 0, 0} ;   // PTDA and PID of kernel monitoring prog

PQPUINFO pResInfBuf = NULL ;        // Resident Info Buffer
ulong_t cbRIB = 0 ;                 // Size of above
ushort_t fRegistered = FALSE ;      // Marks registration of monitoring app
// DCR 32500
/*  pgHighPages - number of pages above the 16 meg line
 *  moved from cinit_data for GetSysInfo call to return true physical memory
 *  size at init time see tkinit.c
 */
ulong_t pgHighPages = 0;

/*  pgHighPagesUsed - number of high pages that were allocated before the
 *              swapper was initialized by dh_vmalloc (VMDHA_USEHIGHMEM flag)
 */
ulong_t pgHighPagesUsed=0;
// end
/* Variables used at init time only */
#pragma data_seg("CINIT_DATA", "CINITDATA")

/* Variables used by NOHIGHMEM support */

ulong_t pgTruePhysMax;
frame_t pgHighMemHeadframe;
frame_t pgHighMemTailframe;

struct pf_s *pgHighMemHeadppf;
struct pf_s *pgHighMemTailppf;
ushort_t pgHighInitPending = 1;
struct physboundary_s pgTrueEndBound;
ulong_t baseladdr;
struct arena_s *paPend;
struct arena_s *paVend;
struct arena_s *pa1M;
#pragma data_seg()
