Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 May 1996 19:14:07 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        asami@cs.berkeley.edu, bde@zeta.org.au
Cc:        current@freebsd.org, nisha@cs.berkeley.edu
Subject:   Re: some more on fast bcopy
Message-ID:  <199605110914.TAA21036@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>Is the following possible?  Say, process A is in the kernel for the
>copyin, and then process B (or rather a device associated to it)
>interrupts it, and it also invokes copyin.  Someone else interrupts B,
>and then when that someone else is done, we go back to A.  Now A's
>copyin is done, and %cr0 is set back to the original value, whose TS
>bit says the coprocessor is not available.  So we get a panic when B
>returns.

It can't be interrupted, but it can go to sleep for handling a page
fault.  Then bad things may happen.

This can probably be fixed by switching the FP context in cpu_switch().

It isn't even necessary to save the FP registers, at least in
non-interrupt handlers, if they aren't already in use.  In particular,
copyin() and copyout() are never called from interrupt handlers, so
it isn't necessary to preserve the kernel FP registers (they are
guaranteed to not be in use).  Only the user FP context needs to be
preserved.  This optimization is closely related to fixing the bug.
It should start out something like:

	if (intr_nesting_level > 0) {
		/* Save reentrantly the same as now. */
	} else {
		if (npxproc != NULL) {
			assert(npxproc == curproc);
			fnsave(&curpcb->pcb_savefpu);
			npxproc = NULL;
		}
		/* Now we own the FPU. */

		/*
		 * The process' FP state is saved in the pcb, but if we get
		 * switched, the cpu_switch() will store our FP state in the
		 * pcb.  It should be possible to avoid all the copying for
		 * this, e.g., by setting a flag to tell cpu_switch() to
		 * save the state somewhere else.
		 */
		tmp = curpcb->pcb_savefpu;

		stop_emulating();
		npxproc = curproc;
	}
	...
	if (intr_nesting_level > 0)
		/* Restore reentrantly the same as now. */
	} else {
		curpcb->pcb_savefpu = tmp;
		start_emulating();
		npxproc = NULL;
	}


>By the way, according to the trace:

>===
>(kgdb) bt
>#0  0xf01b3bf3 in boot ()
>#1  0xf01183a6 in panic ()
>#2  0xf01bbd66 in trap_fatal ()
>#3  0xf01bb5ea in trap ()
>#4  0xf01b1491 in calltrap ()
>#5  0xf019b7e8 in ffs_write ()
>#6  0xf0134c1f in vn_write ()
>#7  0xf0119bc6 in write ()
>#8  0xf01bc005 in syscall ()
>#9  0xf01b14e5 in Xsyscall ()
>#10 0x2289 in ?? ()
>#11 0x1de7 in ?? ()
>#12 0x1095 in ?? ()
>===

>I don't see any copyin()/copyout() or fastmove() there, is this
>natural?  Or does this mean we screwed up the %cr0 for someone else?
>(Although what ffs_write() has to do with the floating-point unit
>unless it's calling our FP copy, I have no idea.)

It's normal for one stack frame to be missing for panics for fatal
traps.  I fixed this in rev.1.10 of exception.s but I think rev.1.14
broke it again.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605110914.TAA21036>