Split of architecture-dependent and -independent functions for i386,
mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
# Makefile for system library implementation
|
||||
|
||||
include /etc/make.conf
|
||||
|
||||
# Directories
|
||||
u = /usr
|
||||
i = $u/include
|
||||
a = ../arch
|
||||
|
||||
# Programs, flags, etc.
|
||||
CC = exec cc $(CFLAGS) -c
|
||||
CCNOPROF = exec cc $(CFLAGSNOPROF) -c # no call profiling for these
|
||||
CPP = $l/cpp
|
||||
LD = $(CC) -.o
|
||||
CFLAGS = -I$i $(CPROFILE)
|
||||
CFLAGS = -I$i $(CPROFILE) -I$a/$(ARCH)/include
|
||||
CFLAGSNOPROF = -I$i
|
||||
LDFLAGS = -i
|
||||
|
||||
@@ -31,8 +34,6 @@ OBJECTS = \
|
||||
$(SYSTEM)(do_irqctl.o) \
|
||||
$(SYSTEM)(do_devio.o) \
|
||||
$(SYSTEM)(do_vdevio.o) \
|
||||
$(SYSTEM)(do_int86.o) \
|
||||
$(SYSTEM)(do_sdevio.o) \
|
||||
$(SYSTEM)(do_copy.o) \
|
||||
$(SYSTEM)(do_vcopy.o) \
|
||||
$(SYSTEM)(do_umap.o) \
|
||||
@@ -44,19 +45,17 @@ OBJECTS = \
|
||||
$(SYSTEM)(do_getksig.o) \
|
||||
$(SYSTEM)(do_endksig.o) \
|
||||
$(SYSTEM)(do_kill.o) \
|
||||
$(SYSTEM)(do_readbios.o) \
|
||||
$(SYSTEM)(do_sigsend.o) \
|
||||
$(SYSTEM)(do_sigreturn.o) \
|
||||
$(SYSTEM)(do_abort.o) \
|
||||
$(SYSTEM)(do_getinfo.o) \
|
||||
$(SYSTEM)(do_iopenable.o) \
|
||||
$(SYSTEM)(do_vm.o) \
|
||||
$(SYSTEM)(do_vm_setbuf.o) \
|
||||
$(SYSTEM)(do_sprofile.o) \
|
||||
$(SYSTEM)(do_cprofile.o) \
|
||||
$(SYSTEM)(do_profbuf.o)
|
||||
|
||||
$(SYSTEM): $(OBJECTS)
|
||||
build $(SYSTEM): $(OBJECTS)
|
||||
aal cr $@ *.o
|
||||
|
||||
clean:
|
||||
@@ -102,15 +101,9 @@ $(SYSTEM)(do_irqctl.o): do_irqctl.c
|
||||
$(SYSTEM)(do_devio.o): do_devio.c
|
||||
$(CC) do_devio.c
|
||||
|
||||
$(SYSTEM)(do_sdevio.o): do_sdevio.c
|
||||
$(CC) do_sdevio.c
|
||||
|
||||
$(SYSTEM)(do_vdevio.o): do_vdevio.c
|
||||
$(CC) do_vdevio.c
|
||||
|
||||
$(SYSTEM)(do_int86.o): do_int86.c
|
||||
$(CC) do_int86.c
|
||||
|
||||
$(SYSTEM)(do_copy.o): do_copy.c
|
||||
$(CC) do_copy.c
|
||||
|
||||
@@ -144,9 +137,6 @@ $(SYSTEM)(do_getinfo.o): do_getinfo.c
|
||||
$(SYSTEM)(do_abort.o): do_abort.c
|
||||
$(CC) do_abort.c
|
||||
|
||||
$(SYSTEM)(do_readbios.o): do_readbios.c
|
||||
$(CC) do_readbios.c
|
||||
|
||||
$(SYSTEM)(do_setgrant.o): do_setgrant.c
|
||||
$(CC) do_setgrant.c
|
||||
|
||||
@@ -159,9 +149,6 @@ $(SYSTEM)(do_safecopy.o): do_safecopy.c
|
||||
$(SYSTEM)(do_segctl.o): do_segctl.c
|
||||
$(CC) do_segctl.c
|
||||
|
||||
$(SYSTEM)(do_iopenable.o): do_iopenable.c
|
||||
$(CC) do_iopenable.c
|
||||
|
||||
$(SYSTEM)(do_vm.o): do_vm.o
|
||||
do_vm.o: do_vm.c
|
||||
$(CC) do_vm.c
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/portio.h>
|
||||
|
||||
#if USE_DEVIO
|
||||
|
||||
@@ -66,16 +67,17 @@ doit:
|
||||
/* Process a single I/O request for byte, word, and long values. */
|
||||
if (io_dir == _DIO_INPUT) {
|
||||
switch (io_type) {
|
||||
/* maybe "it" should not be called ports */
|
||||
case _DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
|
||||
case _DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break;
|
||||
case _DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
|
||||
case _DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
} else {
|
||||
switch (io_type) {
|
||||
case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case _DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,23 +33,18 @@ register message *m_ptr; /* pointer to request message */
|
||||
rp = proc_addr(proc);
|
||||
sp = (reg_t) m_ptr->PR_STACK_PTR;
|
||||
rp->p_reg.sp = sp; /* set the stack pointer */
|
||||
#if (CHIP == M68000)
|
||||
rp->p_splow = sp; /* set the stack pointer low water */
|
||||
#ifdef FPP
|
||||
/* Initialize fpp for this process */
|
||||
fpp_new_state(rp);
|
||||
#endif
|
||||
#endif
|
||||
#if (CHIP == INTEL) /* wipe extra LDT entries */
|
||||
phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0,
|
||||
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
|
||||
|
||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||
/* wipe extra LDT entries */
|
||||
phys_memset(vir2phys(&rp->p_seg.p_ldt[EXTRA_LDT_INDEX]), 0,
|
||||
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_seg.p_ldt[0]));
|
||||
#endif
|
||||
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
|
||||
rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
|
||||
if (rp->p_rts_flags == 0) lock_enqueue(rp);
|
||||
/* Save command name for debugging, ps(1) output, etc. */
|
||||
phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR,
|
||||
(vir_bytes) P_NAME_LEN - 1);
|
||||
(vir_bytes) P_NAME_LEN - 1);
|
||||
if (phys_name != 0) {
|
||||
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
|
||||
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
||||
@@ -57,6 +52,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
} else {
|
||||
strncpy(rp->p_name, "<unset>", P_NAME_LEN);
|
||||
}
|
||||
|
||||
return(OK);
|
||||
}
|
||||
#endif /* USE_EXEC */
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#if (CHIP == INTEL)
|
||||
#include "../protect.h"
|
||||
#endif
|
||||
|
||||
#include <minix/endpoint.h>
|
||||
|
||||
@@ -23,7 +20,7 @@ PUBLIC int do_fork(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */
|
||||
#if (CHIP == INTEL)
|
||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||
reg_t old_ldt_sel;
|
||||
#endif
|
||||
register struct proc *rpc; /* child process pointer */
|
||||
@@ -42,10 +39,10 @@ register message *m_ptr; /* pointer to request message */
|
||||
|
||||
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
|
||||
gen = _ENDPOINT_G(rpc->p_endpoint);
|
||||
#if (CHIP == INTEL)
|
||||
old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */
|
||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||
old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */
|
||||
*rpc = *rpp; /* copy 'proc' struct */
|
||||
rpc->p_ldt_sel = old_ldt_sel; /* restore descriptors */
|
||||
rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
|
||||
#else
|
||||
*rpc = *rpp; /* copy 'proc' struct */
|
||||
#endif
|
||||
|
||||
@@ -11,9 +11,14 @@
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if !( POWERPC )
|
||||
|
||||
static unsigned long bios_buf[1024]; /* 4K, what about alignment */
|
||||
static vir_bytes bios_buf_vir, bios_buf_len;
|
||||
|
||||
#endif /* #if !( POWERPC ) */
|
||||
|
||||
|
||||
#if USE_GETINFO
|
||||
|
||||
/*===========================================================================*
|
||||
@@ -119,6 +124,8 @@ register message *m_ptr; /* pointer to request message */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !( POWERPC )
|
||||
case GET_BIOSBUFFER:
|
||||
bios_buf_vir = (vir_bytes)bios_buf;
|
||||
bios_buf_len = sizeof(bios_buf);
|
||||
@@ -135,7 +142,8 @@ register message *m_ptr; /* pointer to request message */
|
||||
length = sizeof(bios_buf_vir);
|
||||
src_phys = vir2phys(&bios_buf_vir);
|
||||
break;
|
||||
|
||||
#endif /* #if !( POWERPC ) */
|
||||
|
||||
case GET_IRQACTIDS: {
|
||||
length = sizeof(irq_actids);
|
||||
src_phys = vir2phys(irq_actids);
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/* The kernel call implemented in this file:
|
||||
* m_type: SYS_INT86
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* m1_p1: INT86_REG86
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <ibm/int86.h>
|
||||
|
||||
struct reg86u reg86;
|
||||
|
||||
/*===========================================================================*
|
||||
* do_int86 *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_int86(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
vir_bytes caller_vir;
|
||||
phys_bytes caller_phys, kernel_phys;
|
||||
|
||||
caller_vir = (vir_bytes) m_ptr->INT86_REG86;
|
||||
caller_phys = umap_local(proc_addr(who_p), D, caller_vir, sizeof(reg86));
|
||||
if (0 == caller_phys) return(EFAULT);
|
||||
kernel_phys = vir2phys(®86);
|
||||
phys_copy(caller_phys, kernel_phys, (phys_bytes) sizeof(reg86));
|
||||
|
||||
level0(int86);
|
||||
|
||||
/* Copy results back to the caller */
|
||||
phys_copy(kernel_phys, caller_phys, (phys_bytes) sizeof(reg86));
|
||||
|
||||
/* The BIOS call eats interrupts. Call get_randomness to generate some
|
||||
* entropy. Normally, get_randomness is called from an interrupt handler.
|
||||
* Figuring out the exact source is too complicated. CLOCK_IRQ is normally
|
||||
* not very random.
|
||||
*/
|
||||
lock(0, "do_int86");
|
||||
get_randomness(CLOCK_IRQ);
|
||||
unlock(0);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_IOPENABLE
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i2: IO_ENDPT (process to give I/O Protection Level bits)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include "../kernel.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_iopenable *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_iopenable(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr;
|
||||
|
||||
#if 1 /* ENABLE_USERPRIV && ENABLE_USERIOPL */
|
||||
if (m_ptr->IO_ENDPT == SELF) {
|
||||
proc_nr = who_p;
|
||||
} else if(!isokendpt(m_ptr->IO_ENDPT, &proc_nr))
|
||||
return(EINVAL);
|
||||
enable_iop(proc_addr(proc_nr));
|
||||
return(OK);
|
||||
#else
|
||||
return(EPERM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -48,13 +48,10 @@ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
|
||||
src_phys = umap_local(proc_addr(who_p), D, (vir_bytes) map_ptr,
|
||||
sizeof(rp->p_memmap));
|
||||
if (src_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap));
|
||||
phys_copy(src_phys,vir2phys(rp->p_memmap),
|
||||
(phys_bytes)sizeof(rp->p_memmap));
|
||||
|
||||
#if (CHIP != M68000)
|
||||
alloc_segments(rp);
|
||||
#else
|
||||
pmmu_init_proc(rp);
|
||||
#endif
|
||||
old_flags = rp->p_rts_flags; /* save the previous value of the flags */
|
||||
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ PUBLIC int do_nice(message *m_ptr)
|
||||
if (pri == PRIO_STOP) {
|
||||
|
||||
/* Take process off the scheduling queues. */
|
||||
lock_dequeue(rp);
|
||||
if(rp->p_rts_flags == 0) lock_dequeue(rp);
|
||||
rp->p_rts_flags |= NO_PRIORITY;
|
||||
return(OK);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ PUBLIC int do_nice(message *m_ptr)
|
||||
/* Make sure the process is not running while changing its priority.
|
||||
* Put the process back in its new queue if it is runnable.
|
||||
*/
|
||||
lock_dequeue(rp);
|
||||
if(rp->p_rts_flags == 0) lock_dequeue(rp);
|
||||
rp->p_rts_flags &= ~NO_PRIORITY;
|
||||
rp->p_max_priority = rp->p_priority = new_q;
|
||||
if (! rp->p_rts_flags) lock_enqueue(rp);
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/* The kernel call implemented in this file:
|
||||
* m_type: SYS_READBIOS
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* m2_i1: RDB_SIZE number of bytes to copy
|
||||
* m2_l1: RDB_ADDR absolute address in BIOS area
|
||||
* m2_p1: RDB_BUF buffer address in requesting process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_readbios *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_readbios(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr;
|
||||
struct proc *p;
|
||||
phys_bytes address, phys_buf, phys_bios;
|
||||
vir_bytes buf;
|
||||
size_t size;
|
||||
|
||||
address = m_ptr->RDB_ADDR;
|
||||
buf = (vir_bytes)m_ptr->RDB_BUF;
|
||||
size = m_ptr->RDB_SIZE;
|
||||
|
||||
okendpt(m_ptr->m_source, &proc_nr);
|
||||
p = proc_addr(proc_nr);
|
||||
phys_buf = umap_local(p, D, buf, size);
|
||||
if (phys_buf == 0)
|
||||
return EFAULT;
|
||||
phys_bios = umap_bios(p, address, size);
|
||||
if (phys_bios == 0)
|
||||
return EPERM;
|
||||
phys_copy(phys_bios, phys_buf, size);
|
||||
return 0;
|
||||
}
|
||||
@@ -247,7 +247,6 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE
|
||||
PUBLIC int do_safecopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
static endpoint_t new_granter;
|
||||
static int access, src_seg, dst_seg;
|
||||
|
||||
/* Set src and dst parameters.
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/* The kernel call implemented in this file:
|
||||
* m_type: SYS_SDEVIO
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* m2_i3: DIO_REQUEST (request input or output)
|
||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||
* m2_l1: DIO_PORT (port to read/ write)
|
||||
* m2_p1: DIO_VEC_ADDR (virtual address of buffer)
|
||||
* m2_l2: DIO_VEC_SIZE (number of elements)
|
||||
* m2_i2: DIO_VEC_PROC (process where buffer is)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
#include <minix/endpoint.h>
|
||||
|
||||
#if USE_SDEVIO
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sdevio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sdevio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr, proc_nr_e = m_ptr->DIO_VEC_ENDPT;
|
||||
int count = m_ptr->DIO_VEC_SIZE;
|
||||
long port = m_ptr->DIO_PORT;
|
||||
phys_bytes phys_buf;
|
||||
int i, req_type, req_dir, io_type, size, nr_io_range;
|
||||
struct proc *rp;
|
||||
struct priv *privp;
|
||||
struct io_range *iorp;
|
||||
|
||||
/* Allow safe copies and accesses to SELF */
|
||||
if ((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) != _DIO_SAFE &&
|
||||
proc_nr_e != SELF)
|
||||
{
|
||||
static int first= 1;
|
||||
if (first)
|
||||
{
|
||||
first= 0;
|
||||
kprintf("do_sdevio: for %d, req %d\n",
|
||||
m_ptr->m_source, m_ptr->DIO_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if process endpoint is OK.
|
||||
* A driver may directly provide a pointer to a buffer at the user-process
|
||||
* that initiated the device I/O. Kernel processes, of course, are denied.
|
||||
*/
|
||||
if (proc_nr_e == SELF)
|
||||
proc_nr = who_p;
|
||||
else
|
||||
if(!isokendpt(proc_nr_e, &proc_nr))
|
||||
return(EINVAL);
|
||||
if (iskerneln(proc_nr)) return(EPERM);
|
||||
|
||||
/* Extract direction (in or out) and type (size). */
|
||||
req_dir = m_ptr->DIO_REQUEST & _DIO_DIRMASK;
|
||||
req_type = m_ptr->DIO_REQUEST & _DIO_TYPEMASK;
|
||||
|
||||
/* Check for 'safe' variants. */
|
||||
if((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) == _DIO_SAFE) {
|
||||
/* Map grant address to physical address. */
|
||||
if ((phys_buf = umap_verify_grant(proc_addr(proc_nr), who_e,
|
||||
(vir_bytes) m_ptr->DIO_VEC_ADDR,
|
||||
(vir_bytes) m_ptr->DIO_OFFSET, count,
|
||||
req_dir == _DIO_INPUT ? CPF_WRITE : CPF_READ)) == 0)
|
||||
return(EPERM);
|
||||
} else {
|
||||
if(proc_nr != who_p)
|
||||
kprintf("unsafe sdevio by %d in %d\n", who_e, proc_nr_e);
|
||||
/* Get and check physical address. */
|
||||
if ((phys_buf = numap_local(proc_nr,
|
||||
(vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
|
||||
return(EFAULT);
|
||||
}
|
||||
|
||||
rp= proc_addr(who_p);
|
||||
if (privp && privp->s_flags & CHECK_IO_PORT)
|
||||
{
|
||||
switch (io_type)
|
||||
{
|
||||
case _DIO_BYTE: size= 1; break;
|
||||
case _DIO_WORD: size= 2; break;
|
||||
case _DIO_LONG: size= 4; break;
|
||||
default: size= 4; break; /* Be conservative */
|
||||
}
|
||||
port= m_ptr->DIO_PORT;
|
||||
nr_io_range= privp->s_nr_io_range;
|
||||
for (i= 0, iorp= privp->s_io_tab; i<nr_io_range; i++, iorp++)
|
||||
{
|
||||
if (port >= iorp->ior_base && port+size-1 <= iorp->ior_limit)
|
||||
break;
|
||||
}
|
||||
if (i >= nr_io_range)
|
||||
{
|
||||
kprintf(
|
||||
"do_sdevio: I/O port check failed for proc %d, port 0x%x\n",
|
||||
m_ptr->m_source, port);
|
||||
return EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform device I/O for bytes and words. Longs are not supported. */
|
||||
if (req_dir == _DIO_INPUT) {
|
||||
switch (req_type) {
|
||||
case _DIO_BYTE: phys_insb(port, phys_buf, count); break;
|
||||
case _DIO_WORD: phys_insw(port, phys_buf, count); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
} else if (req_dir == _DIO_OUTPUT) {
|
||||
switch (req_type) {
|
||||
case _DIO_BYTE: phys_outsb(port, phys_buf, count); break;
|
||||
case _DIO_WORD: phys_outsw(port, phys_buf, count); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return(EINVAL);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_SDEVIO */
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
* m4_l5: SEG_INDEX (return index into remote memory map here)
|
||||
*/
|
||||
#include "../system.h"
|
||||
#include "../protect.h"
|
||||
|
||||
#if USE_SEGCTL
|
||||
|
||||
@@ -22,7 +21,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
/* Return a segment selector and offset that can be used to reach a physical
|
||||
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
|
||||
*/
|
||||
u16_t selector;
|
||||
u32_t selector;
|
||||
vir_bytes offset;
|
||||
int i, index;
|
||||
register struct proc *rp;
|
||||
@@ -44,30 +43,9 @@ register message *m_ptr; /* pointer to request message */
|
||||
}
|
||||
if (index < 0) return(ENOSPC);
|
||||
|
||||
if (! machine.prot) {
|
||||
selector = phys / HCLICK_SIZE;
|
||||
offset = phys % HCLICK_SIZE;
|
||||
result = OK;
|
||||
} else {
|
||||
/* Check if the segment size can be recorded in bytes, that is, check
|
||||
* if descriptor's limit field can delimited the allowed memory region
|
||||
* precisely. This works up to 1MB. If the size is larger, 4K pages
|
||||
* instead of bytes are used.
|
||||
*/
|
||||
if (size < BYTE_GRAN_MAX) {
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
|
||||
USER_PRIVILEGE);
|
||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||
offset = 0;
|
||||
result = OK;
|
||||
} else {
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
|
||||
USER_PRIVILEGE);
|
||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||
offset = phys & 0xFFFF;
|
||||
result = OK;
|
||||
}
|
||||
}
|
||||
offset = alloc_remote_segment(&selector, &rp->p_seg,
|
||||
i, phys, size, USER_PRIVILEGE);
|
||||
result = OK;
|
||||
|
||||
/* Request successfully done. Now return the result. */
|
||||
m_ptr->SEG_INDEX = index | REMOTE_SEG;
|
||||
|
||||
@@ -40,7 +40,7 @@ message *m_ptr; /* pointer to request message */
|
||||
|
||||
sc.sc_psw = rp->p_reg.psw;
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||
/* Don't panic kernel if user gave bad selectors. */
|
||||
sc.sc_cs = rp->p_reg.cs;
|
||||
sc.sc_ds = rp->p_reg.ds;
|
||||
@@ -52,7 +52,11 @@ message *m_ptr; /* pointer to request message */
|
||||
#endif
|
||||
|
||||
/* Restore the registers. */
|
||||
#if _MINIX_CHIP == _CHIP_POWERPC
|
||||
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct stackframe_s));
|
||||
#else
|
||||
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs));
|
||||
#endif
|
||||
return(OK);
|
||||
}
|
||||
#endif /* USE_SIGRETURN */
|
||||
|
||||
@@ -45,6 +45,11 @@ message *m_ptr; /* pointer to request message */
|
||||
|
||||
/* Copy the registers to the sigcontext structure. */
|
||||
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
|
||||
#ifdef POWERPC
|
||||
memcpy(&sc.sc_regs, (char *) &rp->p_reg, struct(stackframe_s));
|
||||
#else
|
||||
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
|
||||
#endif
|
||||
|
||||
/* Finish the sigcontext initialization. */
|
||||
sc.sc_flags = 0; /* unused at this time */
|
||||
@@ -73,6 +78,16 @@ message *m_ptr; /* pointer to request message */
|
||||
if (dst_phys == 0) return(EFAULT);
|
||||
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
|
||||
|
||||
#if ( _MINIX_CHIP == _CHIP_POWERPC ) /* stuff that can't be done in the assembler code. */
|
||||
/* When the signal handlers C code is called it will write this value
|
||||
* into the signal frame (over the sf_retadr value).
|
||||
*/
|
||||
rp->p_reg.lr = smsg.sm_sigreturn;
|
||||
/* The first (and only) parameter for the user signal handler function.
|
||||
*/
|
||||
rp->p_reg.retreg = smsg.sm_signo; /* note the retreg == first argument */
|
||||
#endif
|
||||
|
||||
/* Reset user registers to execute the signal handler. */
|
||||
rp->p_reg.sp = (reg_t) frp;
|
||||
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
||||
|
||||
@@ -59,7 +59,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
|
||||
sprof_mem_size = m_ptr->PROF_MEM_SIZE;
|
||||
|
||||
init_cmos_clock(m_ptr->PROF_FREQ);
|
||||
init_profile_clock(m_ptr->PROF_FREQ);
|
||||
|
||||
sprofiling = 1;
|
||||
|
||||
@@ -78,7 +78,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
|
||||
sprofiling = 0;
|
||||
|
||||
stop_cmos_clock();
|
||||
stop_profile_clock();
|
||||
|
||||
phys_copy(vir2phys((vir_bytes) &sprof_info),
|
||||
sprof_info_addr, (phys_bytes) sizeof(sprof_info));
|
||||
|
||||
@@ -102,7 +102,7 @@ register message *m_ptr;
|
||||
tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
|
||||
return(EIO);
|
||||
i = (int) tr_addr;
|
||||
#if (CHIP == INTEL)
|
||||
#if (_MINIX_CHIP == _CHIP_INTEL)
|
||||
/* Altering segment registers might crash the kernel when it
|
||||
* tries to load them prior to restarting a process, so do
|
||||
* not allow it.
|
||||
|
||||
@@ -43,9 +43,11 @@ register message *m_ptr; /* pointer to request message */
|
||||
case REMOTE_SEG:
|
||||
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
|
||||
break;
|
||||
#if _MINIX_CHIP == _CHIP_INTEL
|
||||
case BIOS_SEG:
|
||||
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
|
||||
break;
|
||||
#endif
|
||||
case GRANT_SEG:
|
||||
phys_addr = umap_grant(proc_addr(proc_nr), offset, count);
|
||||
break;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/portio.h>
|
||||
|
||||
#if USE_VDEVIO
|
||||
|
||||
@@ -112,16 +113,22 @@ register message *m_ptr; /* pointer to request message */
|
||||
lock(13, "do_vdevio");
|
||||
switch (io_type) {
|
||||
case _DIO_BYTE: /* byte values */
|
||||
if (io_in) for (i=0; i<vec_size; i++) pvb[i].value = inb(pvb[i].port);
|
||||
else for (i=0; i<vec_size; i++) outb(pvb[i].port, pvb[i].value);
|
||||
if (io_in) for (i=0; i<vec_size; i++)
|
||||
pvb[i].value = inb( pvb[i].port);
|
||||
else for (i=0; i<vec_size; i++)
|
||||
outb( pvb[i].port, pvb[i].value);
|
||||
break;
|
||||
case _DIO_WORD: /* word values */
|
||||
if (io_in) for (i=0; i<vec_size; i++) pvw[i].value = inw(pvw[i].port);
|
||||
else for (i=0; i<vec_size; i++) outw(pvw[i].port, pvw[i].value);
|
||||
if (io_in) for (i=0; i<vec_size; i++)
|
||||
pvw[i].value = inw( pvw[i].port);
|
||||
else for (i=0; i<vec_size; i++)
|
||||
outw( pvw[i].port, pvw[i].value);
|
||||
break;
|
||||
default: /* long values */
|
||||
if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);
|
||||
else for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value);
|
||||
if (io_in) for (i=0; i<vec_size; i++)
|
||||
pvl[i].value = inl(pvl[i].port);
|
||||
else for (i=0; i<vec_size; i++)
|
||||
outl( pvb[i].port, pvl[i].value);
|
||||
}
|
||||
unlock(13);
|
||||
|
||||
|
||||
@@ -6,23 +6,13 @@
|
||||
* m4_l2: Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP)
|
||||
* m4_l3: Base address (VM_MAP_BASE)
|
||||
* m4_l4: Size (VM_MAP_SIZE)
|
||||
* m4_l5: Memory address (VM_MAP_ADDR)
|
||||
* m4_l5: address (VM_MAP_ADDR)
|
||||
*/
|
||||
#include "../system.h"
|
||||
|
||||
#include <sys/vm.h>
|
||||
|
||||
PRIVATE int vm_needs_init= 1;
|
||||
PRIVATE u32_t vm_cr3;
|
||||
|
||||
FORWARD _PROTOTYPE( void vm_init, (void) );
|
||||
FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
|
||||
FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
|
||||
FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
|
||||
FORWARD _PROTOTYPE( void set_cr3, (void) );
|
||||
FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
|
||||
FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
|
||||
u32_t offset) );
|
||||
#include <sys/vm.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vm_map *
|
||||
@@ -35,11 +25,10 @@ message *m_ptr; /* pointer to request message */
|
||||
struct proc *pp;
|
||||
|
||||
/* do_serial_debug= 1; */
|
||||
|
||||
if (vm_needs_init)
|
||||
{
|
||||
vm_needs_init= 0;
|
||||
vm_init();
|
||||
vm_needs_init= 0;
|
||||
vm_init();
|
||||
}
|
||||
|
||||
if (m_ptr->VM_MAP_ENDPT == SELF) {
|
||||
@@ -63,17 +52,17 @@ message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
pp->p_misc_flags |= MF_VM;
|
||||
|
||||
map_range(p_phys, size, offset);
|
||||
vm_map_range(p_phys, size, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
map_range(p_phys, size, p_phys);
|
||||
vm_map_range(p_phys, size, p_phys);
|
||||
}
|
||||
vm_set_cr3(vm_cr3);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_map_default *
|
||||
*===========================================================================*/
|
||||
@@ -88,137 +77,7 @@ struct proc *pp;
|
||||
base_clicks= pp->p_memmap[D].mem_phys;
|
||||
size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
|
||||
base_clicks;
|
||||
map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
|
||||
base_clicks << CLICK_SHIFT);
|
||||
vm_set_cr3(vm_cr3);
|
||||
vm_map_range(base_clicks << CLICK_SHIFT,
|
||||
size_clicks << CLICK_SHIFT, base_clicks << CLICK_SHIFT);
|
||||
}
|
||||
|
||||
PRIVATE void vm_init(void)
|
||||
{
|
||||
int o;
|
||||
phys_bytes p, pt_size;
|
||||
phys_bytes vm_dir_base, vm_pt_base, phys_mem;
|
||||
u32_t entry;
|
||||
unsigned pages;
|
||||
|
||||
if (!vm_size)
|
||||
panic("vm_init: no space for page tables", NO_NUM);
|
||||
|
||||
/* Align page directory */
|
||||
o= (vm_base % PAGE_SIZE);
|
||||
if (o != 0)
|
||||
o= PAGE_SIZE-o;
|
||||
vm_dir_base= vm_base+o;
|
||||
|
||||
/* Page tables start after the page directory */
|
||||
vm_pt_base= vm_dir_base+PAGE_SIZE;
|
||||
|
||||
pt_size= (vm_base+vm_size)-vm_pt_base;
|
||||
pt_size -= (pt_size % PAGE_SIZE);
|
||||
|
||||
/* Compute the number of pages based on vm_mem_high */
|
||||
pages= (vm_mem_high-1)/PAGE_SIZE + 1;
|
||||
|
||||
if (pages * I386_VM_PT_ENT_SIZE > pt_size)
|
||||
panic("vm_init: page table too small", NO_NUM);
|
||||
|
||||
for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
|
||||
{
|
||||
phys_mem= p*PAGE_SIZE;
|
||||
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
|
||||
I386_VM_PRESENT;
|
||||
if (phys_mem >= vm_mem_high)
|
||||
entry= 0;
|
||||
phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
|
||||
}
|
||||
|
||||
for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
|
||||
{
|
||||
phys_mem= vm_pt_base + p*PAGE_SIZE;
|
||||
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
|
||||
I386_VM_PRESENT;
|
||||
if (phys_mem >= vm_pt_base + pt_size)
|
||||
entry= 0;
|
||||
phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
|
||||
}
|
||||
vm_set_cr3(vm_dir_base);
|
||||
level0(vm_enable_paging);
|
||||
}
|
||||
|
||||
PRIVATE void phys_put32(addr, value)
|
||||
phys_bytes addr;
|
||||
u32_t value;
|
||||
{
|
||||
phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
|
||||
}
|
||||
|
||||
PRIVATE u32_t phys_get32(addr)
|
||||
phys_bytes addr;
|
||||
{
|
||||
u32_t value;
|
||||
|
||||
phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
PRIVATE void vm_set_cr3(value)
|
||||
u32_t value;
|
||||
{
|
||||
vm_cr3= value;
|
||||
level0(set_cr3);
|
||||
}
|
||||
|
||||
PRIVATE void set_cr3()
|
||||
{
|
||||
write_cr3(vm_cr3);
|
||||
}
|
||||
|
||||
PRIVATE void vm_enable_paging(void)
|
||||
{
|
||||
u32_t cr0;
|
||||
|
||||
cr0= read_cr0();
|
||||
write_cr0(cr0 | I386_CR0_PG);
|
||||
}
|
||||
|
||||
PRIVATE void map_range(base, size, offset)
|
||||
u32_t base;
|
||||
u32_t size;
|
||||
u32_t offset;
|
||||
{
|
||||
u32_t curr_pt, curr_pt_addr, entry;
|
||||
int dir_ent, pt_ent;
|
||||
|
||||
if (base % PAGE_SIZE != 0)
|
||||
panic("map_range: bad base", base);
|
||||
if (size % PAGE_SIZE != 0)
|
||||
panic("map_range: bad size", size);
|
||||
if (offset % PAGE_SIZE != 0)
|
||||
panic("map_range: bad offset", offset);
|
||||
|
||||
curr_pt= -1;
|
||||
curr_pt_addr= 0;
|
||||
while (size != 0)
|
||||
{
|
||||
dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
|
||||
pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
|
||||
if (dir_ent != curr_pt)
|
||||
{
|
||||
/* Get address of page table */
|
||||
curr_pt= dir_ent;
|
||||
curr_pt_addr= phys_get32(vm_cr3 +
|
||||
dir_ent * I386_VM_PT_ENT_SIZE);
|
||||
curr_pt_addr &= I386_VM_ADDR_MASK;
|
||||
}
|
||||
entry= offset | I386_VM_USER | I386_VM_WRITE |
|
||||
I386_VM_PRESENT;
|
||||
#if 0 /* Do we need this for memory mapped I/O? */
|
||||
entry |= I386_VM_PCD | I386_VM_PWT;
|
||||
#endif
|
||||
phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
|
||||
offset += PAGE_SIZE;
|
||||
base += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user