vm_dep.h revision a985e5786d4eb44e83b59c9c7e38bc77e12fec47
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* UNIX machine dependent virtual memory support.
*/
#ifndef _VM_DEP_H
#define _VM_DEP_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
/*
* WARNING: vm_dep.h is included by files in common. As such, macros
* dependent upon PTE36 such as LARGEPAGESIZE cannot be used in this file.
*/
/* memranges in descending order */
#define MEMRANGEHI(mtype) \
#define MTYPE_FREEMEM(mt) \
/*
* combined memory ranges from mnode and memranges[] to manage single
*/
typedef struct {
int mnr_mnode;
int mnr_memrange; /* index into memranges[] */
/* maintain page list stats */
#ifdef DEBUG
int mnr_mts_colors;
} *mnr_mts;
#endif
} mnoderange_t;
#ifdef DEBUG
} \
}
#define PLCNT_INIT(addr) { \
colors; \
} \
} \
}
if (flags & PG_CACHE_LIST) \
mnr_mt_clpgcnt, cnt); \
else if (szc) \
mnr_mt_lgpgcnt, cnt); \
else \
mnr_mt_flpgcnt, cnt); \
mnr_mts_pgcnt, cnt); \
}
#else
#define PLCNT_INIT(base)
if (flags & PG_CACHE_LIST) \
mnr_mt_clpgcnt, cnt); \
else if (szc) \
mnr_mt_lgpgcnt, cnt); \
else \
mnr_mt_flpgcnt, cnt); \
}
#endif
}
}
/*
* macros to update page list max counts. no-op on x86.
*/
#define PLCNT_XFER_NORELOC(pp)
extern mnoderange_t *mnoderanges;
extern int mnoderangecnt;
extern int mtype4g;
/*
* 4g memory management variables for systems with more than 4g of memory:
*
* physical memory below 4g is required for 32bit dma devices and, currently,
* for kmem memory. On systems with more than 4g of memory, the pool of memory
* below 4g can be depleted without any paging activity given that there is
* likely to be sufficient memory above 4g.
*
* physmax4g is set true if the largest pfn is over 4g. The rest of the
* 4g memory management code is enabled only when physmax4g is true.
*
* maxmem4g is the count of the maximum number of pages on the page lists
* with physical addresses below 4g. It can be a lot less then 4g given that
* BIOS may reserve large chunks of space below 4g for hot plug pci devices,
* agp aperture etc.
*
* freemem4g maintains the count of the number of available pages on the
* page lists with physical addresses below 4g.
*
* DESFREE4G specifies the desired amount of below 4g memory. It defaults to
* 6% (desfree4gshift = 4) of maxmem4g.
*
* RESTRICT4G_ALLOC returns true if freemem4g falls below DESFREE4G
* and the amount of physical memory above 4g is greater than freemem4g.
* In this case, page_get_* routines will restrict below 4g allocations
* for requests that don't specifically require it.
*/
extern int physmax4g;
extern int lotsfree4gshift;
extern int desfree4gshift;
#define RESTRICT4G_ALLOC \
/*
* 16m memory management:
*
* reserve some amount of physical memory below 16m for legacy devices.
*
* RESTRICT16M_ALLOC returns true if an there are sufficient free pages above
* 16m or if the 16m pool drops below DESFREE16M.
*
* In this case, general page allocations via page_get_{free,cache}list
* routines will be restricted from allocating from the 16m pool. Allocations
* that require specific pfn ranges (page_get_anylist) and PG_PANIC allocations
* are not restricted.
*/
#define FREEMEM16M MTYPE_FREEMEM(0)
#define DESFREE16M desfree16m
((freemem >= (FREEMEM16M)) || \
extern pgcnt_t desfree16m;
extern int restricted_kmemalloc;
extern int memrange_num(pfn_t);
extern int pfn_2_mtype(pfn_t);
extern int mtype_func(int, int, uint_t);
extern void mtype_modify_max(pfn_t, long);
extern int mnode_pgcnt(int);
/*
* Per page size free lists. Allocated dynamically.
* dimensions [mtype][mmu_page_sizes][colors]
*
* mtype specifies a physical memory range with a unique mnode.
*/
extern page_t ****page_freelists;
/*
* For now there is only a single size cache list. Allocated dynamically.
* dimensions [mtype][colors]
*
* mtype specifies a physical memory range with a unique mnode.
*/
extern page_t ***page_cachelists;
/*
* There are mutexes for both the page freelist
* and the page cachelist. We want enough locks to make contention
* reasonable, but not too many -- otherwise page_freelist_lock() gets
* so expensive that it becomes the bottleneck!
*/
#define NPC_MUTEX 16
/* Find the bin for the given page if it was of size szc */
#if defined(__amd64)
/*
* set the mtype range (called from page_get_{free,cache}list)
* - set range to above 4g if the system has more than 4g of memory and the
* amount of memory below 4g runs low. If not, set range to above 16m if
* 16m threshold is reached otherwise set range to all of memory
* starting from the hi pfns.
*
* page_get_anylist gets its mtype range from the specified ddi_dma_attr_t.
*/
if (RESTRICT4G_ALLOC) { \
/* here only for > 4g systems */ \
flags |= PGI_MT_RANGE4G; \
flags |= PGI_MT_RANGE16M; \
} else { \
flags |= PGI_MT_RANGE0; \
} \
}
/*
* set the mtype range
* - kmem requests needs to be below 4g if restricted_kmemalloc is set.
* - for non kmem requests, set range to above 4g if the amount of memory
* below 4g runs low.
*/
flags |= PGI_MT_RANGE16M; \
} else { \
flags |= PGI_MT_RANGE0; \
} \
} else { \
if (RESTRICT4G_ALLOC) { \
/* here only for > 4g systems */ \
flags |= PGI_MT_RANGE4G; \
flags)) { \
flags |= PGI_MT_RANGE16M; \
} else { \
flags |= PGI_MT_RANGE0; \
} \
} \
}
#endif /* __i386 */
/*
* macros to loop through the mtype range (page_get_mnode_{free,cache,any}list,
* and page_get_contig_pages)
*
* MTYPE_START sets the initial mtype. -1 if the mtype range specified does
* not contain mnode.
*
* MTYPE_NEXT sets the next mtype. -1 if there are no more valid
* mtype in the range.
*/
if (flags & PGI_MT_RANGE) { \
} else { \
mtype = -1; \
} \
}
/* mtype init for page_get_replacement_page */
flags |= PGI_MT_RANGE16M; \
} else { \
flags |= PGI_MT_RANGE0; \
} \
}
#ifdef DEBUG
#else
#endif
#define FULL_REGION_CNT(rg_szc) \
/* Return the leader for this mapping size */
/* Return the root page for this page based on p_szc */
/*
* The counter base must be per page_counter element to prevent
* races when re-indexing, and the base page size element should
* be aligned on a boundary of the given region size.
*
* We also round up the number of pages spanned by the counters
* for a given region to PC_BASE_ALIGN in certain situations to simplify
* the coding for some non-performance critical routines.
*/
/*
* cpu/mmu-dependent vm variables
*/
extern uint_t mmu_page_sizes;
extern uint_t mmu_exported_page_sizes;
/* For x86, userszc is the same as the kernel's szc */
/*
* for hw_page_map_t, sized to hold the ratio of large page to base
* pagesize (1024 max)
*/
typedef short hpmctr_t;
/*
* get the setsize of the current cpu - assume homogenous for x86
*/
#define L2CACHE_ALIGN l2cache_linesz
#define L2CACHE_ALIGN_MAX 64
#define CPUSETSIZE() \
/*
* Return the log2(pagesize(szc) / MMU_PAGESIZE) --- or the shift count
* for the number of base pages in this pagesize
*/
/*
* Internal PG_ flags.
*/
/*
* PGI range flags - should not overlap PGI flags
*/
/*
* hash as and addr to get a bin.
*/
/*
* cpu private vm data - accessed thru CPU->cpu_vm_data
* vc_pnum_memseg: tracks last memseg visited in page_numtopp_nolock()
* vc_pnext_memseg: tracks last memseg visited in page_nextn()
* vc_kmptr: orignal unaligned kmem pointer for this vm_cpu_data_t
* vc_kmsize: orignal kmem size for this vm_cpu_data_t
*/
typedef struct {
struct memseg *vc_pnum_memseg;
struct memseg *vc_pnext_memseg;
void *vc_kmptr;
/* allocation size to ensure vm_cpu_data_t resides in its own cache line */
#define VM_CPU_DATA_PADSIZE \
/* for boot cpu before kmem is initialized */
extern char vm_cpu_data0[];
/*
* When a bin is empty, and we can't satisfy a color request correctly,
* we scan. If we assume that the programs have reasonable spatial
* behavior, then it will not be a good idea to use the adjacent color.
* Using the adjacent color would result in virtually adjacent addresses
* mapping into the same spot in the cache. So, if we stumble across
* an empty bin, skip a bunch before looking. After the first skip,
* then just look one bin at a time so we don't miss our cache on
* every look. Be sure to check every bin. Page_create() will panic
* if we miss a page.
*
* This also explains the `<=' in the for loops in both page_get_freelist()
* and page_get_cachelist(). Since we checked the target bin, skipped
* a bunch, then continued one a time, we wind up checking the target bin
* twice to make sure we get all of them bins.
*/
#define BIN_STEP 19
#ifdef VM_STATS
struct vmm_vmstats_str {
};
extern struct vmm_vmstats_str vmm_vmstats;
#endif /* VM_STATS */
extern size_t page_ctrs_sz(void);
extern void page_ctr_sub(int, int, page_t *, int);
#ifdef __cplusplus
}
#endif
#endif /* _VM_DEP_H */