FreeBSD/sys/powerpc/powerpc/trap.c
/* Handle kernel SLB faults -- runs in real mode, all seat belts off */
Handle kernel SLB faults -- runs in real mode, all seat belts off
Handle kernel SLB faults -- runs in real mode all seat belts off
void
handle_kernel_slb_spill(int type, register_t dar, register_t srr0)
{
	struct slb *slbcache;
	uint64_t slbe, slbv;
	uint64_t esid, addr;
	int i;
	addr = (type == EXC_ISE) ? srr0 : dar;
	slbcache = PCPU_GET(slb);
	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
	slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
	for (i = 0; i < n_slbs; i++)
		if (slbcache[i].slbe == (slbe | (uint64_t)i))
			return;
	slbv = kernel_va_to_slbv(addr);
	if (slbcache[USER_SLB_SLOT].slbe == 0) {
		for (i = 0; i < n_slbs; i++) {
			if (i == USER_SLB_SLOT)
				continue;
			if (!(slbcache[i].slbe & SLBE_VALID))
				goto fillkernslb;
		}
		if (i == n_slbs)
			slbcache[USER_SLB_SLOT].slbe = 1;
	}
	i = mftb() % n_slbs;
	if (i == USER_SLB_SLOT)
		i = (i+1) % n_slbs;
fillkernslb:
	slbcache[i].slbv = slbv;
	slbcache[i].slbe = slbe | (uint64_t)i;
}
void handle_kernel_slb_spill ( int type , register_t dar , register_t srr0 ) { struct slb * slbcache ; uint64_t slbe , slbv ; uint64_t esid , addr ; int i ; addr = ( type == EXC_ISE ) ? srr0 : dar ; slbcache = PCPU_GET ( slb ) ; esid = ( uintptr_t ) addr >> ADDR_SR_SHFT ; slbe = ( esid << SLBE_ESID_SHIFT ) | SLBE_VALID ; for ( i = 0 ; i < n_slbs ; i ++ ) if ( slbcache [ i ] . slbe == ( slbe | ( uint64_t ) i ) ) return ; slbv = kernel_va_to_slbv ( addr ) ; if ( slbcache [ USER_SLB_SLOT ] . slbe == 0 ) { for ( i = 0 ; i < n_slbs ; i ++ ) { if ( i == USER_SLB_SLOT ) continue ; if ( ! ( slbcache [ i ] . slbe & SLBE_VALID ) ) goto fillkernslb ; } if ( i == n_slbs ) slbcache [ USER_SLB_SLOT ] . slbe = 1 ; } i = mftb ( ) % n_slbs ; if ( i == USER_SLB_SLOT ) i = ( i + 1 ) % n_slbs ; fillkernslb : slbcache [ i ] . slbv = slbv ; slbcache [ i ] . slbe = slbe | ( uint64_t ) i ; }
Handle kernel SLB faults -- runs in real mode, all seat belts off
Handle kernel SLB faults -- runs in real mode all seat belts off
/* See if the hardware flushed this somehow (can happen in LPARs) */ /* Not in the map, needs to actually be added */ /* Sacrifice a random SLB entry that is not the user entry */ /* Write new entry */ /* Trap handler will restore from cache on exit */