⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hash_utils_64.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * PowerPC64 port by Mike Corrigan and Dave Engebretsen *   {mikejc|engebret}@us.ibm.com * *    Copyright (c) 2000 Mike Corrigan <mikejc@us.ibm.com> * * SMP scalability work: *    Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM *  *    Module name: htab.c * *    Description: *      PowerPC Hashed Page Table functions * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#undef DEBUG#undef DEBUG_LOW#include <linux/config.h>#include <linux/spinlock.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/sysctl.h>#include <linux/ctype.h>#include <linux/cache.h>#include <linux/init.h>#include <linux/signal.h>#include <asm/processor.h>#include <asm/pgtable.h>#include <asm/mmu.h>#include <asm/mmu_context.h>#include <asm/page.h>#include <asm/types.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/machdep.h>#include <asm/lmb.h>#include <asm/abs_addr.h>#include <asm/tlbflush.h>#include <asm/io.h>#include <asm/eeh.h>#include <asm/tlb.h>#include <asm/cacheflush.h>#include <asm/cputable.h>#include <asm/abs_addr.h>#include <asm/sections.h>#ifdef DEBUG#define DBG(fmt...) udbg_printf(fmt)#else#define DBG(fmt...)#endif#ifdef DEBUG_LOW#define DBG_LOW(fmt...) udbg_printf(fmt)#else#define DBG_LOW(fmt...)#endif#define KB (1024)#define MB (1024*KB)/* * Note:  pte   --> Linux PTE *        HPTE  --> PowerPC Hashed Page Table Entry * * Execution context: *   htab_initialize is called with the MMU off (of course), but *   the kernel has been copied down to zero so it can directly *   reference global data.  At this point it is very difficult *   to print debug info. * */#ifdef CONFIG_U3_DARTextern unsigned long dart_tablebase;#endif /* CONFIG_U3_DART */static unsigned long _SDR1;struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];hpte_t *htab_address;unsigned long htab_hash_mask;int mmu_linear_psize = MMU_PAGE_4K;int mmu_virtual_psize = MMU_PAGE_4K;#ifdef CONFIG_HUGETLB_PAGEint mmu_huge_psize = MMU_PAGE_16M;unsigned int HPAGE_SHIFT;#endif/* There are definitions of page sizes arrays to be used when none * is provided by the firmware. *//* Pre-POWER4 CPUs (4k pages only) */struct mmu_psize_def mmu_psize_defaults_old[] = {	[MMU_PAGE_4K] = {		.shift	= 12,		.sllp	= 0,		.penc	= 0,		.avpnm	= 0,		.tlbiel = 0,	},};/* POWER4, GPUL, POWER5 * * Support for 16Mb large pages */struct mmu_psize_def mmu_psize_defaults_gp[] = {	[MMU_PAGE_4K] = {		.shift	= 12,		.sllp	= 0,		.penc	= 0,		.avpnm	= 0,		.tlbiel = 1,	},	[MMU_PAGE_16M] = {		.shift	= 24,		.sllp	= SLB_VSID_L,		.penc	= 0,		.avpnm	= 0x1UL,		.tlbiel = 0,	},};int htab_bolt_mapping(unsigned long vstart, unsigned long vend,		      unsigned long pstart, unsigned long mode, int psize){	unsigned long vaddr, paddr;	unsigned int step, shift;	unsigned long tmp_mode;	int ret = 0;	shift = mmu_psize_defs[psize].shift;	step = 1 << shift;	for (vaddr = vstart, paddr = pstart; vaddr < vend;	     vaddr += step, paddr += step) {		unsigned long vpn, hash, hpteg;		unsigned long vsid = get_kernel_vsid(vaddr);		unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);		vpn = va >> shift;		tmp_mode = mode;				/* Make non-kernel text non-executable */		if (!in_kernel_text(vaddr))			tmp_mode = mode | HPTE_R_N;		hash = hpt_hash(va, shift);		hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);		/* The crap below can be cleaned once ppd_md.probe() can		 * set up the hash callbacks, thus we can just used the		 * normal insert callback here.		 */#ifdef CONFIG_PPC_ISERIES		if (_machine == PLATFORM_ISERIES_LPAR)			ret = iSeries_hpte_insert(hpteg, va,						  virt_to_abs(paddr),						  tmp_mode,						  HPTE_V_BOLTED,						  psize);		else#endif#ifdef CONFIG_PPC_PSERIES		if (_machine & PLATFORM_LPAR)			ret = pSeries_lpar_hpte_insert(hpteg, va,						       virt_to_abs(paddr),						       tmp_mode,						       HPTE_V_BOLTED,						       psize);		else#endif#ifdef CONFIG_PPC_MULTIPLATFORM			ret = native_hpte_insert(hpteg, va,						 virt_to_abs(paddr),						 tmp_mode, HPTE_V_BOLTED,						 psize);#endif		if (ret < 0)			break;	}	return ret < 0 ? ret : 0;}static int __init htab_dt_scan_page_sizes(unsigned long node,					  const char *uname, int depth,					  void *data){	char *type = of_get_flat_dt_prop(node, "device_type", NULL);	u32 *prop;	unsigned long size = 0;	/* We are scanning "cpu" nodes only */	if (type == NULL || strcmp(type, "cpu") != 0)		return 0;	prop = (u32 *)of_get_flat_dt_prop(node,					  "ibm,segment-page-sizes", &size);	if (prop != NULL) {		DBG("Page sizes from device-tree:\n");		size /= 4;		cur_cpu_spec->cpu_features &= ~(CPU_FTR_16M_PAGE);		while(size > 0) {			unsigned int shift = prop[0];			unsigned int slbenc = prop[1];			unsigned int lpnum = prop[2];			unsigned int lpenc = 0;			struct mmu_psize_def *def;			int idx = -1;			size -= 3; prop += 3;			while(size > 0 && lpnum) {				if (prop[0] == shift)					lpenc = prop[1];				prop += 2; size -= 2;				lpnum--;			}			switch(shift) {			case 0xc:				idx = MMU_PAGE_4K;				break;			case 0x10:				idx = MMU_PAGE_64K;				break;			case 0x14:				idx = MMU_PAGE_1M;				break;			case 0x18:				idx = MMU_PAGE_16M;				cur_cpu_spec->cpu_features |= CPU_FTR_16M_PAGE;				break;			case 0x22:				idx = MMU_PAGE_16G;				break;			}			if (idx < 0)				continue;			def = &mmu_psize_defs[idx];			def->shift = shift;			if (shift <= 23)				def->avpnm = 0;			else				def->avpnm = (1 << (shift - 23)) - 1;			def->sllp = slbenc;			def->penc = lpenc;			/* We don't know for sure what's up with tlbiel, so			 * for now we only set it for 4K and 64K pages			 */			if (idx == MMU_PAGE_4K || idx == MMU_PAGE_64K)				def->tlbiel = 1;			else				def->tlbiel = 0;			DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, "			    "tlbiel=%d, penc=%d\n",			    idx, shift, def->sllp, def->avpnm, def->tlbiel,			    def->penc);		}		return 1;	}	return 0;}static void __init htab_init_page_sizes(void){	int rc;	/* Default to 4K pages only */	memcpy(mmu_psize_defs, mmu_psize_defaults_old,	       sizeof(mmu_psize_defaults_old));	/*	 * Try to find the available page sizes in the device-tree	 */	rc = of_scan_flat_dt(htab_dt_scan_page_sizes, NULL);	if (rc != 0)  /* Found */		goto found;	/*	 * Not in the device-tree, let's fallback on known size	 * list for 16M capable GP & GR	 */	if ((_machine != PLATFORM_ISERIES_LPAR) &&	    cpu_has_feature(CPU_FTR_16M_PAGE))		memcpy(mmu_psize_defs, mmu_psize_defaults_gp,		       sizeof(mmu_psize_defaults_gp)); found:	/*	 * Pick a size for the linear mapping. Currently, we only support	 * 16M, 1M and 4K which is the default	 */	if (mmu_psize_defs[MMU_PAGE_16M].shift)		mmu_linear_psize = MMU_PAGE_16M;	else if (mmu_psize_defs[MMU_PAGE_1M].shift)		mmu_linear_psize = MMU_PAGE_1M;	/*	 * Pick a size for the ordinary pages. Default is 4K, we support	 * 64K if cache inhibited large pages are supported by the	 * processor	 */#ifdef CONFIG_PPC_64K_PAGES	if (mmu_psize_defs[MMU_PAGE_64K].shift &&	    cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))		mmu_virtual_psize = MMU_PAGE_64K;#endif	printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n",	       mmu_psize_defs[mmu_linear_psize].shift,	       mmu_psize_defs[mmu_virtual_psize].shift);#ifdef CONFIG_HUGETLB_PAGE	/* Init large page size. Currently, we pick 16M or 1M depending	 * on what is available	 */	if (mmu_psize_defs[MMU_PAGE_16M].shift)		mmu_huge_psize = MMU_PAGE_16M;	/* With 4k/4level pagetables, we can't (for now) cope with a	 * huge page size < PMD_SIZE */	else if (mmu_psize_defs[MMU_PAGE_1M].shift)		mmu_huge_psize = MMU_PAGE_1M;	/* Calculate HPAGE_SHIFT and sanity check it */	if (mmu_psize_defs[mmu_huge_psize].shift > MIN_HUGEPTE_SHIFT &&	    mmu_psize_defs[mmu_huge_psize].shift < SID_SHIFT)		HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift;	else		HPAGE_SHIFT = 0; /* No huge pages dude ! */#endif /* CONFIG_HUGETLB_PAGE */}static int __init htab_dt_scan_pftsize(unsigned long node,				       const char *uname, int depth,				       void *data){	char *type = of_get_flat_dt_prop(node, "device_type", NULL);	u32 *prop;	/* We are scanning "cpu" nodes only */	if (type == NULL || strcmp(type, "cpu") != 0)		return 0;	prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL);	if (prop != NULL) {		/* pft_size[0] is the NUMA CEC cookie */		ppc64_pft_size = prop[1];		return 1;	}	return 0;}static unsigned long __init htab_get_table_size(void){	unsigned long mem_size, rnd_mem_size, pteg_count;	/* If hash size isn't already provided by the platform, we try to	 * retreive it from the device-tree. If it's not there neither, we	 * calculate it now based on the total RAM size	 */	if (ppc64_pft_size == 0)		of_scan_flat_dt(htab_dt_scan_pftsize, NULL);	if (ppc64_pft_size)		return 1UL << ppc64_pft_size;	/* round mem_size up to next power of 2 */	mem_size = lmb_phys_mem_size();	rnd_mem_size = 1UL << __ilog2(mem_size);	if (rnd_mem_size < mem_size)		rnd_mem_size <<= 1;	/* # pages / 2 */	pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11);	return pteg_count << 7;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -