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

📄 htab.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 3 页
字号:
	pgdir = mm->pgd;	if (pgdir == NULL) return 1;	/*	 * Lock the Linux page table to prevent mmap and kswapd	 * from modifying entries while we search and update	 */	spin_lock(&mm->page_table_lock);	ptep = find_linux_pte(pgdir, ea);	/*	 * If no pte found or not present, send the problem up to	 * do_page_fault	 */	if (ptep && pte_present(*ptep)) {		ret = __hash_page(ea, access, vsid, ptep);	} else {			/* If no pte, send the problem up to do_page_fault */		ret = 1;	}	spin_unlock(&mm->page_table_lock);	return ret;}void flush_hash_page(unsigned long context, unsigned long ea, pte_t *ptep){	unsigned long vsid, vpn, va, hash, secondary, slot, flags;	unsigned long large = 0, local = 0;	pte_t pte;	if ((ea >= USER_START) && (ea <= USER_END))		vsid = get_vsid(context, ea);	else		vsid = get_kernel_vsid(ea);	va = (vsid << 28) | (ea & 0x0fffffff);	if (large)		vpn = va >> LARGE_PAGE_SHIFT;	else		vpn = va >> PAGE_SHIFT;	hash = hpt_hash(vpn, large);	spin_lock_irqsave( &hash_table_lock, flags);	pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0));	secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;	if (secondary) hash = ~hash;	slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;	slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;		if (pte_val(pte) & _PAGE_HASHPTE) {		ppc_md.hpte_invalidate(slot, secondary, va, large, local);	}	spin_unlock_irqrestore( &hash_table_lock, flags );}long plpar_pte_enter(unsigned long flags,		     unsigned long ptex,		     unsigned long new_pteh, unsigned long new_ptel,		     unsigned long *old_pteh_ret, unsigned long *old_ptel_ret){	unsigned long dummy, ret;	ret = plpar_hcall(H_ENTER, flags, ptex, new_pteh, new_ptel,			   old_pteh_ret, old_ptel_ret, &dummy);	return(ret);}long plpar_pte_remove(unsigned long flags,		      unsigned long ptex,		      unsigned long avpn,		      unsigned long *old_pteh_ret, unsigned long *old_ptel_ret){	unsigned long dummy;	return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0,			   old_pteh_ret, old_ptel_ret, &dummy);}long plpar_pte_read(unsigned long flags,		    unsigned long ptex,		    unsigned long *old_pteh_ret, unsigned long *old_ptel_ret){	unsigned long dummy;	return plpar_hcall(H_READ, flags, ptex, 0, 0,			   old_pteh_ret, old_ptel_ret, &dummy);}long plpar_pte_protect(unsigned long flags,		       unsigned long ptex,		       unsigned long avpn){	return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);}static __inline__ void set_pp_bit(unsigned long pp, HPTE *addr){	unsigned long old;	unsigned long *p = &addr->dw1.dword1;	__asm__ __volatile__(        "1:	ldarx	%0,0,%3\n\                rldimi  %0,%2,0,62\n\                stdcx.	%0,0,%3\n\            	bne	1b"        : "=&r" (old), "=m" (*p)        : "r" (pp), "r" (p), "m" (*p)        : "cc");}/* * Functions used to retrieve word 0 of a given page table entry. * * Input : slot : PTE index within the page table of the entry to retrieve  * Output: Contents of word 0 of the specified entry */static unsigned long rpa_lpar_hpte_getword0(unsigned long slot){	unsigned long dword0;	unsigned long lpar_rc;	unsigned long dummy_word1;	unsigned long flags;	/* Read 1 pte at a time                        */	/* Do not need RPN to logical page translation */	/* No cross CEC PFT access                     */	flags = 0;		lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);	if (lpar_rc != H_Success)		panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc);	return dword0;}unsigned long iSeries_hpte_getword0(unsigned long slot){	unsigned long dword0;	HPTE hpte;	HvCallHpt_get(&hpte, slot);	dword0 = hpte.dw0.dword0;	return dword0;}/* * Functions used to find the PTE for a particular virtual address.  * Only used during boot when bolting pages. * * Input : vpn      : virtual page number * Output: PTE index within the page table of the entry *         -1 on failure */static long hpte_find(unsigned long vpn){	HPTE *hptep;	unsigned long hash;	unsigned long i, j;	long slot;	Hpte_dword0 dw0;	hash = hpt_hash(vpn, 0);	for (j = 0; j < 2; j++) {		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;		for (i = 0; i < HPTES_PER_GROUP; i++) {			hptep = htab_data.htab + slot;			dw0 = hptep->dw0.dw0;			if ((dw0.avpn == (vpn >> 11)) && dw0.v &&			    (dw0.h == j)) {				/* HPTE matches */				if (j)					slot = -slot;				return slot;			}			++slot;		}		hash = ~hash;	}	return -1;}static long rpa_lpar_hpte_find(unsigned long vpn){	unsigned long hash;	unsigned long i, j;	long slot;	union {		unsigned long dword0;		Hpte_dword0 dw0;	} hpte_dw0;	Hpte_dword0 dw0;	hash = hpt_hash(vpn, 0);	for (j = 0; j < 2; j++) {		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;		for (i = 0; i < HPTES_PER_GROUP; i++) {			hpte_dw0.dword0 = rpa_lpar_hpte_getword0(slot);			dw0 = hpte_dw0.dw0;			if ((dw0.avpn == (vpn >> 11)) && dw0.v &&			    (dw0.h == j)) {				/* HPTE matches */				if (j)					slot = -slot;				return slot;			}			++slot;		}		hash = ~hash;	}	return -1;} static long iSeries_hpte_find(unsigned long vpn){	HPTE hpte;	long slot;	/*	 * The HvCallHpt_findValid interface is as follows:	 * 0xffffffffffffffff : No entry found.	 * 0x00000000xxxxxxxx : Entry found in primary group, slot x	 * 0x80000000xxxxxxxx : Entry found in secondary group, slot x	 */	slot = HvCallHpt_findValid(&hpte, vpn); 	if (hpte.dw0.dw0.v) {		if (slot < 0) {			slot &= 0x7fffffffffffffff;			slot = -slot;		}	} else {		slot = -1;	}	return slot;}/* * Functions used to invalidate a page table entry from the page table * and tlb. * * Input : slot  : PTE index within the page table of the entry to invalidated *         va    : Virtual address of the entry being invalidated *         large : 1 = large page (16M) *         local : 1 = Use tlbiel to only invalidate the local tlb  */static void hpte_invalidate(unsigned long slot, 			    unsigned long secondary,			    unsigned long va,			    int large, int local){	HPTE *hptep = htab_data.htab + slot;	Hpte_dword0 dw0;	unsigned long vpn, avpn;	unsigned long flags;	if (large)		vpn = va >> LARGE_PAGE_SHIFT;	else		vpn = va >> PAGE_SHIFT;	avpn = vpn >> 11;	dw0 = hptep->dw0.dw0;	/*	 * Do not remove bolted entries.  Alternatively, we could check	 * the AVPN, hash group, and valid bits.  By doing it this way,	 * it is common with the pSeries LPAR optimal path.	 */	if (dw0.bolted) return;	/* Invalidate the hpte. */	hptep->dw0.dword0 = 0;	/* Invalidate the tlb */	spin_lock_irqsave(&pSeries_tlbie_lock, flags);	_tlbie(va, large);	spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);}static void rpa_lpar_hpte_invalidate(unsigned long slot, 				     unsigned long secondary,				     unsigned long va,				     int large, int local){	unsigned long lpar_rc;	unsigned long dummy1, dummy2;	/* 	 * Don't remove a bolted entry.  This case can occur when we bolt	 * pages dynamically after initial boot.	 */	lpar_rc = plpar_pte_remove(H_ANDCOND, slot, (0x1UL << 4), 				   &dummy1, &dummy2);	if (lpar_rc != H_Success)		panic("Bad return code from invalidate rc = %lx\n", lpar_rc);}static void iSeries_hpte_invalidate(unsigned long slot, 				    unsigned long secondary,				    unsigned long va,				    int large, int local){	HPTE lhpte;	unsigned long vpn, avpn;	if (large)		vpn = va >> LARGE_PAGE_SHIFT;	else		vpn = va >> PAGE_SHIFT;	avpn = vpn >> 11;	lhpte.dw0.dword0 = iSeries_hpte_getword0(slot);		if ((lhpte.dw0.dw0.avpn == avpn) && 	    (lhpte.dw0.dw0.v) &&	    (lhpte.dw0.dw0.h == secondary)) {		HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0);	}}/* * Functions used to update page protection bits. * * Input : slot  : PTE index within the page table of the entry to update *         newpp : new page protection bits *         va    : Virtual address of the entry being updated *         large : 1 = large page (16M) * Output: 0 on success, -1 on failure */static long hpte_updatepp(unsigned long slot, 			  unsigned long secondary,			  unsigned long newpp,			  unsigned long va, int large){	HPTE *hptep = htab_data.htab + slot;	Hpte_dword0 dw0;	Hpte_dword1 dw1;	unsigned long vpn, avpn;	unsigned long flags;	if (large)		vpn = va >> LARGE_PAGE_SHIFT;	else		vpn = va >> PAGE_SHIFT;	avpn = vpn >> 11;	dw0 = hptep->dw0.dw0;	if ((dw0.avpn == avpn) && 	    (dw0.v) && (dw0.h == secondary)) {		/* Turn off valid bit in HPTE */		dw0.v = 0;		hptep->dw0.dw0 = dw0;				/* Ensure it is out of the tlb too */		spin_lock_irqsave(&pSeries_tlbie_lock, flags);		_tlbie(va, large);		spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);				/* Insert the new pp bits into the HPTE */		dw1 = hptep->dw1.dw1;		dw1.pp = newpp;		hptep->dw1.dw1 = dw1;				/* Ensure it is visible before validating */		__asm__ __volatile__ ("eieio" : : : "memory");				/* Turn the valid bit back on in HPTE */		dw0.v = 1;		hptep->dw0.dw0 = dw0;				__asm__ __volatile__ ("ptesync" : : : "memory");				return 0;	}	return -1;}static long rpa_lpar_hpte_updatepp(unsigned long slot, 				   unsigned long secondary,				   unsigned long newpp,				   unsigned long va, int large){	unsigned long lpar_rc;	unsigned long flags = (newpp & 7);	unsigned long avpn = va >> 23;	HPTE hpte;	lpar_rc = plpar_pte_read(0, slot, &hpte.dw0.dword0, &hpte.dw1.dword1);	if ((hpte.dw0.dw0.avpn == avpn) &&	    (hpte.dw0.dw0.v) && 	    (hpte.dw0.dw0.h == secondary)) {		lpar_rc = plpar_pte_protect(flags, slot, 0);		if (lpar_rc != H_Success)			panic("bad return code from pte protect rc = %lx\n", 			      lpar_rc);		return 0;	}	return -1;}static long iSeries_hpte_updatepp(unsigned long slot, 				  unsigned long secondary,				  unsigned long newpp, 				  unsigned long va, int large){	unsigned long vpn, avpn;	HPTE hpte;	if (large)		vpn = va >> LARGE_PAGE_SHIFT;	else		vpn = va >> PAGE_SHIFT;	avpn = vpn >> 11;	HvCallHpt_get(&hpte, slot);	if ((hpte.dw0.dw0.avpn == avpn) && 	    (hpte.dw0.dw0.v) &&	    (hpte.dw0.dw0.h == secondary)) {		HvCallHpt_setPp(slot, newpp);		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;

⌨️ 快捷键说明

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