*** empty log message ***

This commit is contained in:
Jorrit Herder
2005-04-29 15:36:43 +00:00
parent 0e869cdd44
commit 89ac678b9b
78 changed files with 1293 additions and 2858 deletions

View File

@@ -21,7 +21,7 @@ LIBS = -lsys -lutils -ltimers
HEAD = mpx.o
OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \
i8259.o exception.o system.o clock.o memory.o misc.o \
i8259.o exception.o system.o clock.o misc.o \
dummy.o \
rtl8139.o pci.o pci_table.o
@@ -91,10 +91,6 @@ main.o: $h/com.h
main.o: proc.h
main.o: sendmask.h
memory.o: $a
memory.o: proc.h
memory.o: protect.h
misc.o: $a
misc.o: $i/stdlib.h
misc.o: $h/com.h
@@ -175,9 +171,7 @@ system/system.a: system/irqctl.c
system/system.a: system/misc.c
system/system.a: system/proctl.c
system/system.a: system/sigctl.c
system/system.a: system/srvrctl.c
system/system.a: system/sysctl.c
system/system.a: system/tracing.c
system/system.a: system/debugging.c
system/system.a: system/do_copy.c
system/system.a: system/do_vcopy.c

View File

@@ -222,7 +222,7 @@ irq_hook_t *hook;
clock_t now;
/* Acknowledge the PS/2 clock interrupt. */
if (ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
/* Update user and system accounting times. Charge the current process for
* user time. If the current process is not billable, that is, if a non-user

View File

@@ -9,7 +9,7 @@
/* To translate an address in kernel space to a physical address. This is
* the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly.
*/
#define vir2phys(vir) (data_base + (vir_bytes) (vir))
#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
/* Constants used in virtual_copy(). Values must be 0 and 1, respectively! */
#define _SRC_ 0
@@ -27,6 +27,9 @@
/* How many bytes for (port,value)-pairs vector to copy in. */
#define VDEVIO_BUF_SIZE 128
/* How many elements in vector of virtual copy requests. */
#define VCOPY_VEC_SIZE 16
/* Program stack words and masks. */
#define INIT_PSW 0x0200 /* initial psw */
#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */

View File

@@ -62,7 +62,7 @@ unsigned vec_nr;
}
/* Exception in system code. This is not supposed to happen. */
if (ep->msg == NIL_PTR || processor < ep->minprocessor)
if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor)
kprintf("\nIntel-reserved exception %d\n", vec_nr);
else
kprintf("\n%s\n", karg(ep->msg));

View File

@@ -16,10 +16,12 @@ EXTERN int shutting_down; /* TRUE if the system is shutting down */
EXTERN struct proc *shutdown_process; /* process awaiting shutdown of */
EXTERN timer_t shutdown_timer; /* watchdog function called after timeout */
/* Kernel memory. */
EXTERN phys_bytes code_base; /* base of kernel code */
EXTERN phys_bytes data_base; /* base of kernel data */
/* Kernel information structures. This groups vital kernel information. */
EXTERN phys_bytes aout; /* address of a.out headers */
EXTERN struct kinfo kinfo; /* kernel information for users */
EXTERN struct machine machine; /* machine information for users */
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
/* Low level notifications may be put on the 'held' queue to prevent races. */
EXTERN struct proc *held_head; /* head of queue of held-up interrupts */
@@ -29,29 +31,11 @@ EXTERN unsigned char k_reenter; /* kernel reentry count (entry count less 1)*/
/* Process table. Here to stop too many things having to include proc.h. */
EXTERN struct proc *proc_ptr; /* pointer to currently running process */
/* Memory sizes. */
EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
EXTERN phys_clicks tot_mem_size; /* total system memory size */
/* Miscellaneous. */
EXTERN unsigned lost_ticks; /* clock ticks counted outside the clock task */
#if (CHIP == INTEL)
/* Machine type. */
EXTERN int pc_at; /* PC-AT compatible hardware interface */
EXTERN int ps_mca; /* PS/2 with Micro Channel */
EXTERN unsigned int processor; /* 86, 186, 286, 386, ... */
#if _WORD_SIZE == 2
EXTERN int protected_mode; /* nonzero if running in Intel protected mode*/
#else
#define protected_mode 1 /* 386 mode implies protected mode */
#endif
/* Video card types. */
EXTERN int ega; /* nonzero if console is EGA */
EXTERN int vga; /* nonzero if console is VGA */
/* Interrupt related variables. */
EXTERN struct irqtab irqtab[NR_IRQ_VECTORS]; /* table with IRQ policies */
EXTERN irq_hook_t *irq_hooks[NR_IRQ_VECTORS]; /* list of IRQ handlers */
@@ -59,11 +43,8 @@ EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */
EXTERN int irq_use; /* bit map of all in-use irq's */
/* Miscellaneous. */
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
EXTERN reg_t mon_ss, mon_sp; /* monitor stack */
EXTERN int mon_return; /* true if return to the monitor possible */
EXTERN phys_bytes mon_params; /* boot parameter block passed in/out */
EXTERN size_t mon_parmsize; /* boot parameter block size */
/* Variables that are initialized elsewhere are just extern here. */
extern struct system_image image[]; /* system image processes (table.c) */

View File

