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

📄 htab.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	case VMALLOC_REGION_ID:		mm = &init_mm;		vsid = get_kernel_vsid( ea );		break;	case IO_UNMAPPED_REGION_ID:		udbg_printf("EEH Error ea = 0x%lx\n", ea); 		PPCDBG_ENTER_DEBUGGER();		panic("EEH Error ea = 0x%lx\n", ea);		break;	case KERNEL_REGION_ID:		/* As htab_initialize is now, we shouldn't ever get here since		 * we're bolting the entire 0xC0... region.		 */		udbg_printf("Little faulted on kernel address 0x%lx\n", ea); 		PPCDBG_ENTER_DEBUGGER();		panic("Little faulted on kernel address 0x%lx\n", ea);		break;	default:		/* Not a valid range, send the problem up to do_page_fault */		return 1;		break;	}	/* Search the Linux page table for a match with va */        va = ( vsid << 28 ) | ( ea & 0x0fffffff );	vpn = va >> PAGE_SHIFT;	pgdir = mm->pgd;	PPCDBG(PPCDBG_MM, "hash_page ea = 0x%16.16lx, va = 0x%16.16lx\n          current = 0x%16.16lx, access = %lx\n", ea, va, current, access);                 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, send the problem up to do_page_fault */	if ( ! ptep ) {	  spin_unlock( &mm->page_table_lock );	  return 1;	}		/* Acquire the hash table lock to guarantee that the linux	 * pte we fetch will not change	 */	spin_lock( &hash_table_lock );		old_pte = *ptep;		/* If the pte is not "present" (valid), send the problem	 * up to do_page_fault.	 */	if ( ! pte_present( old_pte ) ) {	  spin_unlock( &hash_table_lock );	  spin_unlock( &mm->page_table_lock );	  return 1;	}		/* At this point we have found a pte (which was present).	 * The spinlocks prevent this status from changing	 * The hash_table_lock prevents the _PAGE_HASHPTE status	 * from changing (RPN, DIRTY and ACCESSED too)	 * The page_table_lock prevents the pte from being 	 * invalidated or modified	 *//* At this point, we have a pte (old_pte) which can be used to build or update * an HPTE.   There are 5 cases: * * 1. There is a valid (present) pte with no associated HPTE (this is  *	the most common case) * 2. There is a valid (present) pte with an associated HPTE.  The *	current values of the pp bits in the HPTE prevent access because the *	user doesn't have appropriate access rights. * 3. There is a valid (present) pte with an associated HPTE.  The *	current values of the pp bits in the HPTE prevent access because we are *	doing software DIRTY bit management and the page is currently not DIRTY.  * 4. This is a Kernel address (0xC---) for which there is no page directory. *	There is an HPTE for this page, but the pp bits prevent access. *      Since we always set up kernel pages with R/W access for the kernel *	this case only comes about for users trying to access the kernel. *	This case is always an error and is not dealt with further here. * 5. This is a Kernel address (0xC---) for which there is no page directory. *	There is no HPTE for this page. * Check the user's access rights to the page.  If access should be prevented * then send the problem up to do_page_fault. */	access |= _PAGE_PRESENT;	if ( 0 == ( access & ~(pte_val(old_pte)) ) ) {		/*		 * Check if pte might have an hpte, but we have		 * no slot information		 */		if ( pte_val(old_pte) & _PAGE_HPTENOIX ) {			unsigned long slot;				pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;			slot = ppc_md.hpte_find( vpn );			if ( slot != -1 ) {				if ( slot < 0 ) {					pte_val(old_pte) |= _PAGE_SECONDARY;					slot = -slot;				}				pte_val(old_pte) |= ((slot << 12) & _PAGE_GROUP_IX) | _PAGE_HASHPTE;							}		}		/* User has appropriate access rights. */		new_pte = old_pte;		/* If the attempted access was a store */		if ( access & _PAGE_RW )			pte_val(new_pte) |= _PAGE_ACCESSED |				_PAGE_DIRTY;		else			pte_val(new_pte) |= _PAGE_ACCESSED;		/* Only cases 1, 3 and 5 still in play */		newpp = computeHptePP( pte_val(new_pte) );		/* Check if pte already has an hpte (case 3) */		if ( pte_val(old_pte) & _PAGE_HASHPTE ) {			/* There MIGHT be an HPTE for this pte */			unsigned long hash, slot, secondary;			/* Local copy of first doubleword of HPTE */			union {				unsigned long d;				Hpte_dword0   h;			} hpte_dw0;			hash = hpt_hash(vpn, 0);			secondary = (pte_val(old_pte) & _PAGE_SECONDARY) >> 15;			if ( secondary )				hash = ~hash;			slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;			slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;			/* If there is an HPTE for this page it is indexed by slot */			hpte_dw0.d = ppc_md.hpte_getword0( slot );			if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&			     (hpte_dw0.h.v) && 			     (hpte_dw0.h.h == secondary ) ){				/* HPTE matches */				ppc_md.hpte_updatepp( slot, newpp, va );				if ( !pte_same( old_pte, new_pte ) )					*ptep = new_pte;			}			else {				/* HPTE is not for this pte */				pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;			}		}		if ( !( pte_val(old_pte) & _PAGE_HASHPTE ) ) {			/* Cases 1 and 5 */			/* For these cases we need to create a new			 * HPTE and update the linux pte (for			 * case 1).  For case 5 there is no linux pte.			 *			 * Find an available HPTE slot 			 */			slot = ppc_md.hpte_selectslot( vpn );			/* If hpte_selectslot returns 0x8000000000000000 that means			 * that there was already an entry in the HPT even though			 * the linux PTE said there couldn't be. 			 */			/* Debug code */			if ( slot == 0x8000000000000000 ) {				unsigned long xold_pte = pte_val(old_pte);				unsigned long xnew_pte = pte_val(new_pte);								udbg_printf("hash_page: ptep    = 0x%016lx\n", (unsigned long)ptep );				udbg_printf("hash_page: old_pte = 0x%016lx\n", xold_pte );				udbg_printf("hash_page: new_pte = 0x%016lx\n", xnew_pte );				udbg_printf("hash_page: ea      = 0x%016lx\n", ea );				udbg_printf("hash_page: va      = 0x%016lx\n", va );				udbg_printf("hash_page: access  = 0x%016lx\n", access );							panic("hash_page: hpte already exists\n");			}			hash_ind = 0;			if ( slot < 0 ) {				slot = -slot;				hash_ind = 1;			}			/* Set the physical address */			prpn = pte_val(old_pte) >> PTE_SHIFT;						if ( ptep ) {				/* Update the linux pte with the HPTE slot */				pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;				pte_val(new_pte) |= hash_ind << 15;				pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;				pte_val(new_pte) |= _PAGE_HASHPTE;				/* No need to use ldarx/stdcx here because all				 * who might be updating the pte will hold the page_table_lock				 * or the hash_table_lock (we hold both)				 */				*ptep = new_pte;			}			/* copy appropriate flags from linux pte */			hpteflags = (pte_val(new_pte) & 0x1f8) | newpp;			/* Create the HPTE */			ppc_md.hpte_create_valid( slot, vpn, prpn, hash_ind, ptep, hpteflags, 0 ); 		}		/* Indicate success */		rc = 0;	}				spin_unlock( &hash_table_lock );	if (ptep)		spin_unlock( &mm->page_table_lock );	return rc;}void flush_hash_page( unsigned long context, unsigned long ea, pte_t *ptep ){	unsigned long vsid, vpn, va, hash, secondary, slot, flags;	/* Local copy of first doubleword of HPTE */	union {		unsigned long d;		Hpte_dword0   h;	} hpte_dw0;	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);	vpn = va >> PAGE_SHIFT;	hash = hpt_hash(vpn, 0);	spin_lock_irqsave( &hash_table_lock, flags);	pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0));	if ( pte_val(pte) & _PAGE_HASHPTE ) {		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 there is an HPTE for this page it is indexed by slot */		hpte_dw0.d = ppc_md.hpte_getword0( slot );		if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&		     (hpte_dw0.h.v) && 		     (hpte_dw0.h.h == secondary ) ){			/* HPTE matches */			ppc_md.hpte_invalidate( slot );			}		else {			unsigned k;			/* Temporarily lets check for the hpte in all possible slots */			for ( secondary = 0; secondary < 2; ++secondary ) {				hash = hpt_hash(vpn, 0);				if ( secondary )					hash = ~hash;				slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;				for ( k=0; k<8; ++k ) {					hpte_dw0.d = ppc_md.hpte_getword0( slot+k );					if ( ( hpte_dw0.h.avpn == (vpn >> 11) ) &&					     ( hpte_dw0.h.v ) &&					     ( hpte_dw0.h.h == secondary ) ) {						while (1) ;					}				}			}		}	}	spin_unlock_irqrestore( &hash_table_lock, flags );}int proc_dol2crvec(ctl_table *table, int write, struct file *filp,		   void *buffer, size_t *lenp){	int vleft, first=1, len, left, val;#define TMPBUFLEN 256	char buf[TMPBUFLEN], *p;	static const char *sizestrings[4] = {		"2MB", "256KB", "512KB", "1MB"	};	static const char *clockstrings[8] = {		"clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",		"+2 clock", "+2.5 clock", "+3 clock", "reserved(7)"	};	static const char *typestrings[4] = {		"flow-through burst SRAM", "reserved SRAM",		"pipelined burst SRAM", "pipelined late-write SRAM"	};	static const char *holdstrings[4] = {		"0.5", "1.0", "(reserved2)", "(reserved3)"	};	if ( ((_get_PVR() >> 16) != 8) && ((_get_PVR() >> 16) != 12))		return -EFAULT;		if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {		*lenp = 0;		return 0;	}		vleft = table->maxlen / sizeof(int);	left = *lenp;		for (; left /*&& vleft--*/; first=0) {		if (write) {			while (left) {				char c;				if(get_user(c,(char *) buffer))					return -EFAULT;				if (!isspace(c))					break;				left--;				((char *) buffer)++;			}			if (!left)				break;			len = left;			if (len > TMPBUFLEN-1)				len = TMPBUFLEN-1;			if(copy_from_user(buf, buffer, len))				return -EFAULT;			buf[len] = 0;			p = buf;			if (*p < '0' || *p > '9')				break;			val = simple_strtoul(p, &p, 0);			len = p-buf;			if ((len < left) && *p && !isspace(*p))				break;			buffer += len;			left -= len;#if 0			/* DRENG need a def */			_set_L2CR(0);			_set_L2CR(val);			while ( _get_L2CR() & 0x1 )				/* wait for invalidate to finish */;#endif			  		} else {			p = buf;			if (!first)				*p++ = '\t';#if 0			/* DRENG need a def */			val = _get_L2CR();#endif			p += sprintf(p, "0x%08x: ", val);			p += sprintf(p, " %s", (val >> 31) & 1 ? "enabled" :				     "disabled");			p += sprintf(p, ", %sparity", (val>>30)&1 ? "" : "no ");			p += sprintf(p, ", %s", sizestrings[(val >> 28) & 3]);			p += sprintf(p, ", %s", clockstrings[(val >> 25) & 7]);			p += sprintf(p, ", %s", typestrings[(val >> 23) & 2]);			p += sprintf(p, "%s", (val>>22)&1 ? ", data only" : "");			p += sprintf(p, "%s", (val>>20)&1 ? ", ZZ enabled": "");			p += sprintf(p, ", %s", (val>>19)&1 ? "write-through" :				     "copy-back");			p += sprintf(p, "%s", (val>>18)&1 ? ", testing" : "");			p += sprintf(p, ", %sns hold",holdstrings[(val>>16)&3]);			p += sprintf(p, "%s", (val>>15)&1 ? ", DLL slow" : "");			p += sprintf(p, "%s", (val>>14)&1 ? ", diff clock" :"");			p += sprintf(p, "%s", (val>>13)&1 ? ", DLL bypass" :"");						p += sprintf(p,"\n");						len = strlen(buf);			if (len > left)				len = left;			if(copy_to_user(buffer, buf, len))				return -EFAULT;			left -= len;			buffer += len;			break;		}	}	if (!write && !first && left) {		if(put_user('\n', (char *) buffer))			return -EFAULT;		left--, buffer++;	}	if (write) {		p = (char *) buffer;		while (left) {			char c;			if(get_user(c, p++))				return -EFAULT;			if (!isspace(c))				break;			left--;		}	}	if (write && first)		return -EINVAL;	*lenp -= left;	filp->f_pos += *lenp;	return 0;}

⌨️ 快捷键说明

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