i386/84842: i386_set_ioperm(2) timing issue

No Name arundel at h3c.de
Fri Aug 12 13:10:29 GMT 2005


>Number:         84842
>Category:       i386
>Synopsis:       i386_set_ioperm(2) timing issue
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Aug 12 13:10:28 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     No Name
>Release:        FreeBSD 6.0-BETA1 i386
>Organization:
>Environment:
System: FreeBSD skatecity 6.0-BETA1 FreeBSD 6.0-BETA1 #0: Mon Jul 18 03:00:45 CEST 2005 root at skatecity:/usr/obj/usr/src/sys/ARUNDEL i386


	
>Description:
	I'm using the sysarch syscall to set I/O permissions (yes, I know -libc
	is the recommended way of doing this unstead of using syscalls). The
	I/O permissions however don't get set immediately, but need some time
	to get set. This causes a I/O port access that is being issued shortly
	after the sysarch(2) syscall with the i386_set_ioperm(2) argument to
	fail due to missing I/O port permissions:

	Bus error: 10 (core dumped)

	The problem will not occur when there is a heavy system load. Due to
	the mulritasking nature of Unix the code execution will be delayed and
	thus the I/O permissions get set before the actual port access. However
	when the execution time of the app is close to realtime there won't be
	enough time between the success of the sysarch(2) syscall and the port
	request.

	This problem seems to occurs under RELENG_6 as well as under
	5.4-STABLE.

>How-To-Repeat:
	Compile and execute the attached C app. Optimisation settings shouldn't
	have any effect on this matter.

>Fix:
	Maybe usleep(3) or nanosleep(2) in /usr/src/sys/i386/i386/sys_machdep.c
	 could solve the problem?

--- io.c begins here ---
#define PORT    0x378
#include <unistd.h>
#include <machine/sysarch.h>

static inline void outb (unsigned short int port, unsigned char val) {
        __asm__ volatile ("outb %0,%1\n"::"a" (val), "d" (port) );
}

int
main (int argc, char **argv) {

    struct i386_ioperm_args *args;
    struct i386_ioperm_args arg;
    args = &arg;
 
    args->start = PORT;
    args->length = 1;
    args->enable = 1;
 
    if(sysarch(I386_SET_IOPERM,args)) {
    printf("Error during syscall\n");
    exit(1);
    }

    else {

        /* sleep(1); <- With this delay the I/O port access works /*
        outb(0x378,0xFF);
        exit(0);
    }
}

//eof
--- io.c ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-i386 mailing list