*BSD News Article 16619


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!constellation!osuunx.ucc.okstate.edu!moe.ksu.ksu.edu!ux1.cso.uiuc.edu!howland.reston.ans.net!noc.near.net!uunet!pipex!warwick!uknet!mcsun!sun4nl!tuegate.tue.nl!svin09.info.win.tue.nl!wzv.win.tue.nl!gvr.win.tue.nl!guido
From: guido@gvr.win.tue.nl (Guido van Rooij)
Newsgroups: comp.os.386bsd.development
Subject: Re: /dev/mem and /sys/i386/i386/mem.c
Date: 29 May 1993 18:33:02 GMT
Organization: Eindhoven University of Technology, The Netherlands
Lines: 130
Distribution: world
Message-ID: <1u8a8u$o8m@wzv.win.tue.nl>
References: <1993May28.222533.24315@ucsu.Colorado.EDU>
NNTP-Posting-Host: gvr.win.tue.nl

galbrait@rintintin.Colorado.EDU (GALBRAITH JOHN) writes:

>I was wondering if somebody could clarify what happens when
>you read/write to /dev/mem in the locations that are supposed
>to be mapped to the I/O bus.  The man page says something
>about I/O being located in /dev/mem between 0x10000 to 0xa0000.  When
>I look at /sys/i386/i386/mem.c, I can't see how this is going to
>work.  Isn't there normal memory at those locations? mem.c does
>not appear to be written to support writes anyway, just reads.
> 
>On a similar note, has anybody patched mem.c to support /dev/ioportb
>and /dev/ioportw?  I have hacked a little bit on this without
>success.  My test program opens a file on /dev/ioportb, does an
>lseek(), and then a write() (writes one byte only.)  The
>file is successfully opened, the lseek() call returns correctly with
>no error message or anything, and then it goes to mem.c.  The
>uio structure is not correct at this point.  The uio_rw field is
>correct, I believe, as is the direction (sorry, I can't remember the
>name of the field.)  However, the uio_offset field is way off as
>is the uio_resid.  Shouldn't the lseek() call have set the uio_offset
>field?  Also, the call to write specifies one byte only (the third
>parameter is a 1) and should set the uio_resid to 1, right?
> 
>It ends up trying to do many writes to some random address, and 
>all hell breaks loose.  What is wrong with my reasoning?
> 
>thanks, 
>john galbraith
>galbrait@rintintin.colorado.edu

A lot more work needs to be done then just undefining the code in there.
For example, the correct privs for inb/outb's needs to be recorded on
a per process base. And even then, the way this is done in the notdef'ed
code in mem.c is a bit questionable: in this way, each inb or outb is
done in kernel. With a proper interface for setting the bitmap in the TSS
(i.e. specifying, per process, which ports are allowed to read/write), 
you can do the inb/outb's in user mode, and is thus much cheaper.

There is a quick hack that gives a process io permission for *every*
port whenever /dev/mem is opened by that process. 
Currently that is, according to me, the best solution.

I am told that in 386bsd 0.2 the io system is improved.

-Guido

Here's the patch: (note that I am not using /dev/mem but another 
minor for that purpose, but it's quite easy to change that (just
take another minor number))

*** machdep.c~	Fri Apr 30 19:31:38 1993
--- machdep.c	Tue May  4 22:11:11 1993
***************
*** 975,980 ****
--- 975,984 ----
  	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG;
  	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
  	_gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
+ 
+ 	((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt = 
+ 		(sizeof(tss))<<16;
+ 
  	ltr(_gsel_tss);
  
  	/* make a call gate to reenter kernel with */
*** mem.c~	Tue Dec 24 23:23:37 1991
--- mem.c	Wed May  5 20:52:10 1993
***************
*** 50,57 ****
--- 50,59 ----
  #include "systm.h"
  #include "uio.h"
  #include "malloc.h"
+ #include "proc.h"
  
  #include "machine/cpu.h"
+ #include "machine/psl.h"
  
  #include "vm/vm_param.h"
  #include "vm/lock.h"
***************
*** 60,65 ****
--- 62,103 ----
  #include "vm/vm_prot.h"
  
  extern        char *vmmap;            /* poor name! */
+ /*ARGSUSED*/
+ mmclose(dev, uio, flags)
+ 	dev_t dev;
+ 	struct uio *uio;
+ 	int flags;
+ {
+ 	struct syscframe *fp;
+ 
+ 	switch (minor(dev)) {
+ 	case 14:
+ 		fp = (struct syscframe *)curproc->p_regs;
+ 		fp->sf_eflags &= ~PSL_IOPL;
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 	return(0);
+ }
+ /*ARGSUSED*/
+ mmopen(dev, uio, flags)
+ 	dev_t dev;
+ 	struct uio *uio;
+ 	int flags;
+ {
+ 	struct syscframe *fp;
+ 
+ 	switch (minor(dev)) {
+ 	case 14:
+ 		fp = (struct syscframe *)curproc->p_regs;
+ 		fp->sf_eflags |= PSL_IOPL;
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 	return(0);
+ }
  /*ARGSUSED*/
  mmrw(dev, uio, flags)
  	dev_t dev;
-- 
Guido van Rooij                 |  Internet: guido@gvr.win.tue.nl
Bisschopsmolen 16               |  Phone:    ++31.40.461433
5612 DS Eindhoven               |  ((12+144+20)+3*sqrt(4))/7 
The Netherlands                 |    +(5*11)=9^2+0