From owner-freebsd-hackers@FreeBSD.ORG Mon Feb 28 22:55:36 2005 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id DA65D16A4CE for ; Mon, 28 Feb 2005 22:55:36 +0000 (GMT) Received: from intranet.ru (intranet.ru [212.164.71.24]) by mx1.FreeBSD.org (Postfix) with ESMTP id D572143D66 for ; Mon, 28 Feb 2005 22:55:34 +0000 (GMT) (envelope-from denus@ngs.ru) Received: from [172.16.0.10] (HELO smtp.ngs.ru) by intranet.ru (CommuniGate Pro SMTP 4.2.4) with ESMTP id 204396586 for freebsd-hackers@freebsd.org; Tue, 01 Mar 2005 04:56:56 +0600 Received: from ngs.ru (unknown [83.237.133.132]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.ngs.ru (Postfix) with ESMTP id 1E07D774C0C for ; Tue, 1 Mar 2005 04:55:30 +0600 (NOVT) Message-ID: <4223A1D1.6000104@ngs.ru> Date: Tue, 01 Mar 2005 01:57:21 +0300 From: Denis Ustimenko User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20041215 X-Accept-Language: ru, en-us, en MIME-Version: 1.0 To: freebsd-hackers@freebsd.org Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Subject: TDF_NEEDRESCHED when extending pcb on x86 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Feb 2005 22:55:37 -0000 Hi, there! I've tried s3switch utility from ports on 5.2.1 and found that i386_set_ioperm syscall doesn't work properly. The next code illustrates the problem. It will get SIGBUS with very high probability. #include #include #include int main() { if ( i386_set_ioperm( 0x80, 1, 1)) { perror("XXX"); return 1; } inb( 0x80); return 0; } Now I have no 5.3 or CURRENT system but brief looking on code shows that it should give the same result on them. The problem occurs when we extend pcb and set TDF_NEEDRESCHED bit hoping that thread will be rescheduled and new TSS will be loaded. But sched_switch function skips cpu_switch when thread was not changed and ltr is not executed. So I've patched sys_machdep.c the patch is below. But two thoughts in this situation are not clear to me: 1. May be patching of scheduler code to call cpu_switch in case of TDF_NEEDRESCHED is more appropriate decision 2. Is it necessary to protect all new lines of i386_extend_pcb function by sched_lock? It looks like we could move at least ltr out of syncronized code. *** /usr/src/sys/i386/include/segments.h.orig Mon Feb 28 23:34:30 2005 --- /usr/src/sys/i386/include/segments.h Mon Feb 28 23:34:53 2005 *************** *** 243,248 **** --- 243,249 ---- extern struct gate_descriptor *idt; extern union descriptor ldt[NLDT]; extern struct region_descriptor r_gdt, r_idt; + extern int private_tss; void lgdt(struct region_descriptor *rdp); void sdtossd(struct segment_descriptor *sdp, *** /usr/src/sys/i386/i386/sys_machdep.c.orig Mon Feb 28 23:29:31 2005 --- /usr/src/sys/i386/i386/sys_machdep.c Mon Feb 28 23:33:31 2005 *************** *** 172,179 **** mtx_lock_spin(&sched_lock); td->td_pcb->pcb_ext = ext; ! /* switch to the new TSS after syscall completes */ ! td->td_flags |= TDF_NEEDRESCHED; mtx_unlock_spin(&sched_lock); return 0; --- 172,180 ---- mtx_lock_spin(&sched_lock); td->td_pcb->pcb_ext = ext; ! private_tss |= 1 << PCPU_GET(cpuid); ! *PCPU_GET(tss_gdt) = td->td_pcb->pcb_ext->ext_tssd; ! ltr(GSEL(GPROC0_SEL, SEL_KPL)); mtx_unlock_spin(&sched_lock); return 0; -- Best regards Denis