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

📄 htab.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		return 0;	}	return -1;}/* * Functions used to update the page protection bits. Intended to be used  * to create guard pages for kernel data structures on pages which are bolted * in the HPT. Assumes pages being operated on will not be stolen. * Does not work on large pages. No need to lock here because we are the  * only user. *  * Input : newpp : page protection flags *         ea    : effective kernel address to bolt. */static void hpte_updateboltedpp(unsigned long newpp, unsigned long ea){	unsigned long vsid, va, vpn, flags;	long slot;	HPTE *hptep;	vsid = get_kernel_vsid(ea);	va = (vsid << 28) | (ea & 0x0fffffff);	vpn = va >> PAGE_SHIFT;	slot = hpte_find(vpn);	if (slot == -1)		panic("could not find page to bolt\n");	hptep = htab_data.htab + slot;	set_pp_bit(newpp, hptep);	/* Ensure it is out of the tlb too */	spin_lock_irqsave(&pSeries_tlbie_lock, flags);	_tlbie(va, 0);	spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);}static void rpa_lpar_hpte_updateboltedpp(unsigned long newpp, unsigned long ea){	unsigned long lpar_rc;	unsigned long vsid, va, vpn, flags;	long slot;	vsid = get_kernel_vsid(ea);	va = (vsid << 28) | (ea & 0x0fffffff);	vpn = va >> PAGE_SHIFT;	slot = rpa_lpar_hpte_find(vpn);	if (slot == -1)		panic("updateboltedpp: Could not find page to bolt\n");	flags = newpp & 3;	lpar_rc = plpar_pte_protect(flags, slot, 0);	if (lpar_rc != H_Success)		panic("Bad return code from pte bolted protect rc = %lx\n",		      lpar_rc); }void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea){	unsigned long vsid,va,vpn;	long slot;	vsid = get_kernel_vsid( ea );	va = ( vsid << 28 ) | ( ea & 0x0fffffff );	vpn = va >> PAGE_SHIFT;	slot = iSeries_hpte_find(vpn); 	if (slot == -1)		panic("updateboltedpp: Could not find page to bolt\n");	HvCallHpt_setPp(slot, newpp);}/* * Functions used to insert new hardware page table entries. * Will castout non-bolted entries as necessary using a random * algorithm. * * Input : vpn      : virtual page number *         prpn     : real page number in absolute space *         hpteflags: page protection flags *         bolted   : 1 = bolt the page *         large    : 1 = large page (16M) * Output: hsss, where h = hash group, sss = slot within that group */static long hpte_insert(unsigned long vpn, unsigned long prpn,			unsigned long hpteflags, int bolted, int large){	HPTE *hptep;	Hpte_dword0 dw0;	HPTE lhpte;	int i, secondary;	unsigned long hash = hpt_hash(vpn, 0);	unsigned long avpn = vpn >> 11;	unsigned long arpn = physRpn_to_absRpn(prpn);	unsigned long hpte_group;repeat:	secondary = 0;	hpte_group = ((hash & htab_data.htab_hash_mask) *		      HPTES_PER_GROUP) & ~0x7UL;	hptep = htab_data.htab + hpte_group;	for (i = 0; i < HPTES_PER_GROUP; i++) {		dw0 = hptep->dw0.dw0;		if (!dw0.v) {			/* retry with lock held */			dw0 = hptep->dw0.dw0;			if (!dw0.v)				break;		}		hptep++;	}	if (i == HPTES_PER_GROUP) {		secondary = 1;		hpte_group = ((~hash & htab_data.htab_hash_mask) *			      HPTES_PER_GROUP) & ~0x7UL;		hptep = htab_data.htab + hpte_group;		for (i = 0; i < HPTES_PER_GROUP; i++) {			dw0 = hptep->dw0.dw0;			if (!dw0.v) {				/* retry with lock held */				dw0 = hptep->dw0.dw0;				if (!dw0.v)					break;			}			hptep++;		}		if (i == HPTES_PER_GROUP) {			if (mftb() & 0x1)				hpte_group=((hash & htab_data.htab_hash_mask)* 					    HPTES_PER_GROUP) & ~0x7UL;						hpte_remove(hpte_group);			goto repeat;		}	}	lhpte.dw1.dword1      = 0;	lhpte.dw1.dw1.rpn     = arpn;	lhpte.dw1.flags.flags = hpteflags;	lhpte.dw0.dword0      = 0;	lhpte.dw0.dw0.avpn    = avpn;	lhpte.dw0.dw0.h       = secondary;	lhpte.dw0.dw0.bolted  = bolted;	lhpte.dw0.dw0.v       = 1;	if (large) lhpte.dw0.dw0.l = 1;	hptep->dw1.dword1 = lhpte.dw1.dword1;	/* Guarantee the second dword is visible before the valid bit */	__asm__ __volatile__ ("eieio" : : : "memory");	/*	 * Now set the first dword including the valid bit	 * NOTE: this also unlocks the hpte	 */	hptep->dw0.dword0 = lhpte.dw0.dword0;	__asm__ __volatile__ ("ptesync" : : : "memory");	return ((secondary << 3) | i);}static long rpa_lpar_hpte_insert(unsigned long vpn, unsigned long prpn,				 unsigned long hpteflags,				 int bolted, int large){	/* XXX fix for large page */	unsigned long lpar_rc;	unsigned long flags;	unsigned long slot;	HPTE lhpte;	int secondary;	unsigned long hash = hpt_hash(vpn, 0);	unsigned long avpn = vpn >> 11;	unsigned long arpn = physRpn_to_absRpn(prpn);	unsigned long hpte_group;	/* Fill in the local HPTE with absolute rpn, avpn and flags */	lhpte.dw1.dword1      = 0;	lhpte.dw1.dw1.rpn     = arpn;	lhpte.dw1.flags.flags = hpteflags;	lhpte.dw0.dword0      = 0;	lhpte.dw0.dw0.avpn    = avpn;	lhpte.dw0.dw0.bolted  = bolted;	lhpte.dw0.dw0.v       = 1;	if (large) lhpte.dw0.dw0.l = 1;	/* Now fill in the actual HPTE */	/* Set CEC cookie to 0         */	/* Large page = 0              */	/* Zero page = 0               */	/* I-cache Invalidate = 0      */	/* I-cache synchronize = 0     */	/* Exact = 0                   */	flags = 0;	/* XXX why is this here? - Anton */	/*   -- Because at one point we hit a case where non cachable	 *      pages where marked coherent & this is rejected by the HV.	 *      Perhaps it is no longer an issue ... DRENG.	 */ 	if (hpteflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))		lhpte.dw1.flags.flags &= ~_PAGE_COHERENT;repeat:	secondary = 0;	lhpte.dw0.dw0.h = secondary;	hpte_group = ((hash & htab_data.htab_hash_mask) *		      HPTES_PER_GROUP) & ~0x7UL;	__asm__ __volatile__ (		H_ENTER_r3		"mr    4, %2\n"                "mr    5, %3\n"                "mr    6, %4\n"                "mr    7, %5\n"		HVSC                "mr    %0, 3\n"                "mr    %1, 4\n"		: "=r" (lpar_rc), "=r" (slot)		: "r" (flags), "r" (hpte_group), "r" (lhpte.dw0.dword0),		"r" (lhpte.dw1.dword1)		: "r0", "r3", "r4", "r5", "r6", "r7", 		  "r8", "r9", "r10", "r11", "r12", "cc");	if (lpar_rc == H_PTEG_Full) {		secondary = 1;		lhpte.dw0.dw0.h = secondary;		hpte_group = ((~hash & htab_data.htab_hash_mask) *			      HPTES_PER_GROUP) & ~0x7UL;		__asm__ __volatile__ (			      H_ENTER_r3			      "mr    4, %2\n"			      "mr    5, %3\n"			      "mr    6, %4\n"			      "mr    7, %5\n"			      HVSC			      "mr    %0, 3\n"			      "mr    %1, 4\n"			      : "=r" (lpar_rc), "=r" (slot)			      : "r" (flags), "r" (hpte_group), "r" (lhpte.dw0.dword0),			      "r" (lhpte.dw1.dword1)			      : "r0", "r3", "r4", "r5", "r6", "r7",			        "r8", "r9", "r10", "r11", "r12", "cc");		if (lpar_rc == H_PTEG_Full) {			if (mftb() & 0x1)				hpte_group=((hash & htab_data.htab_hash_mask)* 					    HPTES_PER_GROUP) & ~0x7UL;						rpa_lpar_hpte_remove(hpte_group);			goto repeat;		}	}	if (lpar_rc != H_Success)		panic("Bad return code from pte enter rc = %lx\n", lpar_rc);	return ((secondary << 3) | (slot & 0x7));}static long iSeries_hpte_insert(unsigned long vpn, unsigned long prpn,				unsigned long hpteflags,				int bolted, int large){	HPTE lhpte;	unsigned long hash, hpte_group;	unsigned long avpn = vpn >> 11;	unsigned long arpn = physRpn_to_absRpn( prpn );	int secondary = 0;	long slot;	hash = hpt_hash(vpn, 0);repeat:	slot = HvCallHpt_findValid(&lhpte, vpn);	if (lhpte.dw0.dw0.v) {		panic("select_hpte_slot found entry already valid\n");	}	if (slot == -1) { /* No available entry found in either group */		if (mftb() & 0x1) {			hpte_group=((hash & htab_data.htab_hash_mask)* 				    HPTES_PER_GROUP) & ~0x7UL;		} else {			hpte_group=((~hash & htab_data.htab_hash_mask)* 				    HPTES_PER_GROUP) & ~0x7UL;		}		hash = hpt_hash(vpn, 0);		iSeries_hpte_remove(hpte_group);		goto repeat;	} else if (slot < 0) {		slot &= 0x7fffffffffffffff;		secondary = 1;	}	/* Create the HPTE */	lhpte.dw1.dword1      = 0;	lhpte.dw1.dw1.rpn     = arpn;	lhpte.dw1.flags.flags = hpteflags;	lhpte.dw0.dword0     = 0;	lhpte.dw0.dw0.avpn   = avpn;	lhpte.dw0.dw0.h      = secondary;	lhpte.dw0.dw0.bolted = bolted;	lhpte.dw0.dw0.v      = 1;	/* Now fill in the actual HPTE */	HvCallHpt_addValidate(slot, secondary, (HPTE *)&lhpte);	return ((secondary << 3) | (slot & 0x7));}/* * Functions used to remove hardware page table entries. * * Input : hpte_group: PTE index of the first entry in a group * Output: offset within the group of the entry removed or *         -1 on failure */static long hpte_remove(unsigned long hpte_group){	HPTE *hptep;	Hpte_dword0 dw0;	int i;	int slot_offset;	unsigned long vsid, group, pi, pi_high;	unsigned long slot;	unsigned long flags;	int large;	unsigned long va;	/* pick a random slot to start at */	slot_offset = mftb() & 0x7;	for (i = 0; i < HPTES_PER_GROUP; i++) {		hptep = htab_data.htab + hpte_group + slot_offset;		dw0 = hptep->dw0.dw0;		if (dw0.v && !dw0.bolted) {			/* retry with lock held */			dw0 = hptep->dw0.dw0;			if (dw0.v && !dw0.bolted)				break;		}		slot_offset++;		slot_offset &= 0x7;	}	if (i == HPTES_PER_GROUP)		return -1;	large = dw0.l;	/* Invalidate the hpte. NOTE: this also unlocks it */	hptep->dw0.dword0 = 0;	/* Invalidate the tlb */	vsid = dw0.avpn >> 5;	slot = hptep - htab_data.htab;	group = slot >> 3;	if (dw0.h)		group = ~group;	pi = (vsid ^ group) & 0x7ff;	pi_high = (dw0.avpn & 0x1f) << 11;	pi |= pi_high;	if (large)		va = pi << LARGE_PAGE_SHIFT;	else		va = pi << PAGE_SHIFT;	spin_lock_irqsave(&pSeries_tlbie_lock, flags);	_tlbie(va, large);	spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);	return i;}static long rpa_lpar_hpte_remove(unsigned long hpte_group){	unsigned long slot_offset;	unsigned long lpar_rc;	int i;	unsigned long dummy1, dummy2;	/* pick a random slot to start at */	slot_offset = mftb() & 0x7;	for (i = 0; i < HPTES_PER_GROUP; i++) {		/* Don't remove a bolted entry */		lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,					   (0x1UL << 4), &dummy1, &dummy2);		if (lpar_rc == H_Success)			return i;		if (lpar_rc != H_Not_Found)			panic("Bad return code from pte remove rc = %lx\n",			      lpar_rc);		slot_offset++;		slot_offset &= 0x7;	}	return -1;}static long iSeries_hpte_remove(unsigned long hpte_group){	unsigned long slot_offset;	int i;	HPTE lhpte;	/* Pick a random slot to start at */	slot_offset = mftb() & 0x7;	for (i = 0; i < HPTES_PER_GROUP; i++) {		lhpte.dw0.dword0 = 			iSeries_hpte_getword0(hpte_group + slot_offset);		if (!lhpte.dw0.dw0.bolted) {			HvCallHpt_invalidateSetSwBitsGet(hpte_group + 							 slot_offset, 0, 0);			return i;		}		slot_offset++;		slot_offset &= 0x7;	}	return -1;}void hpte_init_pSeries(void){	ppc_md.hpte_invalidate     = hpte_invalidate;	ppc_md.hpte_updatepp       = hpte_updatepp;	ppc_md.hpte_updateboltedpp = hpte_updateboltedpp;	ppc_md.hpte_insert	   = hpte_insert;	ppc_md.hpte_remove	   = hpte_remove;}void pSeries_lpar_mm_init(void){	ppc_md.hpte_invalidate     = rpa_lpar_hpte_invalidate;	ppc_md.hpte_updatepp       = rpa_lpar_hpte_updatepp;	ppc_md.hpte_updateboltedpp = rpa_lpar_hpte_updateboltedpp;	ppc_md.hpte_insert         = rpa_lpar_hpte_insert;	ppc_md.hpte_remove         = rpa_lpar_hpte_remove;}void hpte_init_iSeries(void){	ppc_md.hpte_invalidate     = iSeries_hpte_invalidate;	ppc_md.hpte_updatepp       = iSeries_hpte_updatepp;	ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;	ppc_md.hpte_insert         = iSeries_hpte_insert;	ppc_md.hpte_remove         = iSeries_hpte_remove;}

⌨️ 快捷键说明

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