From owner-freebsd-i386@FreeBSD.ORG Fri Aug 12 23:50:11 2005 Return-Path: X-Original-To: freebsd-i386@hub.freebsd.org Delivered-To: freebsd-i386@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1AE0316A41F for ; Fri, 12 Aug 2005 23:50:11 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id BCFE343D46 for ; Fri, 12 Aug 2005 23:50:10 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id j7CNoAeY068344 for ; Fri, 12 Aug 2005 23:50:10 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id j7CNoAJc068342; Fri, 12 Aug 2005 23:50:10 GMT (envelope-from gnats) Date: Fri, 12 Aug 2005 23:50:10 GMT Message-Id: <200508122350.j7CNoAJc068342@freefall.freebsd.org> To: freebsd-i386@FreeBSD.org From: Bruce Evans Cc: Subject: Re: i386/84842: i386_set_ioperm(2) timing issue X-BeenThere: freebsd-i386@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Bruce Evans List-Id: I386-specific issues for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Aug 2005 23:50:11 -0000 The following reply was made to PR i386/84842; it has been noted by GNATS. From: Bruce Evans To: Bruce Evans Cc: arundel@h3c.de, freebsd-gnats-submit@FreeBSD.org Subject: Re: i386/84842: i386_set_ioperm(2) timing issue Date: Sat, 13 Aug 2005 09:44:33 +1000 (EST) On Fri, 12 Aug 2005, Bruce Evans wrote: > The problem seems to be that the TSS is not loaded by the syscall. The > i/o permissions bitmap is in the TSS and I think think the TSS must be > reloaded for the new bitmap to be seen. The TSS is reloaded on the next > context switch but doesn't seem to be loaded anywhere else in normal > execution (it is also loaded at boot time and for vm86 BIOS calls and > returns). > > Try adding an ltr(gsel_tss) near the end of i386_set_ioperm(). Further reading and testing showed that the bug is a relatively new one and fixing it cleanly is not so easy. The CPU apparently examines the permissions bitmap on every access (that's one reason i/o accesses are so slow :-), so the TSS [register] doesn't need to be reloaded after every change. However, for the first access the bitmap is usually empty since the loading of the new TSS that holds the bitmap has been broken by an optimization. From an old version of i386/sys_machdep.c: % int % i386_extend_pcb(struct thread *td) % { % ... % /* switch to the new TSS after syscall completes */ % td->td_flags |= TDF_NEEDRESCHED; This was broken by optimizing null context switches. Now the switch to the new TSS doesn't normally actually occur after the syscall completes, since the scheduler normally reschedules the same thread and mi_switch() now avoids calling cpu_switch() in this case. % ... % } % % static int % i386_set_ioperm(td, args) % struct thread *td; % char *args; % { % .. % if (td->td_pcb->pcb_ext == 0) % if ((error = i386_extend_pcb(td)) != 0) % return (error); % iomap = (char *)td->td_pcb->pcb_ext->ext_iomap; This extends the pcb on the first call to i386_set_ioperm() for a thread, so if the TSS were reloaded after the call as intended then the first call would be less broken than subsequent calls. % % if (ua.start + ua.length > IOPAGES * PAGE_SIZE * NBBY) % return (EINVAL); % % for (i = ua.start; i < ua.start + ua.length; i++) { % if (ua.enable) % iomap[i >> 3] &= ~(1 << (i & 7)); % else % iomap[i >> 3] |= (1 << (i & 7)); % } Testing shows than an ltr() is not needed here. It is sufficient to sleep (in the application) after the first call so that the new TSS gets loaded. For subsequent calls, the TSS descriptor doesn't change, and the TSS apparently doesn't need to be reloaded to get changes to the contents of the TSS seen. % return (error); % } For a quick fix, a tsleep(..., 1) in 386_extend_pcb() should work as well as a sleep in the application (unless/until somone modifies short sleeps to not switch). Bruce