@@ -45,18 +45,18 @@ int mine;
int i;
lock();
if (protected_mode) {
if (machine.protected) {
/* The AT and newer PS/2 have two interrupt controllers, one master,
* one slaved at IRQ 2. (We don't have to deal with the PC that
* has just one controller, because it must run in real mode.)
*/
outb(INT_CTL, ps_mca ? ICW1_PS : ICW1_AT);
outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
/* ICW2 for master */
outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
outb(INT_CTLMASK, ICW4_AT);
outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
outb(INT2_CTL, ps_mca ? ICW1_PS : ICW1_AT);
outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
/* ICW2 for slave */
outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */

View File

@@ -30,6 +30,7 @@
.define _reset ! reset the system
.define _idle_task ! task executed when there is no work
.define _level0 ! call a function at level 0
.define _read_tsc ! read the cycle counter (Pentium and up)
! The routines only guarantee to preserve the registers the C compiler
! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
@@ -495,3 +496,22 @@ _level0:
mov (_level0_func), eax
int LEVEL0_VECTOR
ret
!*===========================================================================*
!* read_tsc *
!*===========================================================================*
! PUBLIC void read_tsc(unsigned long *low, unsigned long *high);
! Read the cycle counter of the CPU. Pentium and up.
.align 16
_read_tsc:
.data1 0x0f ! this is the RDTSC instruction
.data1 0x31 ! it places the TSC in EDX:EAX
push ebp
mov ebp, 8(esp)
mov (ebp), edx
mov ebp, 12(esp)
mov (ebp), eax
pop ebp
ret

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,6 @@
* Changes:
* Nov 24, 2004 simplified main() with system image (Jorrit N. Herder)
* Oct 21, 2004 moved copyright to announce() (Jorrit N. Herder)
* Sep 30, 2004 moved mem_init() to this file (Jorrit N. Herder)
* Sep 04, 2004 created stop_sequence() to cleanup (Jorrit N. Herder)
* Aug 20, 2004 split wreboot() and shutdown() (Jorrit N. Herder)
* Jun 15, 2004 moved wreboot() to this file (Jorrit N. Herder)
@@ -42,8 +41,8 @@ PUBLIC void main()
register struct proc *rp;
register int i;
int hdrindex; /* index to array of a.out headers */
phys_clicks text_base;
vir_clicks text_clicks;
phys_clicks text_base, bootdev_base;
vir_clicks text_clicks, bootdev_clicks;
vir_clicks data_clicks;
reg_t ktsb; /* kernel task stack base */
struct memory *memp;
@@ -53,9 +52,6 @@ PUBLIC void main()
/* Initialize the interrupt controller. */
intr_init(1);
/* Make free memory list from memory sizes passed by boot monitor. */
mem_init();
/* Clear the process table. Anounce each slot as empty and
* set up mappings for proc_addr() and proc_number() macros.
*/
@@ -90,7 +86,7 @@ PUBLIC void main()
}
ktsb += ttp->stksize; /* point to high end of stack */
rp->p_reg.sp = ktsb; /* this task's initial stack ptr */
text_base = code_base >> CLICK_SHIFT;
text_base = kinfo.code_base >> CLICK_SHIFT;
/* processes that are in the kernel */
hdrindex = 0; /* all use the first a.out header */
} else {
@@ -150,44 +146,37 @@ PUBLIC void main()
/* Code and data segments must be allocated in protected mode. */
alloc_segments(rp);
}
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
/* This actually is not needed, because ready() already set 'proc_ptr' to
* first task that was announced ready.
*/
lock_pick_proc();
/* Expect an image of the root FS to be loaded into memory as well. The
* root FS image is located directly after the programs.
#if ENABLE_BOOTDEV
/* Expect an image of the boot device to be loaded into memory as well.
* The boot device is the last module that is loaded into memory, and,
* for example, can contain the root FS (useful for embedded systems).
*/
hdrindex ++;
phys_copy(aout+hdrindex * A_MINHDR, vir2phys(&e_hdr), (phys_bytes) A_MINHDR);
kprintf("Root FS image found: %s\n", (e_hdr.a_flags&A_IMG)? "yes" : "no");
phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
if (e_hdr.a_flags & A_IMG) {
kprintf("Size of root FS: %u, ", e_hdr.a_data);
kprintf("base : %u, ", e_hdr.a_syms);
kprintf("header size : %u, ", e_hdr.a_hdrlen);
rp = proc_addr(MEMORY);
rp->p_farmem[0].mem_phys = e_hdr.a_syms;
rp->p_farmem[0].mem_len = e_hdr.a_data;
kinfo.bootdev_base = e_hdr.a_syms;
kinfo.bootdev_size = e_hdr.a_data;
/* Remove from free list, to prevent being overwritten. */
text_base = e_hdr.a_syms >> CLICK_SHIFT;
text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* Common I&D */
data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
bootdev_base = e_hdr.a_syms >> CLICK_SHIFT;
bootdev_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
for (memp = mem; memp < &mem[NR_MEMS]; memp++) {
if (memp->base == text_base) {
kprintf("Memory removed from free list.\n", NO_ARG);
memp->base += text_clicks + data_clicks;
memp->size -= text_clicks + data_clicks;
if (memp->base == bootdev_base) {
memp->base += bootdev_clicks;
memp->size -= bootdev_clicks;
}
}
}
#endif
/* MINIX and all system services have been loaded. Announce to the user.
* Then go to the assembly code to start running the current process.
/* This actually is not needed, because ready() already set 'proc_ptr.' */
lock_pick_proc();
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
/* MINIX is now ready. Display the startup banner to the user and return
* to the assembly code to start running the current process.
*/
announce();
restart();
@@ -201,14 +190,18 @@ PUBLIC void main()
PRIVATE void announce(void)
{
/* Display the MINIX startup banner. */
kprintf("MINIX %s Copyright 2001 Prentice-Hall, Inc.\n",
karg(OS_RELEASE "." OS_VERSION));
kprintf("MINIX %s. Copyright 2001 Prentice-Hall, Inc.\n",
karg(kinfo.version));
#if (CHIP == INTEL)
/* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode\n\n",
protected_mode ? karg("32-bit protected") : karg("real"));
machine.protected ? karg("32-bit protected") : karg("real"));
#endif
/* Check if boot device was loaded with the kernel. */
if (kinfo.bootdev_base > 0)
kprintf("Image of /dev/boot loaded. Size: %u KB.\n", kinfo.bootdev_size);
}
@@ -274,7 +267,7 @@ timer_t *tp;
/* See if the last process' shutdown was successfull. Else, force exit. */
if (p != NIL_PROC) {
kprintf("[%s]\n", isalivep(p) ? "FAILED" : "OK");
kprintf("[%s]\n", isalivep(p) ? karg("FAILED") : karg("OK"));
if (isalivep(p))
clear_proc(p->p_nr); /* now force process to exit */
}
@@ -289,8 +282,8 @@ timer_t *tp;
if (p == NIL_PROC) p = BEG_PROC_ADDR;
while (TRUE) {
if (isalivep(p) && p->p_type == level) { /* found a process */
kprintf("- Stopping %s ", p->p_name);
kprintf("%s ... ", types[p->p_type]);
kprintf("- Stopping %s ", karg(p->p_name));
kprintf("%s ... ", karg(types[p->p_type]));
shutdown_process = p; /* directly continue if exited */
notify(proc_number(p), HARD_STOP);
set_timer(tp, get_uptime()+STOP_TICKS, stop_sequence);
@@ -336,15 +329,15 @@ timer_t *tp;
* For RBT_MONITOR, the MM has provided the program.
*/
if (how == RBT_HALT) {
phys_copy(vir2phys(" "), mon_params, 2);
phys_copy(vir2phys("delay;"), kinfo.params_base, 7);
} else if (how == RBT_REBOOT) {
phys_copy(vir2phys("delay;boot"), mon_params, 11);
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
}
level0(monitor);
}
/* Stop BIOS memory test. */
phys_copy(vir2phys(&magic), (phys_bytes) ADR_MEM_CHECK, LEN_MEM_CHECK);
phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE);
/* Reset the system by jumping to the reset address (real mode), or by
* forcing a processor shutdown (protected mode).

View File

@@ -1,120 +0,0 @@
/* Entry points into this file:
* mem_init: create a list a free memory
* alloc_segments: allocate segments for 8088 or higher processor
*/
#include "kernel.h"
#include "protect.h"
#include "proc.h"
#if (CHIP == INTEL)
/* In real mode only 1M can be addressed, and in 16-bit protected we can go
* no further than we can count in clicks. (The 286 is further limited by
* its 24 bit address bus, but we can assume in that case that no more than
* 16M memory is reported by the BIOS.)
*/
#define MAX_REAL 0x00100000L
#define MAX_16BIT (0xFFF0L << CLICK_SHIFT)
/*=========================================================================*
* mem_init *
*=========================================================================*/
PUBLIC void mem_init()
{
/* Initialize the free memory list from the 'memory' boot variable. Translate
* the byte offsets and sizes in this list to clicks, properly truncated. Also
* make sure that we don't exceed the maximum address space of the 286 or the
* 8086, i.e. when running in 16-bit protected mode or real mode.
*/
long base, size, limit;
char *s, *end; /* use to parse boot variable */
int i;
struct memory *memp;
#if _WORD_SIZE == 2
unsigned long max_address;
#endif
/* The available memory is determined by MINIX' boot loader as a list of
* (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
* in boot.s. The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
* b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1
* and b2:s2 are combined if the memory is adjacent.
*/
s = getkenv("memory"); /* get memory boot variable */
tot_mem_size = 0;
for (i = 0; i < NR_MEMS; i++) {
memp = &mem[i]; /* result is stored here */
base = size = 0;
if (*s != 0) { /* end of boot variable */
/* Expect base to be read (end != s) and ':' as next char. */
base = kstrtoul(s, &end, 0x10); /* get number */
if (end != s && *end == ':') s = ++end; /* skip ':' */
else *s=0; /* fake end for next; should not happen */
/* Expect size to be read and skip ',', unless at end. */
size = kstrtoul(s, &end, 0x10); /* get number */
if (end != s && *end == ',') s = ++end; /* skip ',' */
else if (end != s && *end == 0) s = end; /* end found */
else *s=0; /* fake end for next; should not happen */
}
limit = base + size;
#if _WORD_SIZE == 2
max_address = protected_mode ? MAX_16BIT : MAX_REAL;
if (limit > max_address) limit = max_address;
#endif
base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
limit &= ~(long)(CLICK_SIZE-1);
if (limit <= base) continue;
memp->base = base >> CLICK_SHIFT;
memp->size = (limit - base) >> CLICK_SHIFT;
tot_mem_size += memp->size;
}
}
/*==========================================================================*
* alloc_segments *
*==========================================================================*/
PUBLIC void alloc_segments(rp)
register struct proc *rp;
{
/* This is called at system initialization from main() and by do_newmap().
* The code has a separate function because of all hardware-dependencies.
* Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
*/
phys_bytes code_bytes;
phys_bytes data_bytes;
int privilege;
if (protected_mode) {
data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
if (rp->p_memmap[T].mem_len == 0)
code_bytes = data_bytes; /* common I&D, poor protect */
else
code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
privilege = (isidlep(rp) || istaskp(rp)) ?
TASK_PRIVILEGE : USER_PRIVILEGE;
init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
(phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
data_bytes, privilege);
rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
#if _WORD_SIZE == 4
rp->p_reg.gs =
rp->p_reg.fs =
#endif
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
} else {
rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
}
}
#endif /* (CHIP == INTEL) */

View File

@@ -1,762 +0,0 @@
#
! This file, mpx88.s, is included by mpx.s when Minix is compiled for
! 16-bit Intel CPUs. The alternative mpx386.s is compiled for 32-bit CPUs.
!
! This file contains the assembler startup code for Minix and the 16-bit
! interrupt handlers. It cooperates with cstart.c to set up a good
! environment for main().
! This file is part of the lowest layer of the MINIX kernel. The other part
! is "proc.c". The lowest layer does process switching and message handling.
! Every transition to the kernel goes through this file. Transitions are
! caused by sending/receiving messages and by most interrupts. (RS232
! interrupts may be handled in the file "rs2.s" and then they rarely enter
! the kernel.)
! Transitions to the kernel may be nested. The initial entry may be with a
! system call, exception or hardware interrupt; reentries may only be made
! by hardware interrupts. The count of reentries is kept in "k_reenter".
! It is important for deciding whether to switch to the kernel stack and
! for protecting the message passing code in "proc.c".
! For the message passing trap, most of the machine state is saved in the
! proc table. (Some of the registers need not be saved.) Then the stack is
! switched to "k_stack", and interrupts are reenabled. Finally, the system
! call handler (in C) is called. When it returns, interrupts are disabled
! again and the code falls into the restart routine, to finish off held-up
! interrupts and run the process or task whose pointer is in "proc_ptr".
! Hardware interrupt handlers do the same, except (1) The entire state must
! be saved. (2) There are too many handlers to do this inline, so the save
! routine is called. A few cycles are saved by pushing the address of the
! appropiate restart routine for a return later. (3) A stack switch is
! avoided when the stack is already switched. (4) The (master) 8259 interrupt
! controller is reenabled centrally in save(). (5) Each interrupt handler
! masks its interrupt line using the 8259 before enabling (other unmasked)
! interrupts, and unmasks it after servicing the interrupt. This limits the
! nest level to the number of lines and protects the handler from itself.
! For communication with the boot monitor at startup time some constant
! data are compiled into the beginning of the text segment. This facilitates
! reading the data at the start of the boot process, since only the first
! sector of the file needs to be read.
! Some data storage is also allocated at the end of this file. This data
! will be at the start of the data segment of the kernel and will be read
! and modified by the boot monitor before the kernel starts.
#include <minix/config.h>
#include <minix/const.h>
#include <minix/com.h>
#include "const.h"
#include "sconst.h"
#include "protect.h"
! The external entry points into this file are:
! Note: in assembly language the .define statement applied to a function name
! is loosely equivalent to a prototype in C code -- it makes it possible to
! link to an entity declared in the assembly code but does not create
! the entity.
.define _int00 ! handlers for traps and exceptions
.define _int01
.define _int02
.define _int03
.define _int04
.define _int05
.define _int06
.define _int07
.define _hwint00 ! handlers for hardware interrupts
.define _hwint01
.define _hwint02
.define _hwint03
.define _hwint04
.define _hwint05
.define _hwint06
.define _hwint07
.define _hwint08
.define _hwint09
.define _hwint10
.define _hwint11
.define _hwint12
.define _hwint13
.define _hwint14
.define _hwint15
.define _restart ! start running a task or process
.define save ! save the machine state in the proc table
.define _s_call ! process or task wants to send or receive a message
! Exported variables.
.define kernel_ds
.define begbss
.define begdata
.text
!*===========================================================================*
!* MINIX *
!*===========================================================================*
MINIX: ! this is the entry point for the MINIX kernel
jmp over_kernel_ds ! skip over the next few bytes
.data2 CLICK_SHIFT ! for the monitor: memory granularity
kernel_ds:
.data2 0x01B4 ! boot monitor flags: (later kernel DS)
! call in 8086 mode, make bss, make stack,
! load low, don`t patch, will return,
! (has own INT calls), memory vector,
! new boot code return
over_kernel_ds:
! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds
! right. The ss register still references the monitor data segment.)
push bp
mov bp, sp
push si
push di
cmp 4(bp), #0 ! monitor code segment is
jz noret ! nonzero if return possible
inc _mon_return
noret: mov _mon_ss, ss ! save stack location for later return
mov _mon_sp, sp
! Locate boot parameters, set up kernel segment registers and stack.
mov bx, 6(bp) ! boot parameters offset
mov dx, 8(bp) ! boot parameters length
mov ax, 10(bp) ! address of a.out headers
mov _aout+0, ax
mov ax, 12(bp)
mov _aout+2, ax
mov ax, ds ! kernel data
mov es, ax
mov ss, ax
mov sp, #k_stktop ! set sp to point to the top of kernel stack
! Real mode needs to get kernel DS from the code segment. Protected mode
! needs CS in the jump back to real mode.
cseg mov kernel_cs, cs
cseg mov kernel_ds, ds
! Call C startup code to set up a proper environment to run main().
push dx
push bx
push _mon_ss
push ds
push cs
call _cstart ! cstart(cs, ds, mds, parmoff, parmlen)
add sp, #5*2
cmp _protected_mode, #0
jz nosw ! ok to switch to protected mode?
call klib_init_prot ! initialize klib functions for protected mode
call real2prot ! switch to protected mode
push #0 ! set flags to known good state
popf ! especially, clear nested task and int enable
nosw:
jmp _main ! main()
!*===========================================================================*
!* interrupt handlers *
!*===========================================================================*
!*===========================================================================*
!* hwint00 - 07 *
!*===========================================================================*
! Note that the first few lines are a macro
#define hwint_master(irq) \
call save /* save interrupted process state */;\
mov si, *[2*irq] /* load array index offset */;\
mov di, *[1<<irq] /* irq mask bit */;\
jmp hwint_master /* continue with common code */
hwint_master:
inb INT_CTLMASK
or ax, di ! al |= (1 << irq)
outb INT_CTLMASK ! disable the irq
movb al, *ENABLE
outb INT_CTL ! reenable master 8259
mov cx, _irq_hooks(si) ! irq_hooks[irq]
push cx
sti ! enable interrupts
call _intr_handle ! intr_handle(irq_hooks[irq])
cli ! disable interrupts
pop cx
cmp _irq_actids(si), *0 ! interrupt still active?
jnz 0f
inb INT_CTLMASK
not di
and ax, di ! al &= ~(1 << irq)
outb INT_CTLMASK ! enable the irq
0: ret ! restart (another) process
! Each of these entry points is an expansion of the hwint_master macro
_hwint00: ! Interrupt routine for irq 0 (the clock).
hwint_master(0)
_hwint01: ! Interrupt routine for irq 1 (keyboard)
hwint_master(1)
_hwint02: ! Interrupt routine for irq 2 (cascade!)
hwint_master(2)
_hwint03: ! Interrupt routine for irq 3 (second serial)
hwint_master(3)
_hwint04: ! Interrupt routine for irq 4 (first serial)
hwint_master(4)
_hwint05: ! Interrupt routine for irq 5 (XT winchester)
hwint_master(5)
_hwint06: ! Interrupt routine for irq 6 (floppy)
hwint_master(6)
_hwint07: ! Interrupt routine for irq 7 (printer)
hwint_master(7)
!*===========================================================================*
!* hwint08 - 15 *
!*===========================================================================*
! Note that the first few lines are a macro
#define hwint_slave(irq) \
call save /* save interrupted process state */;\
mov si, *[2*irq] /* load array index offset */;\
mov di, *[1<<[irq-8]] /* irq mask bit */;\
jmp hwint_slave /* continue with common code */
hwint_slave:
inb INT2_CTLMASK
or ax, di ! al |= (1 << (irq-8))
outb INT2_CTLMASK ! disable the irq
movb al, *ENABLE
outb INT_CTL ! reenable master 8259
mov cx, _irq_hooks(si) ! irq_hooks[irq]
outb INT2_CTL ! reenable slave 8259
push cx
sti ! enable interrupts
call _intr_handle ! intr_handle(irq_hooks[irq])
cli ! disable interrupts
pop cx
cmp _irq_actids(si), *0 ! interrupt still active?
jnz 0f
inb INT2_CTLMASK
not di
and ax, di ! al &= ~(1 << (irq-8))
outb INT2_CTLMASK ! enable the irq
0: ret ! restart (another) process
! Each of these entry points is an expansion of the hwint_slave macro
_hwint08: ! Interrupt routine for irq 8 (realtime clock)
hwint_slave(8)
_hwint09: ! Interrupt routine for irq 9 (irq 2 redirected)
hwint_slave(9)
_hwint10: ! Interrupt routine for irq 10
hwint_slave(10)
_hwint11: ! Interrupt routine for irq 11
hwint_slave(11)
_hwint12: ! Interrupt routine for irq 12
hwint_slave(12)
_hwint13: ! Interrupt routine for irq 13 (FPU exception)
hwint_slave(13)
_hwint14: ! Interrupt routine for irq 14 (AT winchester)
hwint_slave(14)
_hwint15: ! Interrupt routine for irq 15
hwint_slave(15)
!*===========================================================================*
!* save *
!*===========================================================================*
save: ! save the machine state in the proc table.
! In protected mode a jump to p_save is patched over the following
! code during initialization.
cld ! set direction flag to a known value
push ds
push si
cseg mov ds,kernel_ds
incb _k_reenter ! from -1 if not reentering
jnz push_current_stack ! stack is already kernel stack
mov si,_proc_ptr
mov AXREG(si),ax
mov BXREG(si),bx
mov CXREG(si),cx
mov DXREG(si),dx
pop SIREG(si)
mov DIREG(si),di
mov BPREG(si),bp
mov ESREG(si),es
pop DSREG(si)
pop bx ! return adr
pop PCREG(si)
pop CSREG(si)
pop PSWREG(si)
mov SPREG(si),sp
mov SSREG(si),ss
mov dx,ds
mov ss,dx
mov sp,#k_stktop
mov ax,#_restart ! build return address for interrupt handler
push ax
stack_switched:
mov es,dx
jmp (bx)
push_current_stack:
push es
push bp
push di
push dx
push cx
push bx
push ax
mov bp,sp
mov bx,18(bp) ! get the return adr; it becomes junk on stack
mov ax,#restart1
push ax
mov dx,ss
mov ds,dx
jmp stack_switched
!*===========================================================================*
!* s_call *
!*===========================================================================*
! This is real mode version. Alternate (_p_s_call) will be used in
! protected mode
_s_call: ! System calls are vectored here.
! Do save routine inline for speed,
! but do not save ax, bx, cx, dx,
! since C does not require preservation,
! and ax returns the result code anyway.
! Regs bp, si, di get saved by sys_call as
! well, but it is impractical not to preserve
! them here, in case context gets switched.
! Some special-case code in pick_proc()
! could avoid this.
cld ! set direction flag to a known value
push ds
push si
cseg mov ds,kernel_ds
incb _k_reenter
mov si,_proc_ptr
pop SIREG(si)
mov DIREG(si),di
mov BPREG(si),bp
mov ESREG(si),es
pop DSREG(si)
pop PCREG(si)
pop CSREG(si)
pop PSWREG(si)
mov SPREG(si),sp
mov SSREG(si),ss
mov dx,ds
mov es,dx
mov ss,dx ! interrupt handlers may not make system calls
mov sp,#k_stktop ! so stack is not already switched
! end of inline save
! now set up parameters for C routine sys_call
push bx ! pointer to user message
push ax ! src/dest
push cx ! SEND/RECEIVE/BOTH
sti ! allow SWITCHER to be interrupted
call _sys_call ! sys_call(function, src_dest, m_ptr)
! caller is now explicitly in proc_ptr
mov AXREG(si),ax ! sys_call MUST PRESERVE si
cli
! Fall into code to restart proc/task running.
!*===========================================================================*
!* restart *
!*===========================================================================*
_restart:
! Flush any held-up interrupts.
! This reenables interrupts, so the current interrupt handler may reenter.
! This does not matter, because the current handler is about to exit and no
! other handlers can reenter since flushing is only done when k_reenter == 0.
! In protected mode a jump to p_restart is patched over the following
! code during initialization.
cmp _held_head,#0 ! do fast test to usually avoid function call
jz over_call_unhold
call _unhold ! this is rare so overhead is acceptable
over_call_unhold:
mov si,_proc_ptr
decb _k_reenter
mov ax,AXREG(si) ! start restoring registers from proc table
! could make AXREG == 0 to use lodw here
mov bx,BXREG(si)
mov cx,CXREG(si)
mov dx,DXREG(si)
mov di,DIREG(si)
mov bp,BPREG(si)
mov es,ESREG(si)
mov ss,SSREG(si)
mov sp,SPREG(si)
push PSWREG(si) ! fake interrupt stack frame
push CSREG(si)
push PCREG(si)
! could put si:ds together to use
! lds si,SIREG(si)
push DSREG(si)
mov si,SIREG(si)
pop ds
iret
restart1:
decb _k_reenter
pop ax
pop bx
pop cx
pop dx
pop di
pop bp
pop es
pop si
pop ds
add sp,#2 ! skip return adr
iret
!*===========================================================================*
!* int00-07 *
!*===========================================================================*
! These are entry points for exceptions (processor generated interrupts,
! usually caused by error conditions such as an attempt to divide by zero)
_int00: ! interrupt through vector 0
push ax
movb al,#0
jmp exception
_int01: ! interrupt through vector 1, etc
push ax
movb al,#1
jmp exception
_int02:
push ax
movb al,#2
jmp exception
_int03:
push ax
movb al,#3
jmp exception
_int04:
push ax
movb al,#4
jmp exception
_int05:
push ax
movb al,#5
jmp exception
_int06:
push ax
movb al,#6
jmp exception
_int07:
push ax
movb al,#7
!jmp exception
exception:
cseg movb ex_number,al ! it is cumbersome to get this into dseg
pop ax
call save
cseg push ex_number ! high byte is constant 0
call _exception ! do whatever is necessary (sti only if safe)
add sp,#2
cli
ret
!*===========================================================================*
!* level0_call *
!*===========================================================================*
_level0_call:
call save
jmp @_level0_func
!*===========================================================================*
!* data *
!*===========================================================================*
! NB some variables are stored in code segment.
ex_number: ! exception number
.space 2
!*===========================================================================*
!* variants for 286 protected mode *
!*===========================================================================*
! Most routines are different in 286 protected mode.
! The only essential difference is that an interrupt in protected mode
! (usually) switches the stack, so there is less to do in software.
! These functions are reached along jumps patched in by klib_init_prot():
.define p_restart ! replaces _restart
.define p_save ! replaces save
! These exception and software-interrupt handlers are enabled by the new
! interrupt vector table set up in protect.c:
.define _divide_error ! _int00
.define _single_step_exception ! _int01
.define _nmi ! _int02
.define _breakpoint_exception ! _int03
.define _overflow ! _int04
.define _bounds_check ! _int05
.define _inval_opcode ! _int06
.define _copr_not_available ! _int07
.define _double_fault ! (286 trap)
.define _copr_seg_overrun ! (etc)
.define _inval_tss
.define _segment_not_present
.define _stack_exception
.define _general_protection
.define _p_s_call ! _s_call
.define _level0_call
! The hardware interrupt handlers need not be altered apart from putting
! them in the new table (save() handles the differences).
! Some of the intxx handlers (those for exceptions which do not push an
! error code) need not have been replaced, but the names here are better.
#include "protect.h"
/* Selected 286 tss offsets. */
#define TSS2_S_SP0 2
! imported variables
.extern _tss
.extern _level0_func
!*===========================================================================*
!* p_save *
!*===========================================================================*
! Save for 286 protected mode.
! This is much simpler than for 8086 mode, because the stack already points
! into process table, or has already been switched to the kernel stack.
p_save:
cld ! set direction flag to a known value
pusha ! save "general" registers
push ds ! save ds
push es ! save es
mov dx,ss ! ss is kernel data segment
mov ds,dx ! load rest of kernel segments
mov es,dx
mov bp,sp ! prepare to return
incb _k_reenter ! from -1 if not reentering
jnz set_p1_restart ! stack is already kernel stack
mov sp,#k_stktop
push #p_restart ! build return address for interrupt handler
jmp @RETADR-P_STACKBASE(bp)
set_p1_restart:
push #p1_restart
jmp @RETADR-P_STACKBASE(bp)
!*===========================================================================*
!* p_s_call *
!*===========================================================================*
_p_s_call:
cld ! set direction flag to a known value
sub sp,#6*2 ! skip RETADR, ax, cx, dx, bx, st
push bp ! stack already points into process table
push si
push di
push ds
push es
mov dx,ss
mov ds,dx
mov es,dx
incb _k_reenter
mov si,sp ! assumes P_STACKBASE == 0
mov sp,#k_stktop
! end of inline save
sti ! allow SWITCHER to be interrupted
! now set up parameters for C routine sys_call
push bx ! pointer to user message
push ax ! src/dest
push cx ! SEND/RECEIVE/BOTH
call _sys_call ! sys_call(function, src_dest, m_ptr)
! caller is now explicitly in proc_ptr
mov AXREG(si),ax ! sys_call MUST PRESERVE si
cli
! Fall into code to restart proc/task running.
p_restart:
! Flush any held-up interrupts.
! This reenables interrupts, so the current interrupt handler may reenter.
! This does not matter, because the current handler is about to exit and no
! other handlers can reenter since flushing is only done when k_reenter == 0.
cmp _held_head,#0 ! do fast test to usually avoid function call
jz p_over_call_unhold
call _unhold ! this is rare so overhead is acceptable
p_over_call_unhold:
mov si,_proc_ptr
lldt P_LDT_SEL(si) ! enable segment descriptors for task
lea ax,P_STACKTOP(si) ! arrange for next interrupt
mov _tss+TSS2_S_SP0,ax ! to save state in process table
mov sp,si ! assumes P_STACKBASE == 0
p1_restart:
decb _k_reenter
pop es
pop ds
popa
add sp,#2 ! skip return adr
iret ! continue process
!*===========================================================================*
!* exception handlers *
!*===========================================================================*
_divide_error:
push #DIVIDE_VECTOR
jmp p_exception
_single_step_exception:
push #DEBUG_VECTOR
jmp p_exception
_nmi:
push #NMI_VECTOR
jmp p_exception
_breakpoint_exception:
push #BREAKPOINT_VECTOR
jmp p_exception
_overflow:
push #OVERFLOW_VECTOR
jmp p_exception
_bounds_check:
push #BOUNDS_VECTOR
jmp p_exception
_inval_opcode:
push #INVAL_OP_VECTOR
jmp p_exception
_copr_not_available:
push #COPROC_NOT_VECTOR
jmp p_exception
_double_fault:
push #DOUBLE_FAULT_VECTOR
jmp errexception
_copr_seg_overrun:
push #COPROC_SEG_VECTOR
jmp p_exception
_inval_tss:
push #INVAL_TSS_VECTOR
jmp errexception
_segment_not_present:
push #SEG_NOT_VECTOR
jmp errexception
_stack_exception:
push #STACK_FAULT_VECTOR
jmp errexception
_general_protection:
push #PROTECTION_VECTOR
jmp errexception
!*===========================================================================*
!* p_exception *
!*===========================================================================*
! This is called for all exceptions which do not push an error code.
p_exception:
sseg pop ds_ex_number
call p_save
jmp p1_exception
!*===========================================================================*
!* errexception *
!*===========================================================================*
! This is called for all exceptions which push an error code.
errexception:
sseg pop ds_ex_number
sseg pop trap_errno
call p_save
p1_exception: ! Common for all exceptions.
push ds_ex_number
call _exception
add sp,#2
cli
ret
!*===========================================================================*
!* data *
!*===========================================================================*
.data
begdata:
.data2 0x526F ! this must be the first data entry (magic #)
.bss
begbss:
k_stack:
.space K_STACK_BYTES ! kernel stack
k_stktop: ! top of kernel stack
.comm ds_ex_number, 2
.comm trap_errno, 2

View File

@@ -19,7 +19,7 @@
* Oct 10, 2004 require BOTH for kernel sys_call() (Jorrit N. Herder)
* (to protect kernel tasks from being blocked)
* Sep 25, 2004 generalized notify() function (Jorrit N. Herder)
* Sep 23, 2004 removed MM sig check in mini_rec() (Jorrit N. Herder)
* Sep 23, 2004 removed PM sig check in mini_rec() (Jorrit N. Herder)
* Aug 19, 2004 generalized ready()/unready() (Jorrit N. Herder)
* Aug 18, 2004 added notify() function (Jorrit N. Herder)
* May 01, 2004 check p_sendmask in mini_send() (Jorrit N. Herder)
@@ -163,7 +163,7 @@ message *m_ptr; /* pointer to message in the caller's space */
/* Calls directed to the kernel may only be sendrec(), because tasks always
* reply and may not block if the caller doesn't do receive(). Users also
* may only use sendrec() to protect the MM and FS.
* may only use sendrec() to protect the process manager and file system.
*/
if ((iskernel(src_dst) || isuserp(caller_ptr)) && function != BOTH) {
result = ECALLDENIED; /* BOTH was required */

View File

@@ -14,6 +14,7 @@
* May 01, 2004 new p_sendmask to protect syscalls (Jorrit N. Herder)
*/
#include <minix/com.h>
#include "protect.h"
#include "const.h"
struct proc {
@@ -21,8 +22,7 @@ struct proc {
#if (CHIP == INTEL)
reg_t p_ldt_sel; /* selector in gdt giving ldt base and limit*/
struct segdesc_s p_ldt[4]; /* local descriptors for code and data */
/* 4 is LDT_SIZE - avoid include protect.h */
struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
#endif /* (CHIP == INTEL) */
#if (CHIP == M68000)
@@ -123,7 +123,7 @@ struct proc {
#define isalivep(p) ((p)->p_type > P_NONE)
#define isrxhardware(n) ((n) == ANY || (n) == HARDWARE)
#define iskernel(n) ((n) == CLOCK || (n) == SYSTASK)
#define issysentn(n) ((n) == FS_PROC_NR || (n) == MM_PROC_NR)
#define issysentn(n) ((n) == FS_PROC_NR || (n) == PM_PROC_NR)
#define issysentp(p) (issysentn((p)->p_nr))
#define isreservedp(p) ((p)->p_type == P_RESERVED)
#define isemptyp(p) ((p)->p_type == P_NONE)

View File

@@ -82,10 +82,6 @@ PUBLIC void prot_init()
/* Set up tables for protected mode.
* All GDT slots are allocated at compile time.
*/
extern int etext, end;
#define code_bytes ((vir_bytes) &etext) /* Size of code segment. */
#define data_bytes ((vir_bytes) &end) /* Size of data segment. */
struct gate_table_s *gtp;
struct desctableptr_s *dtp;
unsigned ldt_index;
@@ -149,8 +145,8 @@ PUBLIC void prot_init()
* (u32_t *) dtp->base = vir2phys(idt);
/* Build segment descriptors for tasks and interrupt handlers. */
init_codeseg(&gdt[CS_INDEX], code_base, code_bytes, INTR_PRIVILEGE);
init_dataseg(&gdt[DS_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
init_codeseg(&gdt[CS_INDEX], kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE);
init_dataseg(&gdt[DS_INDEX], kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE);
init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE);
/* Build scratch descriptors for functions in klib88. */
@@ -268,7 +264,7 @@ U16_t seg;
phys_bytes base;
struct segdesc_s *segdp;
if (!protected_mode) {
if (! machine.protected) {
base = hclick_to_physb(seg);
} else {
segdp = &gdt[seg >> 3];
@@ -292,7 +288,7 @@ phys_bytes phys;
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
*/
#if _WORD_SIZE == 2
if (!protected_mode) {
if (! machine.protected) {
*seg = phys / HCLICK_SIZE;
*off = phys % HCLICK_SIZE;
} else {
@@ -342,3 +338,51 @@ struct proc *pp;
*/
pp->p_reg.psw |= 0x3000;
}
/*==========================================================================*
* alloc_segments *
*==========================================================================*/
PUBLIC void alloc_segments(rp)
register struct proc *rp;
{
/* This is called at system initialization from main() and by do_newmap().
* The code has a separate function because of all hardware-dependencies.
* Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
*/
phys_bytes code_bytes;
phys_bytes data_bytes;
int privilege;
if (machine.protected) {
data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
if (rp->p_memmap[T].mem_len == 0)
code_bytes = data_bytes; /* common I&D, poor protect */
else
code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
privilege = (isidlep(rp) || istaskp(rp)) ?
TASK_PRIVILEGE : USER_PRIVILEGE;
init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
(phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
data_bytes, privilege);
rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
#if _WORD_SIZE == 4
rp->p_reg.gs =
rp->p_reg.fs =
#endif
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
} else {
rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
}
}

View File

@@ -4,7 +4,7 @@
#define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS)
/* spec. and LDT's */
#define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */
#define LDT_SIZE 4 /* contains CS, DS and two extras */
#define LDT_SIZE (2 + NR_REMOTE_SEGS) /* CS, DS and remote segments */
/* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */
#define GDT_INDEX 1 /* GDT descriptor */

View File

@@ -46,10 +46,6 @@ _PROTOTYPE( void prepare_shutdown, (int how) );
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
_PROTOTYPE( void shutdown, (struct timer *tp) );
/* memory.c */
_PROTOTYPE( void mem_init, (void) );
_PROTOTYPE( void alloc_segments, (struct proc *rp) );
/* misc.c */
_PROTOTYPE( void panic, (_CONST char *s, int n) );
@@ -145,6 +141,7 @@ _PROTOTYPE( void phys_outsw, (Port_t port, phys_bytes buf, size_t count));
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );
_PROTOTYPE( void read_tsc, (unsigned long *low, unsigned long *high) );
/* mpx*.s */
_PROTOTYPE( void idle_task, (void) );
@@ -202,6 +199,7 @@ _PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
_PROTOTYPE( phys_bytes seg2phys, (U16_t seg) );
_PROTOTYPE( void phys2seg, (u16_t *seg, vir_bytes *off, phys_bytes phys));
_PROTOTYPE( void enable_iop, (struct proc *pp) );
_PROTOTYPE( void alloc_segments, (struct proc *rp) );
#endif /* (CHIP == INTEL) */

View File

@@ -88,7 +88,7 @@
allow_all_mask \
deny(1, USER_PROC_NR)
#define MM_SENDMASK \
#define PM_SENDMASK \
deny_all_mask \
allow(1, IS_PROC_NR) /* output diagnostics */ \
allow(1, SYSTASK) \
@@ -120,7 +120,7 @@
allow((NR_CTRLRS >= 3), CTRLR(2)) \
allow((NR_CTRLRS >= 4), CTRLR(3)) \
allow(1, INIT_PROC_NR) \
allow(1, MM_PROC_NR) /* cooperates with memory manager */ \
allow(1, PM_PROC_NR) /* cooperates with process manager */ \
allow(1, USER_PROC_NR) /* reply to system calls */
#endif
@@ -154,12 +154,12 @@
#define INIT_SENDMASK \
deny_all_mask \
allow(1, FS_PROC_NR) /* init makes system calls to FS and MM */ \
allow(1, MM_PROC_NR)
allow(1, PM_PROC_NR)
#define USER_PROC_SENDMASK \
deny_all_mask \
allow(1, FS_PROC_NR) /* users can only make system calls */ \
allow(1, MM_PROC_NR) \
allow(1, PM_PROC_NR) \
allow(1, IS_PROC_NR) \
allow(ENABLE_TASKSERVER, TS_PROC_NR)

View File

@@ -11,10 +11,12 @@
#include "kernel.h"
#include "protect.h"
#include "proc.h"
/* Environment strings passed by loader. */
PRIVATE char k_environ[128*sizeof(char *)];
FORWARD _PROTOTYPE( void mem_init, (void) );
/*==========================================================================*
* cstart *
@@ -29,46 +31,127 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
*/
register char *envp;
unsigned mon_start;
extern int etext, end;
/* Decide if mode is protected; 386 or higher implies protected mode.
* This must be done first, because it is needed for, e.g., seg2phys().
* For 286 machines we cannot decide on protected mode, yet. This is
* done below.
*/
#if _WORD_SIZE != 2
machine.protected = 1;
#endif
/* Record where the kernel and the monitor are. */
code_base = seg2phys(cs);
data_base = seg2phys(ds);
kinfo.code_base = seg2phys(cs);
kinfo.code_size = (phys_bytes) &etext; /* size of code segment */
kinfo.data_base = seg2phys(ds);
kinfo.data_size = (phys_bytes) &end; /* size of data segment */
/* Initialize protected mode descriptors. */
prot_init();
/* Copy the boot parameters to kernel memory. */
mon_params = seg2phys(mds) + parmoff;
mon_parmsize = MAX(parmsize,sizeof(k_environ));
if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
phys_copy(mon_params, vir2phys(k_environ), (phys_bytes) parmsize);
kinfo.params_base = seg2phys(mds) + parmoff;
kinfo.params_size = MAX(parmsize,sizeof(k_environ)-2);
phys_copy(kinfo.params_base, vir2phys(k_environ), kinfo.params_size);
/* Type of VDU: */
envp = getkenv("video");
if (kstrcmp(envp, "ega") == 0) ega = TRUE;
if (kstrcmp(envp, "vga") == 0) vga = ega = TRUE;
/* Record miscellaneous information for user-space servers. */
kstrncpy(kinfo.version, OS_RELEASE "." OS_VERSION, 6);
kinfo.proc_addr = (vir_bytes) proc;
kinfo.kmem_base = vir2phys(0);
kinfo.kmem_size = (phys_bytes) &end;
/* Processor? */
processor = katoi(getkenv("processor")); /* 86, 186, 286, 386, ... */
machine.processor=katoi(getkenv("processor")); /* 86, 186, 286, 386, ... */
/* Decide if mode is protected for older machines. */
#if _WORD_SIZE == 2
machine.protected = machine.processor >= 286;
#endif
if (! machine.protected) mon_return = 0;
/* XT, AT or MCA bus? */
envp = getkenv("bus");
if (envp == NIL_PTR || kstrcmp(envp, "at") == 0) {
pc_at = TRUE;
} else
if (kstrcmp(envp, "mca") == 0) {
pc_at = ps_mca = TRUE;
machine.pc_at = TRUE; /* PC-AT compatible hardware */
} else if (kstrcmp(envp, "mca") == 0) {
machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */
}
/* Decide if mode is protected. */
/* Type of VDU: */
envp = getkenv("video"); /* EGA or VGA video unit */
if (kstrcmp(envp, "ega") == 0) machine.vdu_ega = TRUE;
if (kstrcmp(envp, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
/* Initialize free memory list from size passed by boot monitor. */
mem_init();
/* Return to assembler code to switch to protected mode (if 286),
* reload selectors and call main().
*/
}
/* In real mode only 1M can be addressed, and in 16-bit protected we can go
* no further than we can count in clicks. (The 286 is further limited by
* its 24 bit address bus, but we can assume in that case that no more than
* 16M memory is reported by the BIOS.)
*/
#define MAX_REAL 0x00100000L
#define MAX_16BIT (0xFFF0L << CLICK_SHIFT)
/*=========================================================================*
* mem_init *
*=========================================================================*/
PRIVATE void mem_init()
{
/* Initialize the free memory list from the 'memory' boot variable. Translate
* the byte offsets and sizes in this list to clicks, properly truncated. Also
* make sure that we don't exceed the maximum address space of the 286 or the
* 8086, i.e. when running in 16-bit protected mode or real mode.
*/
long base, size, limit;
char *s, *end; /* use to parse boot variable */
int i;
struct memory *memp;
#if _WORD_SIZE == 2
protected_mode = processor >= 286;
if (!protected_mode) mon_return = 0;
unsigned long max_address;
#endif
/* Return to assembler code to switch to protected mode (if 286), reload
* selectors and call main().
/* The available memory is determined by MINIX' boot loader as a list of
* (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
* in boot.s. The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
* b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1
* and b2:s2 are combined if the memory is adjacent.
*/
s = getkenv("memory"); /* get memory boot variable */
for (i = 0; i < NR_MEMS; i++) {
memp = &mem[i]; /* result is stored here */
base = size = 0;
if (*s != 0) { /* end of boot variable */
/* Expect base to be read (end != s) and ':' as next char. */
base = kstrtoul(s, &end, 0x10); /* get number */
if (end != s && *end == ':') s = ++end; /* skip ':' */
else *s=0; /* fake end for next; should not happen */
/* Expect size to be read and skip ',', unless at end. */
size = kstrtoul(s, &end, 0x10); /* get number */
if (end != s && *end == ',') s = ++end; /* skip ',' */
else if (end != s && *end == 0) s = end; /* end found */
else *s=0; /* fake end for next; should not happen */
}
limit = base + size;
#if _WORD_SIZE == 2
max_address = kinfo.protected ? MAX_16BIT : MAX_REAL;
if (limit > max_address) limit = max_address;
#endif
base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
limit &= ~(long)(CLICK_SIZE-1);
if (limit <= base) continue;
memp->base = base >> CLICK_SHIFT;
memp->size = (limit - base) >> CLICK_SHIFT;
}
}

View File

@@ -18,16 +18,16 @@
* umap_bios: map virtual address in BIOS_SEG to physical
* numap_local: umap_local D segment from proc nr instead of pointer
* virtual_copy: copy bytes from one virtual address to another
* vir_copy: copy bytes from one process to another
* generic_handler: interrupt handler for user-level device drivers
*
* Changes:
* Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
* Oct 29, 2004 new clear_proc() function (Jorrit N. Herder)
* Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
* Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
* Sep 10, 2004 system call functions in library (Jorrit N. Herder)
* 2003/2004 various new syscalls (see syslib.h) (Jorrit N. Herder)
* 2004 to 2005 various new syscalls (see syslib.h) (Jorrit N. Herder)
*/
#include "kernel.h"
@@ -40,59 +40,24 @@
#include <minix/callnr.h>
#include "sendmask.h"
#if (CHIP == INTEL)
#include <ibm/memory.h>
#include "protect.h"
#endif
/* Declaration of the call vector that defines the mapping of system calls
* to handler functions. The vector is initialized in sys_init() with map(),
* which makes sure the system call numbers are ok. No space is allocated,
* because the dummy is declared extern. If an illegal call is given, the
* array size will be negative and this won't compile.
*/
PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);
#define map(call_nr, handler) \
{extern int dummy[NR_SYS_CALLS > (unsigned) (call_nr) ? 1 : -1];} \
call_vec[(call_nr)] = (handler)
FORWARD _PROTOTYPE( void initialize, (void));
/* Declaration of the call vector that defines the mapping of system calls to
* handler functions. The order of the do_call handler functions must match
* the SYS_CALL numbering defined in <minix/com.h>.
*/
PUBLIC _PROTOTYPE (int (*call_vec[]), (message *m_ptr) ) = {
do_times, /* 0: get uptime and process CPU time consumption */
do_xit, /* 1: informs kernel that a process has exited */
do_unused, /* 2: unused */
do_sigctl, /* 3: MM signal control (incl. POSIX style handling) */
do_fork, /* 4: informs kernel that a process has forked */
do_newmap, /* 5: allows MM to set up a process memory map */
do_copy, /* 6: copy a block of data between processes */
do_exec, /* 7: sets program counter and stack pointer after EXEC */
do_unused, /* 8: unused */
do_abort, /* 9: MM or FS cannot go on; abort MINIX */
do_kill, /* 10: cause a signal to be sent via MM */
do_umap, /* 11: compute the physical address for a virtual address */
do_unused, /* 12: returns the next free chunk of physical memory */
do_trace, /* 13: request a trace operation */
do_vcopy, /* 14: request a series of data blocks to be copied */
do_signalrm, /* 15: schedule an alarm that causes an alarm signal */
do_syncalrm, /* 16: schedule an alarm that sends a notification message */
do_flagalrm, /* 17: schedule an alarm that sets a timeout flag to 1 */
do_unused, /* 18: unused */
do_svrctl, /* 19: handles miscelleneous kernel control functions */
do_sdevio, /* 20: device I/O: phys_insb, _insw, _outsb, _outsw */
do_unused, /* 21: unused */
do_getinfo, /* 22: request some kind of system information */
do_devio, /* 23: device I/O: inb, inw, inl, outb, outw, outl */
do_vdevio, /* 24: device I/O: vector with in[b|w|l], out[b|w|l] */
do_irqctl, /* 25: request an interrupt control operation */
do_kmalloc, /* 26: request allocation of (DMA) buffer in mem chunk */
do_iopenable, /* 27: allow a user process to use I/O instructions */
do_phys2seg, /* 28: do a phys addr to segment selector/ offset conversion */
do_exit, /* 29: an server or driver requests to be aborted */
do_vircopy, /* 30: copy from process to process (virtual addressing) */
do_physcopy, /* 31: copy from anywhere to anywhere (physical addressing) */
};
/* Check if system call table is correct. This should not fail. No space is
* allocated here, because the dummy is declared extern. If the call vector
* is unbalanced, the array size will be negative and this won't compile.
*/
extern int dummy[sizeof(call_vec)==NR_SYS_CALLS*sizeof(call_vec[0]) ? 1 : -1];
/* Some system task variables. */
PRIVATE message m; /* used to receive requests */
/*===========================================================================*
* sys_task *
@@ -100,7 +65,7 @@ PRIVATE message m; /* used to receive requests */
PUBLIC void sys_task()
{
/* Main entry point of sys_task. Get the message and dispatch on type. */
static message m;
register int result;
/* Initialize the system task. */
@@ -145,6 +110,59 @@ PRIVATE void initialize(void)
tmr_inittimer(&(rp->p_syncalrm));
tmr_inittimer(&(rp->p_flagalrm));
}
/* Initialize the call vector to a safe default handler. Some system calls
* may be disabled or nonexistant. Then explicitely map known calls to their
* handler functions. This is done with a macro that gives a compile error
* if an illegal call number is used. The ordering is not important here.
*/
for (i=0; i<NR_SYS_CALLS; i++) {
call_vec[i] = do_unused;
}
/* Process management. */
map(SYS_FORK, do_fork); /* informs kernel that a process has forked */
map(SYS_XIT, do_xit); /* informs kernel that a process has exited */
map(SYS_NEWMAP, do_newmap); /* allows PM to set up a process memory map */
map(SYS_EXEC, do_exec); /* sets program counter and stack pointer after EXEC */
map(SYS_TRACE, do_trace); /* request a trace operation */
/* Signal handling. */
map(SYS_KILL, do_kill); /* cause a process to be signaled */
map(SYS_GETSIG, do_getsig); /* PM checks for pending signals */
map(SYS_ENDSIG, do_endsig); /* PM finished processing signal */
map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */
map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */
/* Clock functionality. */
map(SYS_TIMES, do_times); /* get uptime and process times */
map(SYS_SIGNALRM, do_signalrm); /* causes an alarm signal */
map(SYS_SYNCALRM, do_syncalrm); /* send a notification message */
map(SYS_FLAGALRM, do_flagalrm); /* set a timeout flag to 1 */
/* Device I/O. */
map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
map(SYS_DEVIO, do_devio); /* inb, inw, inl, outb, outw, outl */
map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
/* Server and driver control. */
map(SYS_KMALLOC, do_kmalloc); /* request chunk of free memory */
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
map(SYS_IOPENABLE, do_iopenable); /* enable CPU I/O protection bits */
map(SYS_SVRCTL, do_svrctl); /* kernel control functions */
map(SYS_EXIT, do_exit); /* exit a system process*/
/* Copying. */
map(SYS_UMAP, do_umap); /* map virtual to physical address */
map(SYS_VIRCOPY, do_vircopy); /* use virtual addressing */
map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */
map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
/* Miscellaneous. */
map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
map(SYS_RANDOM, do_random); /* request kernel random data */
}
/*===========================================================================*
@@ -216,6 +234,14 @@ int proc_nr; /* slot of process to clean up */
PUBLIC int generic_handler(hook)
irq_hook_t *hook;
{
/* This function handles hardware interrupt in a simpel and generic way. All
* interrupts are transformed into messages to a driver. The IRQ line will be
* reenabled if the policy says so.
*/
irq_policy_t policy = irqtab[hook->irq].policy;
int proc_nr = irqtab[hook->irq].proc_nr;
#if DEAD_CODE
/* This function handles hardware interrupt in a generic way, according to
* the policy set with SYS_IRQCTL. This is rather complicated since different
* devices require different actions. Options are (1) do nothing, (2a) read a
@@ -223,8 +249,6 @@ irq_hook_t *hook;
* read, or (3) write a value to a port. Finally, the policy may or may not
* reenable IRQs. A notification is sent in all cases.
*/
irq_policy_t policy = irqtab[hook->irq].policy;
int proc_nr = irqtab[hook->irq].proc_nr;
long port = irqtab[hook->irq].port;
phys_bytes addr = irqtab[hook->irq].addr;
long mask_val = irqtab[hook->irq].mask_val;
@@ -270,6 +294,7 @@ irq_hook_t *hook;
default: /* do nothing */ ; /* wrong type flags */
}
}
#endif /* DEAD_CODE */
/* Almost done, send a HARD_INT notification to allow further processing
* and possibly reenable interrupts - this depends on the policy given.
@@ -290,12 +315,12 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
* TTY wanting to cause SIGINT upon getting a DEL
* CLOCK wanting to cause SIGALRM when timer expires
* FS also uses this to send a signal, via the SYS_KILL message. Signals are
* handled by sending a message to MM. This central function handles the
* signals and makes sure the MM gets them by sending a notification. The
* process being signaled is blocked while MM has not finished all signals
* handled by sending a message to PM. This central function handles the
* signals and makes sure the PM gets them by sending a notification. The
* process being signaled is blocked while PM has not finished all signals
* for it. These signals are counted in p_pendcount, and the SIG_PENDING
* flag is kept nonzero while there are some. It is not sufficient to ready
* the process when MM is informed, because MM can block waiting for FS to
* the process when PM is informed, because PM can block waiting for FS to
* do a core dump.
*/
register struct proc *rp, *mmp;
@@ -309,7 +334,7 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
return; /* another signal already pending */
if (rp->p_flags == 0) lock_unready(rp);
rp->p_flags |= PENDING | SIG_PENDING;
notify(MM_PROC_NR, KSIG_PENDING);
notify(PM_PROC_NR, KSIG_PENDING);
}
@@ -321,12 +346,22 @@ register struct proc *rp; /* pointer to proc table entry for process */
vir_bytes vir_addr; /* virtual address in BIOS segment */
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address at the BIOS. */
/* Calculate the physical memory address at the BIOS. Note: currently, BIOS
* address zero (the first BIOS interrupt vector) is not considered, as an
* error here, but since the physical address will be zero as well, the
* calling function will think an error occurred. This is not a problem,
* since no one uses the first BIOS interrupt vector.
*/
phys_bytes phys_addr;
phys_addr = (phys_bytes) vir_addr; /* no check currently! */
/* Check all acceptable ranges. */
if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END)
return (phys_bytes) vir_addr;
else if (vir_addr >= UPPER_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
return (phys_bytes) vir_addr;
return phys_addr;
kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr);
return 0;
}
/*===========================================================================*
@@ -438,11 +473,16 @@ vir_bytes vir_addr; /* virtual address in bytes within the seg */
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address for a given virtual address. */
phys_bytes phys_addr;
struct far_mem *fm;
phys_addr = (phys_bytes) 0; /* no yet supported currently! */
if (bytes <= 0) return( (phys_bytes) 0);
if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
return phys_addr;
fm = &rp->p_farmem[seg];
if (! fm->in_use) return( (phys_bytes) 0);
if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
return(fm->mem_phys + (phys_bytes) vir_addr);
}
/*==========================================================================*
@@ -454,7 +494,7 @@ struct vir_addr *dst_addr; /* destination virtual address */
vir_bytes bytes; /* # of bytes to copy */
{
/* Copy bytes from virtual address src_addr to virtual address dst_addr.
* Virtual addresses can be in LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
* Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
*/
struct vir_addr *vir_addr[2]; /* virtual source and destination address */
phys_bytes phys_addr[2]; /* absolute source and destination */
@@ -488,6 +528,9 @@ vir_bytes bytes; /* # of bytes to copy */
phys_addr[i] = umap_bios( proc_addr(vir_addr[i]->proc_nr),
vir_addr[i]->offset, bytes );
break;
case PHYS_SEG:
phys_addr[i] = vir_addr[i]->offset;
break;
default:
kprintf("v_cp: Unknown segment type: %d\n",
vir_addr[i]->segment & SEGMENT_TYPE);
@@ -495,7 +538,7 @@ vir_bytes bytes; /* # of bytes to copy */
}
/* Check if mapping succeeded. */
if (phys_addr[i] <= 0) {
if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) {
kprintf("v_cp: Mapping failed ... phys <= 0\n", NO_ARG);
return(EFAULT);
}

View File

@@ -19,22 +19,23 @@ _PROTOTYPE( int do_fork, (message *m_ptr) );
_PROTOTYPE( int do_newmap, (message *m_ptr) );
_PROTOTYPE( int do_xit, (message *m_ptr) );
_PROTOTYPE( int do_vircopy, (message *m_ptr) ); /* copying */
_PROTOTYPE( int do_physcopy, (message *m_ptr) );
_PROTOTYPE( int do_copy, (message *m_ptr) ); /* copying */
#define do_vircopy do_copy
#define do_physcopy do_copy
_PROTOTYPE( int do_vcopy, (message *m_ptr) );
#define do_virvcopy do_vcopy
_PROTOTYPE( int do_umap, (message *m_ptr) );
_PROTOTYPE( int do_vcopy, (message *m_ptr) );
_PROTOTYPE( int do_copy, (message *m_ptr) );
_PROTOTYPE( int do_unused, (message *m_ptr) ); /* miscellaneous */
_PROTOTYPE( int do_abort, (message *m_ptr) );
_PROTOTYPE( int do_times, (message *m_ptr) );
_PROTOTYPE( int do_getinfo, (message *m_ptr) );
_PROTOTYPE( int do_random, (message *m_ptr) );
_PROTOTYPE( int do_exit, (message *m_ptr) ); /* server control */
_PROTOTYPE( int do_svrctl, (message *m_ptr) );
_PROTOTYPE( int do_kmalloc, (message *m_ptr) );
_PROTOTYPE( int do_iopenable, (message *m_ptr) );
_PROTOTYPE( int do_phys2seg, (message *m_ptr) );
_PROTOTYPE( int do_segctl, (message *m_ptr) );
_PROTOTYPE( int do_devio, (message *m_ptr) ); /* device I/O */
_PROTOTYPE( int do_vdevio, (message *m_ptr) );
@@ -43,9 +44,13 @@ _PROTOTYPE( int do_sdevio, (message *m_ptr) );
_PROTOTYPE( int do_irqctl, (message *m_ptr) ); /* interrupt control */
_PROTOTYPE( int do_kill, (message *m_ptr) ); /* signal handling */
_PROTOTYPE( int do_sigctl, (message *m_ptr) );
_PROTOTYPE( int do_getsig, (message *m_ptr) );
_PROTOTYPE( int do_endsig, (message *m_ptr) );
_PROTOTYPE( int do_sigsend, (message *m_ptr) );
_PROTOTYPE( int do_sigreturn, (message *m_ptr) );
_PROTOTYPE( int do_setalarm, (message *m_ptr) ); /* alarm functions */
_PROTOTYPE( int do_times, (message *m_ptr) ); /* clock functions */
_PROTOTYPE( int do_setalarm, (message *m_ptr) );
#define do_flagalrm do_setalarm
#define do_signalrm do_setalarm
#define do_syncalrm do_setalarm
@@ -57,6 +62,7 @@ _PROTOTYPE( int do_trace, (message *m_ptr) ); /* process tracing */
#endif
#if ENABLE_K_DEBUGGING /* debugging */
#error Kernel debugging routines are not implemented.
#else
#endif

View File

@@ -20,8 +20,7 @@ CFLAGS = -I$i
LDFLAGS = -i
SYS = alarms.o copying.o debugging.o devio.o irqctl.o proctl.o \
srvrctl.o misc.o sigctl.o tracing.o \
do_copy.o do_vcopy.o
sysctl.o misc.o sigctl.o tracing.o \
# What to make.
all build: $(SYS)
@@ -48,11 +47,8 @@ irqctl.o: $a $b
misc.o: $a $b $i/unistd.h
proctl.o: $a $b $k/sendmask.h $k/protect.h $i/signal.h
sigctl.o: $a $b $i/signal.h $s/sigcontext.h
srvrctl.o: $a $b $s/svrctl.h $k/sendmask.h
sysctl.o: $a $b $s/svrctl.h $k/sendmask.h
tracing.o: $a $b $s/ptrace.h
do_copy.o: $a $b
do_vcopy.o: $a $b

View File

@@ -1,5 +1,5 @@
/* The system call implemented in this file:
* m_type: SYS_VIRCOPY
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY
*
* The parameters for this system call are:
* m5_c1: CP_SRC_SPACE
@@ -13,14 +13,17 @@
#include "../kernel.h"
#include "../system.h"
#include <minix/type.h>
/*===========================================================================*
* do_vircopy *
* do_copy *
*===========================================================================*/
PUBLIC int do_vircopy(m_ptr)
PUBLIC int do_copy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_vircopy(). Copy data by using virtual addressing. */
/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
* physical addressing.
*/
struct vir_addr vir_addr[2]; /* virtual source and destination address */
vir_bytes bytes; /* number of bytes to copy */
int i;
@@ -41,21 +44,18 @@ register message *m_ptr; /* pointer to request message */
/* Check if process number was given implictly with SELF and is valid. */
if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source;
if (! isokprocn(vir_addr[i].proc_nr)) {
kprintf("do_vircopy: illegal proc nr\n",NO_ARG);
if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) {
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_ARG);
return(EINVAL);
}
/* Copying from or to special segments can only done by the owner. */
if ((vir_addr[i].segment & SEGMENT_TYPE) != LOCAL_SEG &&
vir_addr[i].proc_nr != m_ptr->m_source) {
kprintf("do_vircopy: special seg permission denied\n", NO_ARG);
return(EPERM);
}
/* Check if physical addressing is used without SYS_PHYSCOPY. */
if ((vir_addr[i].segment & SEGMENT_TYPE) == PHYS_SEG &&
m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
}
/* Check for overflow. This would happen for 64K segments and 16-bit
* vir_bytes. Especially copying by the MM on do_fork() is affected.
* vir_bytes. Especially copying by the PM on do_fork() is affected.
*/
if (bytes != (vir_bytes) bytes) {
kprintf("do_vircopy: overflow\n", NO_ARG);
@@ -67,37 +67,44 @@ register message *m_ptr; /* pointer to request message */
}
/* The system call implemented in this file:
* m_type: SYS_PHYSCOPY
*
* The parameters for this system call are:
* m5_l1: CP_SRC_ADDR (physical source address)
* m5_l2: CP_DST_ADDR (physical destination address)
* m5_l3: CP_NR_BYTES (number of bytes to copy)
*
* Author:
* Jorrit N. Herder <jnherder@cs.vu.nl>
*/
/* Buffer to hold copy request vector from user. */
PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
/*===========================================================================*
* do_physcopy *
* do_vcopy *
*===========================================================================*/
PUBLIC int do_physcopy(m_ptr)
PUBLIC int do_vcopy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_physcopy(). Copy data by using physical addressing. */
/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
int nr_req;
int caller_pid;
vir_bytes caller_vir;
phys_bytes caller_phys;
phys_bytes kernel_phys;
phys_bytes bytes;
int i,s;
phys_bytes src_phys, dst_phys, bytes;
/* Check if request vector size is ok. */
nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
bytes = nr_req * sizeof(struct vir_cp_req);
/* Dismember the command message. */
src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
/* Calculate physical addresses and copy (port,value)-pairs from user. */
caller_pid = (int) m_ptr->m_source;
caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR;
caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
if (0 == caller_phys) return(EFAULT);
kernel_phys = vir2phys(vir_cp_req);
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
/* Do some checks and copy the data. */
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
phys_copy(src_phys, dst_phys, bytes);
return(OK);
/* Assume vector with requests is correct. Try to copy everything. */
for (i=0; i<nr_req; i++) {
s = virtual_copy(&vir_cp_req[i].src, &vir_cp_req[i].dst,
vir_cp_req[i].count);
if (s != OK) break;
}
return(s);
}

View File

@@ -1,69 +0,0 @@
/* The system call implemented in this file:
* m_type: SYS_COPY
*
* The parameters for this system call are:
* m5_c1: CP_SRC_SPACE
* m5_i1: CP_SRC_PROC_NR
* m5_l1: CP_SRC_ADDR
* m5_c2: CP_DST_SPACE
* m5_i2: CP_DST_PROC_NR
* m5_l2: CP_DST_ADDR
* m5_l3: CP_NR_BYTES
*/
#include "../kernel.h"
#include "../system.h"
/*===========================================================================*
* do_copy *
*===========================================================================*/
PUBLIC int do_copy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_copy(). Copy data by using virtual or physical addressing. */
int src_proc, dst_proc, src_space, dst_space;
vir_bytes src_vir, dst_vir;
phys_bytes src_phys, dst_phys, bytes;
/* Dismember the command message. */
src_proc = m_ptr->CP_SRC_PROC_NR;
dst_proc = m_ptr->CP_DST_PROC_NR;
src_space = m_ptr->CP_SRC_SPACE;
dst_space = m_ptr->CP_DST_SPACE;
src_vir = (vir_bytes) m_ptr->CP_SRC_ADDR;
dst_vir = (vir_bytes) m_ptr->CP_DST_ADDR;
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
/* Check if process number was given implicitly with SELF. */
if (src_proc == SELF) src_proc = m_ptr->m_source;
if (dst_proc == SELF) dst_proc = m_ptr->m_source;
/* Compute the source and destination addresses and do the copy. */
if (src_proc == ABS) {
src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
} else {
if (bytes != (vir_bytes) bytes) {
/* This would happen for 64K segments and 16-bit vir_bytes.
* It would happen a lot for do_fork except MM uses ABS
* copies for that case.
*/
panic("overflow in count in do_copy", NO_NUM);
}
src_phys = umap_local(proc_addr(src_proc), src_space, src_vir,
(vir_bytes) bytes);
}
if (dst_proc == ABS) {
dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
} else {
dst_phys = umap_local(proc_addr(dst_proc), dst_space, dst_vir,
(vir_bytes) bytes);
}
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
phys_copy(src_phys, dst_phys, bytes);
return(OK);
}

View File

@@ -1,55 +0,0 @@
/* The system call implemented in this file:
* m_type: SYS_VCOPY
*
* The parameters for this system call are:
* m1_i1: VCP_SRC_PROC (source process number)
* m1_i2: VCP_DST_PROC (destination process number)
* m1_i3: VCP_VEC_SIZE (vector size)
* m1_p1: VCP_VEC_ADDR (pointer to vector)
*
* Author:
* Jorrit N. Herder <jnherder@cs.vu.nl>
*/
#include "../kernel.h"
#include "../system.h"
/*===========================================================================*
* do_vcopy *
*===========================================================================*/
PUBLIC int do_vcopy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_vcopy(). Copy multiple blocks of memory */
int src_proc, dst_proc, vect_s, i;
vir_bytes src_vir, dst_vir, vect_addr;
phys_bytes src_phys, dst_phys, bytes;
cpvec_t cpvec_table[CPVEC_NR];
/* Dismember the command message. */
src_proc = m_ptr->VCP_SRC_PROC;
dst_proc = m_ptr->VCP_DST_PROC;
vect_s = m_ptr->VCP_VEC_SIZE;
vect_addr = (vir_bytes)m_ptr->VCP_VEC_ADDR;
if (vect_s > CPVEC_NR) return EDOM;
src_phys= numap_local(m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
if (!src_phys) return EFAULT;
phys_copy(src_phys, vir2phys(cpvec_table),
(phys_bytes) (vect_s * sizeof(cpvec_t)));
for (i = 0; i < vect_s; i++) {
src_vir= cpvec_table[i].cpv_src;
dst_vir= cpvec_table[i].cpv_dst;
bytes= cpvec_table[i].cpv_size;
src_phys = numap_local(src_proc,src_vir,(vir_bytes)bytes);
dst_phys = numap_local(dst_proc,dst_vir,(vir_bytes)bytes);
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
phys_copy(src_phys, dst_phys, bytes);
}
return(OK);
}

View File

@@ -27,11 +27,13 @@ register message *m_ptr; /* pointer to request message */
/* Dismember the request message. */
int irq = m_ptr->IRQ_VECTOR; /* which IRQ vector */
int policy = m_ptr->IRQ_POLICY; /* policy field with flags */
int proc_nr = m_ptr->IRQ_PROC_NR; /* process number to forward to */
#if DEAD_CODE
long port = m_ptr->IRQ_PORT; /* port to read or write */
vir_bytes vir_addr = m_ptr->IRQ_VIR_ADDR; /* address at caller */
phys_bytes phys_addr = 0; /* calculate physical address */
long mask_val = m_ptr->IRQ_MASK_VAL; /* mask or value to be written */
int proc_nr = m_ptr->IRQ_PROC_NR; /* process number to forward to */
#endif
/* Check if IRQ line is acceptable. */
if ((unsigned) irq >= NR_IRQ_VECTORS) {
@@ -76,6 +78,7 @@ register message *m_ptr; /* pointer to request message */
kprintf("ST: notify: invalid proc_nr: %d\n", proc_nr);
return(EINVAL);
}
#if DEAD_CODE
if (policy & IRQ_READ_PORT) { /* get phys_addr at caller */
switch(policy & (IRQ_BYTE|IRQ_WORD|IRQ_LONG)) {
case IRQ_BYTE: phys_addr=numap_local(proc_nr,vir_addr,sizeof( u8_t));
@@ -88,12 +91,15 @@ register message *m_ptr; /* pointer to request message */
}
if (phys_addr==0) return(EFAULT); /* invalid address */
}
#endif
/* Arguments seem to be OK, register them in the IRQ table. */
irqtab[irq].policy = policy; /* policy for interrupts */
irqtab[irq].proc_nr = proc_nr; /* process number to notify */
#if DEAD_CODE
irqtab[irq].port = port; /* port to read or write */
irqtab[irq].addr = phys_addr; /* address to store status */
irqtab[irq].mask_val = mask_val; /* strobe mask or value */
#endif
put_irq_handler(&irqtab[irq].hook, irq, generic_handler);
}
break;

View File

@@ -54,6 +54,16 @@ message *m; /* pointer to request message */
}
/*===========================================================================*
* do_random *
*===========================================================================*/
PUBLIC int do_random(m)
message *m; /* pointer to request message */
{
return(ENOSYS); /* no yet implemented */
}
/* The system call implemented in this file:
* m_type: SYS_ABORT
*
@@ -71,7 +81,7 @@ PUBLIC int do_abort(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
* MM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
* PM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
* after debugging dumps).
*/
register struct proc *rp;
@@ -84,11 +94,11 @@ message *m_ptr; /* pointer to request message */
if (how == RBT_MONITOR) {
/* The monitor is to run user specified instructions. */
len = m_ptr->ABRT_MON_LEN + 1;
assert(len <= mon_parmsize);
assert(len <= kinfo.params_size);
src_phys = numap_local(m_ptr->ABRT_MON_PROC,
(vir_bytes) m_ptr->ABRT_MON_ADDR, len);
assert(src_phys != 0);
phys_copy(src_phys, mon_params, (phys_bytes) len);
phys_copy(src_phys, kinfo.params_base, (phys_bytes) len);
}
prepare_shutdown(how);
return(OK); /* pro-forma (really EDISASTER) */
@@ -125,23 +135,14 @@ register message *m_ptr; /* pointer to request message */
/* Set source address and length based on request type. */
switch (m_ptr->I_REQUEST) {
case GET_KENVIRON: {
struct kenviron kenv;
extern int end;
kenv.pc_at = pc_at; kenv.ps_mca = ps_mca;
kenv.processor = processor; kenv.protected = protected_mode;
kenv.ega = ega; kenv.vga = vga;
kenv.proc_addr = (vir_bytes) proc;
kenv.params_base = mon_params;
kenv.params_size = mon_parmsize;
kenv.kmem_base = vir2phys(0);
kenv.kmem_size = vir2phys(&end) - vir2phys(0) + 1;
kenv.bootfs_base = proc_addr(MEMORY)->p_farmem[0].mem_phys;
kenv.bootfs_size = proc_addr(MEMORY)->p_farmem[0].mem_len;
length = sizeof(struct kenviron);
src_phys = vir2phys(&kenv);
case GET_MACHINE: {
length = sizeof(struct machine);
src_phys = vir2phys(&machine);
break;
}
case GET_KINFO: {
length = sizeof(struct kinfo);
src_phys = vir2phys(&kinfo);
break;
}
case GET_IMAGE: {
@@ -184,20 +185,26 @@ register message *m_ptr; /* pointer to request message */
break;
}
case GET_MONPARAMS: {
src_phys = mon_params; /* already is a physical address! */
length = mon_parmsize;
src_phys = kinfo.params_base; /* already is a physical address! */
length = kinfo.params_size;
break;
}
case GET_PROCNR: {
length = sizeof(int);
if (m_ptr->I_KEY_LEN == 0) { /* get own process nr */
#if DEAD_CODE
/* GET_PROCNR functionality will be moved to the Process Manager! */
kprintf("GET_PROCNR (own) from %d\n", m_ptr->m_source);
#endif
src_phys = vir2phys(&proc_nr);
length = sizeof(int);
} else { /* lookup nr by name */
int proc_found = FALSE;
struct proc *pp;
char key[8]; /* storage for process name to lookup */
kprintf("GET_PROCNR (others) from %d\n", m_ptr->m_source);
#if DEAD_CODE
/* GET_PROCNR functionality will be moved to the Process Manager! */
kprintf("GET_PROCNR (by name) from %d\n", m_ptr->m_source);
#endif
proc_nr = m_ptr->m_source; /* only caller can request copy */
if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR, SYSTASK,
@@ -205,6 +212,7 @@ register message *m_ptr; /* pointer to request message */
for (pp=BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
if (kstrncmp(pp->p_name, key, m_ptr->I_KEY_LEN) == 0) {
src_phys = vir2phys(&(pp->p_nr));
length = sizeof(int);
proc_found = TRUE;
break;
}

View File

@@ -4,7 +4,7 @@
* The parameters for this system call are:
* m1_i1: PR_PROC_NR (child's process table slot)
* m1_i2: PR_PPROC_NR (parent, process that forked)
* m1_i3: PR_PID (child pid received from MM)
* m1_i3: PR_PID (child pid received from PM)
*/
#include "../kernel.h"
@@ -81,23 +81,23 @@ register message *m_ptr; /* pointer to request message */
PUBLIC int do_newmap(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_newmap(). Fetch the memory map from MM. */
/* Handle sys_newmap(). Fetch the memory map from PM. */
register struct proc *rp;
phys_bytes src_phys;
int caller; /* whose space has the new map (usually MM) */
int caller; /* whose space has the new map (usually PM) */
int k; /* process whose map is to be loaded */
int old_flags; /* value of flags before modification */
struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
/* Extract message parameters and copy new memory map from MM. */
/* Extract message parameters and copy new memory map from PM. */
caller = m_ptr->m_source;
k = m_ptr->PR_PROC_NR;
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
if (!isokprocn(k)) return(EINVAL);
rp = proc_addr(k); /* ptr to entry of user getting new map */
/* Copy the map from MM. */
/* Copy the map from PM. */
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr,
sizeof(rp->p_memmap));
assert(src_phys != 0);
@@ -158,7 +158,7 @@ register message *m_ptr; /* pointer to request message */
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
#endif
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
rp->p_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
rp->p_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
if (rp->p_flags == 0) lock_ready(rp);
/* Save command name for debugging, ps(1) output, etc. */
@@ -189,7 +189,7 @@ register message *m_ptr; /* pointer to request message */
PUBLIC int do_xit(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_exit. A user process has exited (the MM sent the request).
/* Handle sys_exit. A user process has exited (the PM sent the request).
*/
register struct proc *rp, *rc;
struct proc *np, *xp;
@@ -201,7 +201,7 @@ message *m_ptr; /* pointer to request message */
if (! isokprocn(exit_proc_nr)) return(EINVAL);
rc = proc_addr(exit_proc_nr);
/* If this is a user process and the MM passed in a valid parent process,
/* If this is a user process and the PM passed in a valid parent process,
* accumulate the child times at the parent.
*/
if (isuserp(rc) && isokprocn(m_ptr->PR_PPROC_NR)) {
@@ -217,7 +217,7 @@ message *m_ptr; /* pointer to request message */
* and resets important process table fields.
*/
clear_proc(exit_proc_nr);
return(OK); /* tell MM that cleanup succeeded */
return(OK); /* tell PM that cleanup succeeded */
}

View File

@@ -23,67 +23,54 @@
#include <sys/sigcontext.h>
INIT_ASSERT
/*===========================================================================*
* do_sigctl *
*===========================================================================*/
PUBLIC int do_sigctl(m_ptr)
/* PM is ready to accept signals and repeatedly does a system call to get
* one. Find a process with pending signals. If no signals are available,
* return NONE in the process number field.
*/
PUBLIC int do_getsig(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Only the MM and FS are allowed to use signal control operations. */
if (m_ptr->m_source != MM_PROC_NR && m_ptr->m_source != FS_PROC_NR)
return(EPERM);
register struct proc *rp;
/* Now see what request we got. The supported requests are S_GETSIG,
* S_ENDSIG, S_SENDSIG, S_SIGRETURN, and S_KILL. Unsupported requests
* result in an EINVAL error.
*/
switch(m_ptr->SIG_REQUEST) {
/* MM is ready to accept signals and repeatedly does a system call to get
* one. Find a process with pending signals. If no signals are available,
* return NONE in the process number field.
*/
case S_GETSIG: {
register struct proc *rp;
/* Find the next process with pending signals. */
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
if (rp->p_flags & PENDING) {
m_ptr->SIG_PROC = proc_number(rp);
m_ptr->SIG_MAP = rp->p_pending;
sigemptyset(&rp->p_pending); /* ball is in MM's court */
rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */
return(OK);
}
}
/* No process with pending signals was found. */
m_ptr->SIG_PROC = NONE;
return(OK);
/* Find the next process with pending signals. */
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
if (rp->p_flags & PENDING) {
m_ptr->SIG_PROC = proc_number(rp);
m_ptr->SIG_MAP = rp->p_pending;
sigemptyset(&rp->p_pending); /* ball is in PM's court */
rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */
return(OK);
}
}
/* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a
* call to cause_sig by a task
*/
case S_ENDSIG: {
/* No process with pending signals was found. */
m_ptr->SIG_PROC = NONE;
return(OK);
}
register struct proc *rp;
PUBLIC int do_endsig(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Finish up after a kernel type signal, caused by a SYS_KILL message or a
* call to cause_sig by a task. This is called by the PM after processing a
* signal it got with SYS_GETSIG.
*/
register struct proc *rp;
rp = proc_addr(m_ptr->SIG_PROC);
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
assert(isuserp(rp));
rp = proc_addr(m_ptr->SIG_PROC);
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
/* MM has finished one KSIG. Perhaps process is ready now? */
if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
&& (rp->p_flags &= ~SIG_PENDING) == 0)
lock_ready(rp);
return(OK);
}
/* PM has finished one kernel signal. Perhaps process is ready now? */
if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
&& (rp->p_flags &= ~SIG_PENDING) == 0)
lock_ready(rp);
return(OK);
}
/* Handle sys_sendsig, POSIX-style signal handling.
*/
case S_SENDSIG: {
PUBLIC int do_sigsend(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_sigsend, POSIX-style signal handling. */
struct sigmsg smsg;
register struct proc *rp;
@@ -95,7 +82,7 @@ message *m_ptr; /* pointer to request message */
assert(isuserp(rp));
/* Get the sigmsg structure into our address space. */
src_phys = umap_local(proc_addr(MM_PROC_NR), D, (vir_bytes)
src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes)
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
assert(src_phys != 0);
phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
@@ -140,13 +127,14 @@ message *m_ptr; /* pointer to request message */
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
return(OK);
}
/* POSIX style signals require sys_sigreturn to put things in order before
* the signalled process can resume execution
*/
case S_SIGRETURN: {
}
PUBLIC int do_sigreturn(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* POSIX style signals require sys_sigreturn to put things in order before
* the signalled process can resume execution
*/
struct sigcontext sc;
register struct proc *rp;
phys_bytes src_phys;
@@ -193,30 +181,18 @@ message *m_ptr; /* pointer to request message */
/* Restore the registers. */
kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
return(OK);
}
/* Handle sys_kill(). Cause a signal to be sent to a process via MM.
* Note that this has nothing to do with the kill(2) system call, this
* is how the FS (and possibly other servers) get access to cause_sig.
*/
case S_KILL: {
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
return(OK);
}
default:
return(EINVAL);
}
}
/*===========================================================================*
* do_sigctl *
*===========================================================================*/
PUBLIC int do_kill(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_kill(). Cause a signal to be sent to a process via MM.
/* Handle sys_kill(). Cause a signal to be sent to a process via PM.
* Note that this has nothing to do with the kill (2) system call, this
* is how the FS (and possibly other servers) get access to cause_sig.
*/

View File

@@ -82,7 +82,7 @@ message *m_ptr; /* pointer to request message */
argp = (vir_bytes) m_ptr->CTL_ARG_PTR;
rp = proc_addr(proc_nr);
/* Check if the MM privileges are super user. */
/* Check if the PM privileges are super user. */
if (!priv || !isuserp(rp))
return(EPERM);
@@ -99,7 +99,7 @@ message *m_ptr; /* pointer to request message */
rp->p_type = P_SERVER;
rp->p_sendmask = ALLOW_ALL_MASK;
send_mask_allow(proc_addr(RTL8139)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(MM_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(PM_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(FS_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(IS_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(CLOCK)->p_sendmask, proc_nr);
@@ -112,7 +112,7 @@ message *m_ptr; /* pointer to request message */
}
/* The system call implemented in this file:
* m_type: SYS_MEMCTL
* m_type: SYS_SEGCTL
*
* The parameters for this system call are:
* m4_l3: SEG_PHYS (physical base address)
@@ -127,9 +127,9 @@ message *m_ptr; /* pointer to request message */
/*===========================================================================*
* do_phys2seg *
* do_segctl *
*===========================================================================*/
PUBLIC int do_phys2seg(m_ptr)
PUBLIC int do_segctl(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Return a segment selector and offset that can be used to reach a physical
@@ -137,14 +137,28 @@ register message *m_ptr; /* pointer to request message */
*/
u16_t selector;
vir_bytes offset;
int i, index;
register struct proc *rp;
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
int result;
kprintf("Using Experimental LDT selector for video memory\n", NO_ARG);
/* First check if there is a slot available for this segment. */
rp = proc_addr(m_ptr->m_source);
index = -1;
for (i=0; i < NR_REMOTE_SEGS; i++) {
if (! rp->p_farmem[i].in_use) {
index = i;
rp->p_farmem[i].in_use = TRUE;
rp->p_farmem[i].mem_phys = phys;
rp->p_farmem[i].mem_len = size;
break;
}
}
if (index < 0) return(ENOSPC);
if (!protected_mode) {
if (! machine.protected) {
selector = phys / HCLICK_SIZE;
offset = phys % HCLICK_SIZE;
result = OK;
@@ -155,26 +169,22 @@ register message *m_ptr; /* pointer to request message */
* instead of bytes are used.
*/
if (size < BYTE_GRAN_MAX) {
rp = proc_addr(m_ptr->m_source);
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys, size,
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
USER_PRIVILEGE);
selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
offset = 0;
result = OK;
} else {
#if ENABLE_USERPRIV && ENABLE_LOOSELDT
rp = proc_addr(m_ptr->m_source);
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys & ~0xFFFF, 0,
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
USER_PRIVILEGE);
selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
offset = phys & 0xFFFF;
result = OK;
#else
result = E2BIG; /* allow settings only */
#endif
}
}
/* Request successfully done. Now return the result. */
m_ptr->SEG_INDEX = index | REMOTE_SEG;
m_ptr->SEG_SELECT = selector;
m_ptr->SEG_OFFSET = offset;
return(result);

View File

@@ -36,7 +36,7 @@ register message *m_ptr;
* T_EXIT exit
* T_STEP set trace bit
*
* The T_OK and T_EXIT commands are handled completely by the memory manager,
* The T_OK and T_EXIT commands are handled completely by the process manager,
* all others come here.
*/

View File

@@ -70,7 +70,7 @@ PUBLIC struct system_image image[] = {
{ CLOCK, clock_task, P_TASK, PPRI_TASK, CLOCK_STACK, CLOCK_SENDMASK, "CLOCK" },
{ SYSTASK, sys_task, P_TASK, PPRI_TASK, SYS_STACK, SYSTEM_SENDMASK, "SYS" },
{ HARDWARE, 0, P_TASK, PPRI_TASK, HARDWARE_STACK,HARDWARE_SENDMASK,"HARDWAR" },
{ MM_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, MM_SENDMASK, "MM" },
{ PM_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, PM_SENDMASK, "PM" },
{ FS_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, FS_SENDMASK, "FS" },
{ IS_PROC_NR, 0, P_SYSTEM, PPRI_HIGHER, 0, IS_SENDMASK, "IS" },
{ TTY, 0, P_SYSTEM, PPRI_HIGHER, 0, TTY_SENDMASK, "TTY" },

View File

@@ -5,13 +5,6 @@ typedef _PROTOTYPE( void task_t, (void) );
typedef _PROTOTYPE( int (*rdwt_t), (message *m_ptr) );
typedef _PROTOTYPE( void (*watchdog_t), (void) );
/* This is used within the kernel to handle virtual copying. */
struct vir_addr {
int proc_nr;
int segment;
vir_bytes offset;
};
/* Type accepted by kprintf(). This is a hack to accept both integers and
* char pointers in the same argument.
*/