BOOK.T
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:987k
- 04202 */
- 04203 #define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */
- 04204 #define _MINIX 1 /* tell headers to include MINIX stuff */
- 04205 #define _SYSTEM 1 /* tell headers that this is the kernel */
- 04206
- 04207 /* The following are so basic, all the *.c files get them automatically. */
- 04208 #include <minix/config.h> /* MUST be first */
- 04209 #include <ansi.h> /* MUST be second */
- 04210 #include <sys/types.h>
- 04211 #include <minix/const.h>
- 04212 #include <minix/type.h>
- 04213 #include <minix/syslib.h>
- 04214
- 04215 #include <string.h>
- 04216 #include <limits.h>
- 04217 #include <errno.h>
- 04218
- 04219 #include "const.h"
- 04220 #include "type.h"
- 04221 #include "proto.h"
- 04222 #include "glo.h"
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/const.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 04300 /* General constants used by the kernel. */
- 04301
- 04302 #if (CHIP == INTEL)
- 04303
- 04304 #define K_STACK_BYTES 1024 /* how many bytes for the kernel stack */
- 04305
- 04306 #define INIT_PSW 0x0200 /* initial psw */
- 04307 #define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
- 04308 #define TRACEBIT 0x100 /* OR this with psw in proc[] for tracing */
- 04309 #define SETPSW(rp, new) /* permits only certain bits to be set */
- 04310 ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
- 04311
- 04312 /* Initial sp for mm, fs and init.
- 04313 * 2 bytes for short jump
- 04314 * 2 bytes unused
- .Op 49 src/kernel/const.h
- 04315 * 3 words for init_org[] used by fs only
- 04316 * 3 words for real mode debugger trap (actually needs 1 more)
- 04317 * 3 words for save and restart temporaries
- 04318 * 3 words for interrupt
- 04319 * Leave no margin, to flush bugs early.
- 04320 */
- 04321 #define INIT_SP (2 + 2 + 3 * 2 + 3 * 2 + 3 * 2 + 3 * 2)
- 04322
- 04323 #define HCLICK_SHIFT 4 /* log2 of HCLICK_SIZE */
- 04324 #define HCLICK_SIZE 16 /* hardware segment conversion magic */
- 04325 #if CLICK_SIZE >= HCLICK_SIZE
- 04326 #define click_to_hclick(n) ((n) << (CLICK_SHIFT - HCLICK_SHIFT))
- 04327 #else
- 04328 #define click_to_hclick(n) ((n) >> (HCLICK_SHIFT - CLICK_SHIFT))
- 04329 #endif
- 04330 #define hclick_to_physb(n) ((phys_bytes) (n) << HCLICK_SHIFT)
- 04331 #define physb_to_hclick(n) ((n) >> HCLICK_SHIFT)
- 04332
- 04333 /* Interrupt vectors defined/reserved by processor. */
- 04334 #define DIVIDE_VECTOR 0 /* divide error */
- 04335 #define DEBUG_VECTOR 1 /* single step (trace) */
- 04336 #define NMI_VECTOR 2 /* non-maskable interrupt */
- 04337 #define BREAKPOINT_VECTOR 3 /* software breakpoint */
- 04338 #define OVERFLOW_VECTOR 4 /* from INTO */
- 04339
- 04340 /* Fixed system call vector. */
- 04341 #define SYS_VECTOR 32 /* system calls are made with int SYSVEC */
- 04342 #define SYS386_VECTOR 33 /* except 386 system calls use this */
- 04343 #define LEVEL0_VECTOR 34 /* for execution of a function at level 0 */
- 04344
- 04345 /* Suitable irq bases for hardware interrupts. Reprogram the 8259(s) from
- 04346 * the PC BIOS defaults since the BIOS doesn't respect all the processor's
- 04347 * reserved vectors (0 to 31).
- 04348 */
- 04349 #define BIOS_IRQ0_VEC 0x08 /* base of IRQ0-7 vectors used by BIOS */
- 04350 #define BIOS_IRQ8_VEC 0x70 /* base of IRQ8-15 vectors used by BIOS */
- 04351 #define IRQ0_VECTOR 0x28 /* more or less arbitrary, but > SYS_VECTOR */
- 04352 #define IRQ8_VECTOR 0x30 /* together for simplicity */
- 04353
- 04354 /* Hardware interrupt numbers. */
- 04355 #define NR_IRQ_VECTORS 16
- 04356 #define CLOCK_IRQ 0
- 04357 #define KEYBOARD_IRQ 1
- 04358 #define CASCADE_IRQ 2 /* cascade enable for 2nd AT controller */
- 04359 #define ETHER_IRQ 3 /* default ethernet interrupt vector */
- 04360 #define SECONDARY_IRQ 3 /* RS232 interrupt vector for port 2 */
- 04361 #define RS232_IRQ 4 /* RS232 interrupt vector for port 1 */
- 04362 #define XT_WINI_IRQ 5 /* xt winchester */
- 04363 #define FLOPPY_IRQ 6 /* floppy disk */
- 04364 #define PRINTER_IRQ 7
- 04365 #define AT_WINI_IRQ 14 /* at winchester */
- 04366
- 04367 /* Interrupt number to hardware vector. */
- 04368 #define BIOS_VECTOR(irq)
- 04369 (((irq) < 8 ? BIOS_IRQ0_VEC : BIOS_IRQ8_VEC) + ((irq) & 0x07))
- 04370 #define VECTOR(irq)
- 04371 (((irq) < 8 ? IRQ0_VECTOR : IRQ8_VECTOR) + ((irq) & 0x07))
- 04372
- 04373 /* BIOS hard disk parameter vectors. */
- 04374 #define WINI_0_PARM_VEC 0x41
- .Ep 50 src/kernel/const.h
- 04375 #define WINI_1_PARM_VEC 0x46
- 04376
- 04377 /* 8259A interrupt controller ports. */
- 04378 #define INT_CTL 0x20 /* I/O port for interrupt controller */
- 04379 #define INT_CTLMASK 0x21 /* setting bits in this port disables ints */
- 04380 #define INT2_CTL 0xA0 /* I/O port for second interrupt controller */
- 04381 #define INT2_CTLMASK 0xA1 /* setting bits in this port disables ints */
- 04382
- 04383 /* Magic numbers for interrupt controller. */
- 04384 #define ENABLE 0x20 /* code used to re-enable after an interrupt */
- 04385
- 04386 /* Sizes of memory tables. */
- 04387 #define NR_MEMS 3 /* number of chunks of memory */
- 04388
- 04389 /* Miscellaneous ports. */
- 04390 #define PCR 0x65 /* Planar Control Register */
- 04391 #define PORT_B 0x61 /* I/O port for 8255 port B (kbd, beeper...) */
- 04392 #define TIMER0 0x40 /* I/O port for timer channel 0 */
- 04393 #define TIMER2 0x42 /* I/O port for timer channel 2 */
- 04394 #define TIMER_MODE 0x43 /* I/O port for timer mode control */
- 04395
- 04396 #endif /* (CHIP == INTEL) */
- 04397
- 04398 #if (CHIP == M68000)
- 04399
- 04400 #define K_STACK_BYTES 1024 /* how many bytes for the kernel stack */
- 04401
- 04402 /* Sizes of memory tables. */
- 04403 #define NR_MEMS 2 /* number of chunks of memory */
- 04404
- 04405 /* p_reg contains: d0-d7, a0-a6, in that order. */
- 04406 #define NR_REGS 15 /* number of general regs in each proc slot */
- 04407
- 04408 #define TRACEBIT 0x8000 /* or this with psw in proc[] for tracing */
- 04409 #define SETPSW(rp, new) /* permits only certain bits to be set */
- 04410 ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xFF | (new) & 0xFF)
- 04411
- 04412 #define MEM_BYTES 0xffffffff /* memory size for /dev/mem */
- 04413
- 04414 #ifdef __ACK__
- 04415 #define FSTRUCOPY
- 04416 #endif
- 04417
- 04418 #endif /* (CHIP == M68000) */
- 04419
- 04420 /* The following items pertain to the scheduling queues. */
- 04421 #define TASK_Q 0 /* ready tasks are scheduled via queue 0 */
- 04422 #define SERVER_Q 1 /* ready servers are scheduled via queue 1 */
- 04423 #define USER_Q 2 /* ready users are scheduled via queue 2 */
- 04424
- 04425 #if (MACHINE == ATARI)
- 04426 #define SHADOW_Q 3 /* runnable, but shadowed processes */
- 04427 #define NQ 4 /* # of scheduling queues */
- 04428 #else
- 04429 #define NQ 3 /* # of scheduling queues */
- 04430 #endif
- 04431
- 04432 /* Env_parse() return values. */
- 04433 #define EP_UNSET 0 /* variable not set */
- 04434 #define EP_OFF 1 /* var = off */
- .Op 51 src/kernel/const.h
- 04435 #define EP_ON 2 /* var = on (or field left blank) */
- 04436 #define EP_SET 3 /* var = 1:2:3 (nonblank field) */
- 04437
- 04438 /* To translate an address in kernel space to a physical address. This is
- 04439 * the same as umap(proc_ptr, D, vir, sizeof(*vir)), but a lot less costly.
- 04440 */
- 04441 #define vir2phys(vir) (data_base + (vir_bytes) (vir))
- 04442
- 04443 #define printf printk /* the kernel really uses printk, not printf */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/type.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 04500 #ifndef TYPE_H
- 04501 #define TYPE_H
- 04502
- 04503 typedef _PROTOTYPE( void task_t, (void) );
- 04504 typedef _PROTOTYPE( int (*rdwt_t), (message *m_ptr) );
- 04505 typedef _PROTOTYPE( void (*watchdog_t), (void) );
- 04506
- 04507 struct tasktab {
- 04508 task_t *initial_pc;
- 04509 int stksize;
- 04510 char name[8];
- 04511 };
- 04512
- 04513 struct memory {
- 04514 phys_clicks base;
- 04515 phys_clicks size;
- 04516 };
- 04517
- 04518 /* Administration for clock polling. */
- 04519 struct milli_state {
- 04520 unsigned long accum_count; /* accumulated clock ticks */
- 04521 unsigned prev_count; /* previous clock value */
- 04522 };
- 04523
- 04524 #if (CHIP == INTEL)
- 04525 typedef unsigned port_t;
- 04526 typedef unsigned segm_t;
- 04527 typedef unsigned reg_t; /* machine register */
- 04528
- 04529 /* The stack frame layout is determined by the software, but for efficiency
- 04530 * it is laid out so the assembly code to use it is as simple as possible.
- 04531 * 80286 protected mode and all real modes use the same frame, built with
- 04532 * 16-bit registers. Real mode lacks an automatic stack switch, so little
- 04533 * is lost by using the 286 frame for it. The 386 frame differs only in
- 04534 * having 32-bit registers and more segment registers. The same names are
- 04535 * used for the larger registers to avoid differences in the code.
- 04536 */
- 04537 struct stackframe_s { /* proc_ptr points here */
- 04538 #if _WORD_SIZE == 4
- 04539 u16_t gs; /* last item pushed by save */
- 04540 u16_t fs; /* ^ */
- 04541 #endif
- 04542 u16_t es; /* | */
- 04543 u16_t ds; /* | */
- 04544 reg_t di; /* di through cx are not accessed in C */
- .Ep 52 src/kernel/type.h
- 04545 reg_t si; /* order is to match pusha/popa */
- 04546 reg_t fp; /* bp */
- 04547 reg_t st; /* hole for another copy of sp */
- 04548 reg_t bx; /* | */
- 04549 reg_t dx; /* | */
- 04550 reg_t cx; /* | */
- 04551 reg_t retreg; /* ax and above are all pushed by save */
- 04552 reg_t retadr; /* return address for assembly code save() */
- 04553 reg_t pc; /* ^ last item pushed by interrupt */
- 04554 reg_t cs; /* | */
- 04555 reg_t psw; /* | */
- 04556 reg_t sp; /* | */
- 04557 reg_t ss; /* these are pushed by CPU during interrupt */
- 04558 };
- 04559
- 04560 struct segdesc_s { /* segment descriptor for protected mode */
- 04561 u16_t limit_low;
- 04562 u16_t base_low;
- 04563 u8_t base_middle;
- 04564 u8_t access; /* |P|DL|1|X|E|R|A| */
- 04565 #if _WORD_SIZE == 4
- 04566 u8_t granularity; /* |G|X|0|A|LIMT| */
- 04567 u8_t base_high;
- 04568 #else
- 04569 u16_t reserved;
- 04570 #endif
- 04571 };
- 04572
- 04573 typedef _PROTOTYPE( int (*irq_handler_t), (int irq) );
- 04574
- 04575 #endif /* (CHIP == INTEL) */
- 04576
- 04577 #if (CHIP == M68000)
- 04578 typedef _PROTOTYPE( void (*dmaint_t), (void) );
- 04579
- 04580 typedef u32_t reg_t; /* machine register */
- 04581
- 04582 /* The name and fields of this struct were chosen for PC compatibility. */
- 04583 struct stackframe_s {
- 04584 reg_t retreg; /* d0 */
- 04585 reg_t d1;
- 04586 reg_t d2;
- 04587 reg_t d3;
- 04588 reg_t d4;
- 04589 reg_t d5;
- 04590 reg_t d6;
- 04591 reg_t d7;
- 04592 reg_t a0;
- 04593 reg_t a1;
- 04594 reg_t a2;
- 04595 reg_t a3;
- 04596 reg_t a4;
- 04597 reg_t a5;
- 04598 reg_t fp; /* also known as a6 */
- 04599 reg_t sp; /* also known as a7 */
- 04600 reg_t pc;
- 04601 u16_t psw;
- 04602 u16_t dummy; /* make size multiple of reg_t for system.c */
- 04603 };
- 04604
- .Op 53 src/kernel/type.h
- 04605 struct fsave {
- 04606 struct cpu_state {
- 04607 u16_t i_format;
- 04608 u32_t i_addr;
- 04609 u16_t i_state[4];
- 04610 } cpu_state;
- 04611 struct state_frame {
- 04612 u8_t frame_type;
- 04613 u8_t frame_size;
- 04614 u16_t reserved;
- 04615 u8_t frame[212];
- 04616 } state_frame;
- 04617 struct fpp_model {
- 04618 u32_t fpcr;
- 04619 u32_t fpsr;
- 04620 u32_t fpiar;
- 04621 struct fpN {
- 04622 u32_t high;
- 04623 u32_t low;
- 04624 u32_t mid;
- 04625 } fpN[8];
- 04626 } fpp_model;
- 04627 };
- 04628 #endif /* (CHIP == M68000) */
- 04629
- 04630 #endif /* TYPE_H */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/proto.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 04700 /* Function prototypes. */
- 04701
- 04702 #ifndef PROTO_H
- 04703 #define PROTO_H
- 04704
- 04705 /* Struct declarations. */
- 04706 struct proc;
- 04707 struct tty;
- 04708
- 04709 /* at_wini.c, wini.c */
- 04710 _PROTOTYPE( void winchester_task, (void) );
- 04711 _PROTOTYPE( void at_winchester_task, (void) );
- 04712
- 04713 /* clock.c */
- 04714 _PROTOTYPE( void clock_task, (void) );
- 04715 _PROTOTYPE( void clock_stop, (void) );
- 04716 _PROTOTYPE( clock_t get_uptime, (void) );
- 04717 _PROTOTYPE( void syn_alrm_task, (void) );
- 04718
- 04719 /* dmp.c */
- 04720 _PROTOTYPE( void map_dmp, (void) );
- 04721 _PROTOTYPE( void p_dmp, (void) );
- 04722 _PROTOTYPE( void reg_dmp, (struct proc *rp) );
- 04723
- 04724 /* dp8390.c */
- .Ep 54 src/kernel/proto.h
- 04725 _PROTOTYPE( void dp8390_task, (void) );
- 04726 _PROTOTYPE( void dp_dump, (void) );
- 04727 _PROTOTYPE( void dp8390_stop, (void) );
- 04728
- 04729 /* floppy.c, stfloppy.c */
- 04730 _PROTOTYPE( void floppy_task, (void) );
- 04731 _PROTOTYPE( void floppy_stop, (void) );
- 04732
- 04733 /* main.c, stmain.c */
- 04734 _PROTOTYPE( void main, (void) );
- 04735 _PROTOTYPE( void panic, (const char *s, int n) );
- 04736
- 04737 /* memory.c */
- 04738 _PROTOTYPE( void mem_task, (void) );
- 04739
- 04740 /* misc.c */
- 04741 _PROTOTYPE( int env_parse, (char *env, char *fmt, int field,
- 04742 long *param, long min, long max) );
- 04743
- 04744 /* printer.c, stprint.c */
- 04745 _PROTOTYPE( void printer_task, (void) );
- 04746
- 04747 /* proc.c */
- 04748 _PROTOTYPE( void interrupt, (int task) );
- 04749 _PROTOTYPE( int lock_mini_send, (struct proc *caller_ptr,
- 04750 int dest, message *m_ptr) );
- 04751 _PROTOTYPE( void lock_pick_proc, (void) );
- 04752 _PROTOTYPE( void lock_ready, (struct proc *rp) );
- 04753 _PROTOTYPE( void lock_sched, (void) );
- 04754 _PROTOTYPE( void lock_unready, (struct proc *rp) );
- 04755 _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
- 04756 _PROTOTYPE( void unhold, (void) );
- 04757
- 04758 /* rs232.c */
- 04759 _PROTOTYPE( void rs_init, (struct tty *tp) );
- 04760
- 04761 /* system.c */
- 04762 _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
- 04763 _PROTOTYPE( void inform, (void) );
- 04764 _PROTOTYPE( phys_bytes numap, (int proc_nr, vir_bytes vir_addr,
- 04765 vir_bytes bytes) );
- 04766 _PROTOTYPE( void sys_task, (void) );
- 04767 _PROTOTYPE( phys_bytes umap, (struct proc *rp, int seg, vir_bytes vir_addr,
- 04768 vir_bytes bytes) );
- 04769
- 04770 /* tty.c */
- 04771 _PROTOTYPE( void handle_events, (struct tty *tp) );
- 04772 _PROTOTYPE( void sigchar, (struct tty *tp, int sig) );
- 04773 _PROTOTYPE( void tty_task, (void) );
- 04774 _PROTOTYPE( int in_process, (struct tty *tp, char *buf, int count) );
- 04775 _PROTOTYPE( void out_process, (struct tty *tp, char *bstart, char *bpos,
- 04776 char *bend, int *icount, int *ocount) );
- 04777 _PROTOTYPE( void tty_wakeup, (clock_t now) );
- 04778 _PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
- 04779 int status) );
- 04780 _PROTOTYPE( void tty_devnop, (struct tty *tp) );
- 04781
- 04782 /* library */
- 04783 _PROTOTYPE( void *memcpy, (void *_s1, const void *_s2, size_t _n) );
- 04784
- .Op 55 src/kernel/proto.h
- 04785 #if (CHIP == INTEL)
- 04786
- 04787 /* clock.c */
- 04788 _PROTOTYPE( void milli_start, (struct milli_state *msp) );
- 04789 _PROTOTYPE( unsigned milli_elapsed, (struct milli_state *msp) );
- 04790 _PROTOTYPE( void milli_delay, (unsigned millisec) );
- 04791
- 04792 /* console.c */
- 04793 _PROTOTYPE( void cons_stop, (void) );
- 04794 _PROTOTYPE( void putk, (int c) );
- 04795 _PROTOTYPE( void scr_init, (struct tty *tp) );
- 04796 _PROTOTYPE( void toggle_scroll, (void) );
- 04797 _PROTOTYPE( int con_loadfont, (phys_bytes user_phys) );
- 04798 _PROTOTYPE( void select_console, (int cons_line) );
- 04799
- 04800 /* cstart.c */
- 04801 _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mcs, U16_t mds,
- 04802 U16_t parmoff, U16_t parmsize) );
- 04803 _PROTOTYPE( char *k_getenv, (char *name) );
- 04804
- 04805 /* exception.c */
- 04806 _PROTOTYPE( void exception, (unsigned vec_nr) );
- 04807
- 04808 /* i8259.c */
- 04809 _PROTOTYPE( irq_handler_t get_irq_handler, (int irq) );
- 04810 _PROTOTYPE( void put_irq_handler, (int irq, irq_handler_t handler) );
- 04811 _PROTOTYPE( void intr_init, (int mine) );
- 04812
- 04813 /* keyboard.c */
- 04814 _PROTOTYPE( void kb_init, (struct tty *tp) );
- 04815 _PROTOTYPE( int kbd_loadmap, (phys_bytes user_phys) );
- 04816 _PROTOTYPE( void wreboot, (int how) );
- 04817
- 04818 /* klib*.s */
- 04819 _PROTOTYPE( void bios13, (void) );
- 04820 _PROTOTYPE( phys_bytes check_mem, (phys_bytes base, phys_bytes size) );
- 04821 _PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset,
- 04822 phys_clicks dst_clicks, vir_bytes dst_offset) );
- 04823 _PROTOTYPE( int in_byte, (port_t port) );
- 04824 _PROTOTYPE( int in_word, (port_t port) );
- 04825 _PROTOTYPE( void lock, (void) );
- 04826 _PROTOTYPE( void unlock, (void) );
- 04827 _PROTOTYPE( void enable_irq, (unsigned irq) );
- 04828 _PROTOTYPE( int disable_irq, (unsigned irq) );
- 04829 _PROTOTYPE( u16_t mem_rdw, (segm_t segm, vir_bytes offset) );
- 04830 _PROTOTYPE( void out_byte, (port_t port, int value) );
- 04831 _PROTOTYPE( void out_word, (port_t port, int value) );
- 04832 _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
- 04833 phys_bytes count) );
- 04834 _PROTOTYPE( void port_read, (unsigned port, phys_bytes destination,
- 04835 unsigned bytcount) );
- 04836 _PROTOTYPE( void port_read_byte, (unsigned port, phys_bytes destination,
- 04837 unsigned bytcount) );
- 04838 _PROTOTYPE( void port_write, (unsigned port, phys_bytes source,
- 04839 unsigned bytcount) );
- 04840 _PROTOTYPE( void port_write_byte, (unsigned port, phys_bytes source,
- 04841 unsigned bytcount) );
- 04842 _PROTOTYPE( void reset, (void) );
- 04843 _PROTOTYPE( void vid_vid_copy, (unsigned src, unsigned dst, unsigned count));
- 04844 _PROTOTYPE( void mem_vid_copy, (u16_t *src, unsigned dst, unsigned count));
- .Ep 56 src/kernel/proto.h
- 04845 _PROTOTYPE( void level0, (void (*func)(void)) );
- 04846 _PROTOTYPE( void monitor, (void) );
- 04847
- 04848 /* misc.c */
- 04849 _PROTOTYPE( void mem_init, (void) );
- 04850
- 04851 /* mpx*.s */
- 04852 _PROTOTYPE( void idle_task, (void) );
- 04853 _PROTOTYPE( void restart, (void) );
- 04854
- 04855 /* The following are never called from C (pure asm procs). */
- 04856
- 04857 /* Exception handlers (real or protected mode), in numerical order. */
- 04858 void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
- 04859 void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
- 04860 void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
- 04861 void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
- 04862 void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
- 04863 void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
- 04864 void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
- 04865 void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
- 04866 void _PROTOTYPE( double_fault, (void) );
- 04867 void _PROTOTYPE( copr_seg_overrun, (void) );
- 04868 void _PROTOTYPE( inval_tss, (void) );
- 04869 void _PROTOTYPE( segment_not_present, (void) );
- 04870 void _PROTOTYPE( stack_exception, (void) );
- 04871 void _PROTOTYPE( general_protection, (void) );
- 04872 void _PROTOTYPE( page_fault, (void) );
- 04873 void _PROTOTYPE( copr_error, (void) );
- 04874
- 04875 /* Hardware interrupt handlers. */
- 04876 _PROTOTYPE( void hwint00, (void) );
- 04877 _PROTOTYPE( void hwint01, (void) );
- 04878 _PROTOTYPE( void hwint02, (void) );
- 04879 _PROTOTYPE( void hwint03, (void) );
- 04880 _PROTOTYPE( void hwint04, (void) );
- 04881 _PROTOTYPE( void hwint05, (void) );
- 04882 _PROTOTYPE( void hwint06, (void) );
- 04883 _PROTOTYPE( void hwint07, (void) );
- 04884 _PROTOTYPE( void hwint08, (void) );
- 04885 _PROTOTYPE( void hwint09, (void) );
- 04886 _PROTOTYPE( void hwint10, (void) );
- 04887 _PROTOTYPE( void hwint11, (void) );
- 04888 _PROTOTYPE( void hwint12, (void) );
- 04889 _PROTOTYPE( void hwint13, (void) );
- 04890 _PROTOTYPE( void hwint14, (void) );
- 04891 _PROTOTYPE( void hwint15, (void) );
- 04892
- 04893 /* Software interrupt handlers, in numerical order. */
- 04894 _PROTOTYPE( void trp, (void) );
- 04895 _PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
- 04896 _PROTOTYPE( void level0_call, (void) );
- 04897
- 04898 /* printer.c */
- 04899 _PROTOTYPE( void pr_restart, (void) );
- 04900
- 04901 /* protect.c */
- 04902 _PROTOTYPE( void prot_init, (void) );
- 04903 _PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
- 04904 phys_bytes size, int privilege) );
- .Op 57 src/kernel/proto.h
- 04905 _PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
- 04906 phys_bytes size, int privilege) );
- 04907 _PROTOTYPE( phys_bytes seg2phys, (U16_t seg) );
- 04908 _PROTOTYPE( void enable_iop, (struct proc *pp) );
- 04909
- 04910 /* pty.c */
- 04911 _PROTOTYPE( void do_pty, (struct tty *tp, message *m_ptr) );
- 04912 _PROTOTYPE( void pty_init, (struct tty *tp) );
- 04913
- 04914 /* system.c */
- 04915 _PROTOTYPE( void alloc_segments, (struct proc *rp) );
- 04916
- 04917 #endif /* (CHIP == INTEL) */
- 04918
- 04919 #endif /* PROTO_H */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/glo.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05000 /* Global variables used in the kernel. */
- 05001
- 05002 /* EXTERN is defined as extern except in table.c. */
- 05003 #ifdef _TABLE
- 05004 #undef EXTERN
- 05005 #define EXTERN
- 05006 #endif
- 05007
- 05008 /* Kernel memory. */
- 05009 EXTERN phys_bytes code_base; /* base of kernel code */
- 05010 EXTERN phys_bytes data_base; /* base of kernel data */
- 05011
- 05012 /* Low level interrupt communications. */
- 05013 EXTERN struct proc *held_head; /* head of queue of held-up interrupts */
- 05014 EXTERN struct proc *held_tail; /* tail of queue of held-up interrupts */
- 05015 EXTERN unsigned char k_reenter; /* kernel reentry count (entry count less 1)*/
- 05016
- 05017 /* Process table. Here to stop too many things having to include proc.h. */
- 05018 EXTERN struct proc *proc_ptr; /* pointer to currently running process */
- 05019
- 05020 /* Signals. */
- 05021 EXTERN int sig_procs; /* number of procs with p_pending != 0 */
- 05022
- 05023 /* Memory sizes. */
- 05024 EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
- 05025 EXTERN phys_clicks tot_mem_size; /* total system memory size */
- 05026
- 05027 /* Miscellaneous. */
- 05028 extern u16_t sizes[]; /* table filled in by boot monitor */
- 05029 extern struct tasktab tasktab[];/* initialized in table.c, so extern here */
- 05030 extern char *t_stack[]; /* initialized in table.c, so extern here */
- 05031 EXTERN unsigned lost_ticks; /* clock ticks counted outside the clock task */
- 05032 EXTERN clock_t tty_timeout; /* time to wake up the TTY task */
- 05033 EXTERN int current; /* currently visible console */
- 05034
- .Ep 58 src/kernel/glo.h
- 05035 #if (CHIP == INTEL)
- 05036
- 05037 /* Machine type. */
- 05038 EXTERN int pc_at; /* PC-AT compatible hardware interface */
- 05039 EXTERN int ps_mca; /* PS/2 with Micro Channel */
- 05040 EXTERN unsigned int processor; /* 86, 186, 286, 386, ... */
- 05041 #if _WORD_SIZE == 2
- 05042 EXTERN int protected_mode; /* nonzero if running in Intel protected mode*/
- 05043 #else
- 05044 #define protected_mode 1 /* 386 mode implies protected mode */
- 05045 #endif
- 05046
- 05047 /* Video card types. */
- 05048 EXTERN int ega; /* nonzero if console is EGA or VGA */
- 05049 EXTERN int vga; /* nonzero if console is VGA */
- 05050
- 05051 /* Memory sizes. */
- 05052 EXTERN unsigned ext_memsize; /* initialized by assembler startup code */
- 05053 EXTERN unsigned low_memsize;
- 05054
- 05055 /* Miscellaneous. */
- 05056 EXTERN irq_handler_t irq_table[NR_IRQ_VECTORS];
- 05057 EXTERN int irq_use; /* bit map of all in-use irq's */
- 05058 EXTERN reg_t mon_ss, mon_sp; /* monitor stack */
- 05059 EXTERN int mon_return; /* true if return to the monitor possible */
- 05060 EXTERN phys_bytes reboot_code; /* program for the boot monitor */
- 05061
- 05062 /* Variables that are initialized elsewhere are just extern here. */
- 05063 extern struct segdesc_s gdt[]; /* global descriptor table for protected mode*/
- 05064
- 05065 EXTERN _PROTOTYPE( void (*level0_func), (void) );
- 05066 #endif /* (CHIP == INTEL) */
- 05067
- 05068 #if (CHIP == M68000)
- 05069 /* Variables that are initialized elsewhere are just extern here. */
- 05070 extern int keypad; /* Flag for keypad mode */
- 05071 extern int app_mode; /* Flag for arrow key application mode */
- 05072 extern int STdebKey; /* nonzero if ctl-alt-Fx detected */
- 05073 extern struct tty *cur_cons; /* virtual cons currently displayed */
- 05074 extern unsigned char font8[]; /* 8 pixel wide font table (initialized) */
- 05075 extern unsigned char font12[]; /* 12 pixel wide font table (initialized) */
- 05076 extern unsigned char font16[]; /* 16 pixel wide font table (initialized) */
- 05077 extern unsigned short resolution; /* screen res; ST_RES_LOW..TT_RES_HIGH */
- 05078 #endif
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/proc.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05100 #ifndef PROC_H
- 05101 #define PROC_H
- 05102
- 05103 /* Here is the declaration of the process table. It contains the process'
- 05104 * registers, memory map, accounting, and message send/receive information.
- 05105 * Many assembly code routines reference fields in it. The offsets to these
- 05106 * fields are defined in the assembler include file sconst.h. When changing
- 05107 * 'proc', be sure to change sconst.h to match.
- 05108 */
- 05109
- .Op 59 src/kernel/proc.h
- 05110 struct proc {
- 05111 struct stackframe_s p_reg; /* process' registers saved in stack frame */
- 05112
- 05113 #if (CHIP == INTEL)
- 05114 reg_t p_ldt_sel; /* selector in gdt giving ldt base and limit*/
- 05115 struct segdesc_s p_ldt[2]; /* local descriptors for code and data */
- 05116 /* 2 is LDT_SIZE - avoid include protect.h */
- 05117 #endif /* (CHIP == INTEL) */
- 05118
- 05119 reg_t *p_stguard; /* stack guard word */
- 05120
- 05121 int p_nr; /* number of this process (for fast access) */
- 05122
- 05123 int p_int_blocked; /* nonzero if int msg blocked by busy task */
- 05124 int p_int_held; /* nonzero if int msg held by busy syscall */
- 05125 struct proc *p_nextheld; /* next in chain of held-up int processes */
- 05126
- 05127 int p_flags; /* P_SLOT_FREE, SENDING, RECEIVING, etc. */
- 05128 struct mem_map p_map[NR_SEGS];/* memory map */
- 05129 pid_t p_pid; /* process id passed in from MM */
- 05130
- 05131 clock_t user_time; /* user time in ticks */
- 05132 clock_t sys_time; /* sys time in ticks */
- 05133 clock_t child_utime; /* cumulative user time of children */
- 05134 clock_t child_stime; /* cumulative sys time of children */
- 05135 clock_t p_alarm; /* time of next alarm in ticks, or 0 */
- 05136
- 05137 struct proc *p_callerq; /* head of list of procs wishing to send */
- 05138 struct proc *p_sendlink; /* link to next proc wishing to send */
- 05139 message *p_messbuf; /* pointer to message buffer */
- 05140 int p_getfrom; /* from whom does process want to receive? */
- 05141 int p_sendto;
- 05142
- 05143 struct proc *p_nextready; /* pointer to next ready process */
- 05144 sigset_t p_pending; /* bit map for pending signals */
- 05145 unsigned p_pendcount; /* count of pending and unfinished signals */
- 05146
- 05147 char p_name[16]; /* name of the process */
- 05148 };
- 05149
- 05150 /* Guard word for task stacks. */
- 05151 #define STACK_GUARD ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF))
- 05152
- 05153 /* Bits for p_flags in proc[]. A process is runnable iff p_flags == 0. */
- 05154 #define P_SLOT_FREE 001 /* set when slot is not in use */
- 05155 #define NO_MAP 002 /* keeps unmapped forked child from running */
- 05156 #define SENDING 004 /* set when process blocked trying to send */
- 05157 #define RECEIVING 010 /* set when process blocked trying to recv */
- 05158 #define PENDING 020 /* set when inform() of signal pending */
- 05159 #define SIG_PENDING 040 /* keeps to-be-signalled proc from running */
- 05160 #define P_STOP 0100 /* set when process is being traced */
- 05161
- 05162 /* Magic process table addresses. */
- 05163 #define BEG_PROC_ADDR (&proc[0])
- 05164 #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
- 05165 #define END_TASK_ADDR (&proc[NR_TASKS])
- 05166 #define BEG_SERV_ADDR (&proc[NR_TASKS])
- 05167 #define BEG_USER_ADDR (&proc[NR_TASKS + LOW_USER])
- 05168
- 05169 #define NIL_PROC ((struct proc *) 0)
- .Ep 60 src/kernel/proc.h
- 05170 #define isidlehardware(n) ((n) == IDLE || (n) == HARDWARE)
- 05171 #define isokprocn(n) ((unsigned) ((n) + NR_TASKS) < NR_PROCS + NR_TASKS)
- 05172 #define isoksrc_dest(n) (isokprocn(n) || (n) == ANY)
- 05173 #define isoksusern(n) ((unsigned) (n) < NR_PROCS)
- 05174 #define isokusern(n) ((unsigned) ((n) - LOW_USER) < NR_PROCS - LOW_USER)
- 05175 #define isrxhardware(n) ((n) == ANY || (n) == HARDWARE)
- 05176 #define issysentn(n) ((n) == FS_PROC_NR || (n) == MM_PROC_NR)
- 05177 #define istaskp(p) ((p) < END_TASK_ADDR && (p) != proc_addr(IDLE))
- 05178 #define isuserp(p) ((p) >= BEG_USER_ADDR)
- 05179 #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
- 05180 #define cproc_addr(n) (&(proc + NR_TASKS)[(n)])
- 05181 #define proc_number(p) ((p)->p_nr)
- 05182 #define proc_vir2phys(p, vir)
- 05183 (((phys_bytes)(p)->p_map[D].mem_phys << CLICK_SHIFT)
- 05184 + (vir_bytes) (vir))
- 05185
- 05186 EXTERN struct proc proc[NR_TASKS + NR_PROCS]; /* process table */
- 05187 EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS];
- 05188 /* ptrs to process table slots; fast because now a process entry can be found
- 05189 by indexing the pproc_addr array, while accessing an element i requires
- 05190 a multiplication with sizeof(struct proc) to determine the address */
- 05191 EXTERN struct proc *bill_ptr; /* ptr to process to bill for clock ticks */
- 05192 EXTERN struct proc *rdy_head[NQ]; /* pointers to ready list headers */
- 05193 EXTERN struct proc *rdy_tail[NQ]; /* pointers to ready list tails */
- 05194
- 05195 #endif /* PROC_H */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/protect.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05200 /* Constants for protected mode. */
- 05201
- 05202 /* Table sizes. */
- 05203 #define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) /* spec. and LDT's */
- 05204 #define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */
- 05205 #define LDT_SIZE 2 /* contains CS and DS only */
- 05206
- 05207 /* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */
- 05208 #define GDT_INDEX 1 /* GDT descriptor */
- 05209 #define IDT_INDEX 2 /* IDT descriptor */
- 05210 #define DS_INDEX 3 /* kernel DS */
- 05211 #define ES_INDEX 4 /* kernel ES (386: flag 4 Gb at startup) */
- 05212 #define SS_INDEX 5 /* kernel SS (386: monitor SS at startup) */
- 05213 #define CS_INDEX 6 /* kernel CS */
- 05214 #define MON_CS_INDEX 7 /* temp for BIOS (386: monitor CS at startup) */
- 05215 #define TSS_INDEX 8 /* kernel TSS */
- 05216 #define DS_286_INDEX 9 /* scratch 16-bit source segment */
- 05217 #define ES_286_INDEX 10 /* scratch 16-bit destination segment */
- 05218 #define VIDEO_INDEX 11 /* video memory segment */
- 05219 #define DP_ETH0_INDEX 12 /* Western Digital Etherplus buffer */
- 05220 #define DP_ETH1_INDEX 13 /* Western Digital Etherplus buffer */
- 05221 #define FIRST_LDT_INDEX 14 /* rest of descriptors are LDT's */
- 05222
- 05223 #define GDT_SELECTOR 0x08 /* (GDT_INDEX * DESC_SIZE) bad for asld */
- 05224 #define IDT_SELECTOR 0x10 /* (IDT_INDEX * DESC_SIZE) */
- .Op 61 src/kernel/protect.h
- 05225 #define DS_SELECTOR 0x18 /* (DS_INDEX * DESC_SIZE) */
- 05226 #define ES_SELECTOR 0x20 /* (ES_INDEX * DESC_SIZE) */
- 05227 #define FLAT_DS_SELECTOR 0x21 /* less privileged ES */
- 05228 #define SS_SELECTOR 0x28 /* (SS_INDEX * DESC_SIZE) */
- 05229 #define CS_SELECTOR 0x30 /* (CS_INDEX * DESC_SIZE) */
- 05230 #define MON_CS_SELECTOR 0x38 /* (MON_CS_INDEX * DESC_SIZE) */
- 05231 #define TSS_SELECTOR 0x40 /* (TSS_INDEX * DESC_SIZE) */
- 05232 #define DS_286_SELECTOR 0x49 /* (DS_286_INDEX * DESC_SIZE + 1) */
- 05233 #define ES_286_SELECTOR 0x51 /* (ES_286_INDEX * DESC_SIZE + 1) */
- 05234 #define VIDEO_SELECTOR 0x59 /* (VIDEO_INDEX * DESC_SIZE + 1) */
- 05235 #define DP_ETH0_SELECTOR 0x61 /* (DP_ETH0_INDEX * DESC_SIZE) */
- 05236 #define DP_ETH1_SELECTOR 0x69 /* (DP_ETH1_INDEX * DESC_SIZE) */
- 05237
- 05238 /* Fixed local descriptors. */
- 05239 #define CS_LDT_INDEX 0 /* process CS */
- 05240 #define DS_LDT_INDEX 1 /* process DS=ES=FS=GS=SS */
- 05241
- 05242 /* Privileges. */
- 05243 #define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
- 05244 #define TASK_PRIVILEGE 1
- 05245 #define USER_PRIVILEGE 3
- 05246
- 05247 /* 286 hardware constants. */
- 05248
- 05249 /* Exception vector numbers. */
- 05250 #define BOUNDS_VECTOR 5 /* bounds check failed */
- 05251 #define INVAL_OP_VECTOR 6 /* invalid opcode */
- 05252 #define COPROC_NOT_VECTOR 7 /* coprocessor not available */
- 05253 #define DOUBLE_FAULT_VECTOR 8
- 05254 #define COPROC_SEG_VECTOR 9 /* coprocessor segment overrun */
- 05255 #define INVAL_TSS_VECTOR 10 /* invalid TSS */
- 05256 #define SEG_NOT_VECTOR 11 /* segment not present */
- 05257 #define STACK_FAULT_VECTOR 12 /* stack exception */
- 05258 #define PROTECTION_VECTOR 13 /* general protection */
- 05259
- 05260 /* Selector bits. */
- 05261 #define TI 0x04 /* table indicator */
- 05262 #define RPL 0x03 /* requester privilege level */
- 05263
- 05264 /* Descriptor structure offsets. */
- 05265 #define DESC_BASE 2 /* to base_low */
- 05266 #define DESC_BASE_MIDDLE 4 /* to base_middle */
- 05267 #define DESC_ACCESS 5 /* to access byte */
- 05268 #define DESC_SIZE 8 /* sizeof (struct segdesc_s) */
- 05269
- 05270 /* Segment sizes. */
- 05271 #define MAX_286_SEG_SIZE 0x10000L
- 05272
- 05273 /* Base and limit sizes and shifts. */
- 05274 #define BASE_MIDDLE_SHIFT 16 /* shift for base --> base_middle */
- 05275
- 05276 /* Access-byte and type-byte bits. */
- 05277 #define PRESENT 0x80 /* set for descriptor present */
- 05278 #define DPL 0x60 /* descriptor privilege level mask */
- 05279 #define DPL_SHIFT 5
- 05280 #define SEGMENT 0x10 /* set for segment-type descriptors */
- 05281
- 05282 /* Access-byte bits. */
- 05283 #define EXECUTABLE 0x08 /* set for executable segment */
- 05284 #define CONFORMING 0x04 /* set for conforming segment if executable */
- .Ep 62 src/kernel/protect.h
- 05285 #define EXPAND_DOWN 0x04 /* set for expand-down segment if !executable*/
- 05286 #define READABLE 0x02 /* set for readable segment if executable */
- 05287 #define WRITEABLE 0x02 /* set for writeable segment if !executable */
- 05288 #define TSS_BUSY 0x02 /* set if TSS descriptor is busy */
- 05289 #define ACCESSED 0x01 /* set if segment accessed */
- 05290
- 05291 /* Special descriptor types. */
- 05292 #define AVL_286_TSS 1 /* available 286 TSS */
- 05293 #define LDT 2 /* local descriptor table */
- 05294 #define BUSY_286_TSS 3 /* set transparently to the software */
- 05295 #define CALL_286_GATE 4 /* not used */
- 05296 #define TASK_GATE 5 /* only used by debugger */
- 05297 #define INT_286_GATE 6 /* interrupt gate, used for all vectors */
- 05298 #define TRAP_286_GATE 7 /* not used */
- 05299
- 05300 /* Extra 386 hardware constants. */
- 05301
- 05302 /* Exception vector numbers. */
- 05303 #define PAGE_FAULT_VECTOR 14
- 05304 #define COPROC_ERR_VECTOR 16 /* coprocessor error */
- 05305
- 05306 /* Descriptor structure offsets. */
- 05307 #define DESC_GRANULARITY 6 /* to granularity byte */
- 05308 #define DESC_BASE_HIGH 7 /* to base_high */
- 05309
- 05310 /* Base and limit sizes and shifts. */
- 05311 #define BASE_HIGH_SHIFT 24 /* shift for base --> base_high */
- 05312 #define BYTE_GRAN_MAX 0xFFFFFL /* maximum size for byte granular segment */
- 05313 #define GRANULARITY_SHIFT 16 /* shift for limit --> granularity */
- 05314 #define OFFSET_HIGH_SHIFT 16 /* shift for (gate) offset --> offset_high */
- 05315 #define PAGE_GRAN_SHIFT 12 /* extra shift for page granular limits */
- 05316
- 05317 /* Type-byte bits. */
- 05318 #define DESC_386_BIT 0x08 /* 386 types are obtained by ORing with this */
- 05319 /* LDT's and TASK_GATE's don't need it */
- 05320
- 05321 /* Granularity byte. */
- 05322 #define GRANULAR 0x80 /* set for 4K granularilty */
- 05323 #define DEFAULT 0x40 /* set for 32-bit defaults (executable seg) */
- 05324 #define BIG 0x40 /* set for "BIG" (expand-down seg) */
- 05325 #define AVL 0x10 /* 0 for available */
- 05326 #define LIMIT_HIGH 0x0F /* mask for high bits of limit */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/sconst.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05400 ! Miscellaneous constants used in assembler code.
- 05401 W = _WORD_SIZE ! Machine word size.
- 05402
- 05403 ! Offsets in struct proc. They MUST match proc.h.
- 05404 P_STACKBASE = 0
- 05405 #if _WORD_SIZE == 2
- 05406 ESREG = P_STACKBASE
- 05407 #else
- 05408 GSREG = P_STACKBASE
- 05409 FSREG = GSREG + 2 ! 386 introduces FS and GS segments
- .Op 63 src/kernel/sconst.h
- 05410 ESREG = FSREG + 2
- 05411 #endif
- 05412 DSREG = ESREG + 2
- 05413 DIREG = DSREG + 2
- 05414 SIREG = DIREG + W
- 05415 BPREG = SIREG + W
- 05416 STREG = BPREG + W ! hole for another SP
- 05417 BXREG = STREG + W
- 05418 DXREG = BXREG + W
- 05419 CXREG = DXREG + W
- 05420 AXREG = CXREG + W
- 05421 RETADR = AXREG + W ! return address for save() call
- 05422 PCREG = RETADR + W
- 05423 CSREG = PCREG + W
- 05424 PSWREG = CSREG + W
- 05425 SPREG = PSWREG + W
- 05426 SSREG = SPREG + W
- 05427 P_STACKTOP = SSREG + W
- 05428 P_LDT_SEL = P_STACKTOP
- 05429 P_LDT = P_LDT_SEL + W
- 05430
- 05431 #if _WORD_SIZE == 2
- 05432 Msize = 12 ! size of a message in 16-bit words
- 05433 #else
- 05434 Msize = 9 ! size of a message in 32-bit words
- 05435 #endif
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/assert.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05500 /*
- 05501 assert.h
- 05502 */
- 05503 #ifndef ASSERT_H
- 05504 #define ASSERT_H
- 05505
- 05506 #if DEBUG
- 05507
- 05508 #define INIT_ASSERT static char *assert_file= __FILE__;
- 05509
- 05510 void bad_assertion(char *file, int line, char *what);
- 05511 void bad_compare(char *file, int line, int lhs, char *what, int rhs);
- 05512
- 05513 #define assert(x) (!(x) ? bad_assertion(assert_file, __LINE__, #x)
- 05514 : (void) 0)
- 05515 #define compare(a,t,b) (!((a) t (b)) ? bad_compare(assert_file, __LINE__,
- 05516 (a), #a " " #t " " #b, (b)) : (void) 0)
- 05517 #else /* !DEBUG */
- 05518
- 05519 #define INIT_ASSERT /* nothing */
- 05520
- 05521 #define assert(x) (void)0
- 05522 #define compare(a,t,b) (void)0
- 05523
- 05524 #endif /* !DEBUG */
- .Ep 64 src/kernel/assert.h
- 05525
- 05526 #endif /* ASSERT_H */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/table.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05600 /* The object file of "table.c" contains all the data. In the *.h files,
- 05601 * declared variables appear with EXTERN in front of them, as in
- 05602 *
- 05603 * EXTERN int x;
- 05604 *
- 05605 * Normally EXTERN is defined as extern, so when they are included in another
- 05606 * file, no storage is allocated. If the EXTERN were not present, but just
- 05607 * say,
- 05608 *
- 05609 * int x;
- 05610 *
- 05611 * then including this file in several source files would cause 'x' to be
- 05612 * declared several times. While some linkers accept this, others do not,
- 05613 * so they are declared extern when included normally. However, it must
- 05614 * be declared for real somewhere. That is done here, by redefining
- 05615 * EXTERN as the null string, so the inclusion of all the *.h files in
- 05616 * table.c actually generates storage for them. All the initialized
- 05617 * variables are also declared here, since
- 05618 *
- 05619 * extern int x = 4;
- 05620 *
- 05621 * is not allowed. If such variables are shared, they must also be declared
- 05622 * in one of the *.h files without the initialization.
- 05623 */
- 05624
- 05625 #define _TABLE
- 05626
- 05627 #include "kernel.h"
- 05628 #include <termios.h>
- 05629 #include <minix/com.h>
- 05630 #include "proc.h"
- 05631 #include "tty.h"
- 05632
- 05633 /* The startup routine of each task is given below, from -NR_TASKS upwards.
- 05634 * The order of the names here MUST agree with the numerical values assigned to
- 05635 * the tasks in <minix/com.h>.
- 05636 */
- 05637 #define SMALL_STACK (128 * sizeof(char *))
- 05638
- 05639 #define TTY_STACK (3 * SMALL_STACK)
- 05640 #define SYN_ALRM_STACK SMALL_STACK
- 05641
- 05642 #define DP8390_STACK (SMALL_STACK * ENABLE_NETWORKING)
- 05643
- 05644 #if (CHIP == INTEL)
- 05645 #define IDLE_STACK ((3+3+4) * sizeof(char *)) /* 3 intr, 3 temps, 4 db */
- 05646 #else
- 05647 #define IDLE_STACK SMALL_STACK
- 05648 #endif
- 05649
- .Op 65 src/kernel/table.c
- 05650 #define PRINTER_STACK SMALL_STACK
- 05651
- 05652 #if (CHIP == INTEL)
- 05653 #define WINCH_STACK (2 * SMALL_STACK * ENABLE_WINI)
- 05654 #else
- 05655 #define WINCH_STACK (3 * SMALL_STACK * ENABLE_WINI)
- 05656 #endif
- 05657
- 05658 #if (MACHINE == ATARI)
- 05659 #define SCSI_STACK (3 * SMALL_STACK)
- 05660 #endif
- 05661
- 05662 #if (MACHINE == IBM_PC)
- 05663 #define SCSI_STACK (2 * SMALL_STACK * ENABLE_SCSI)
- 05664 #endif
- 05665
- 05666 #define CDROM_STACK (4 * SMALL_STACK * ENABLE_CDROM)
- 05667 #define AUDIO_STACK (4 * SMALL_STACK * ENABLE_AUDIO)
- 05668 #define MIXER_STACK (4 * SMALL_STACK * ENABLE_AUDIO)
- 05669
- 05670 #define FLOP_STACK (3 * SMALL_STACK)
- 05671 #define MEM_STACK SMALL_STACK
- 05672 #define CLOCK_STACK SMALL_STACK
- 05673 #define SYS_STACK SMALL_STACK
- 05674 #define HARDWARE_STACK 0 /* dummy task, uses kernel stack */
- 05675
- 05676
- 05677 #define TOT_STACK_SPACE (TTY_STACK + DP8390_STACK + SCSI_STACK +
- 05678 SYN_ALRM_STACK + IDLE_STACK + HARDWARE_STACK + PRINTER_STACK +
- 05679 WINCH_STACK + FLOP_STACK + MEM_STACK + CLOCK_STACK + SYS_STACK +
- 05680 CDROM_STACK + AUDIO_STACK + MIXER_STACK)
- 05681
- 05682
- 05683 /* SCSI, CDROM and AUDIO may in the future have different choices like
- 05684 * WINCHESTER, but for now the choice is fixed.
- 05685 */
- 05686 #define scsi_task aha_scsi_task
- 05687 #define cdrom_task mcd_task
- 05688 #define audio_task dsp_task
- 05689
- 05690
- 05691 /*
- 05692 * Some notes about the following table:
- 05693 * 1) The tty_task should always be first so that other tasks can use printf
- 05694 * if their initialisation has problems.
- 05695 * 2) If you add a new kernel task, add it before the printer task.
- 05696 * 3) The task name is used for the process name (p_name).
- 05697 */
- 05698
- 05699 PUBLIC struct tasktab tasktab[] = {
- 05700 { tty_task, TTY_STACK, "TTY" },
- 05701 #if ENABLE_NETWORKING
- 05702 { dp8390_task, DP8390_STACK, "DP8390" },
- 05703 #endif
- 05704 #if ENABLE_CDROM
- 05705 { cdrom_task, CDROM_STACK, "CDROM" },
- 05706 #endif
- 05707 #if ENABLE_AUDIO
- 05708 { audio_task, AUDIO_STACK, "AUDIO" },
- 05709 { mixer_task, MIXER_STACK, "MIXER" },
- .Ep 66 src/kernel/table.c
- 05710 #endif
- 05711 #if ENABLE_SCSI
- 05712 { scsi_task, SCSI_STACK, "SCSI" },
- 05713 #endif
- 05714 #if ENABLE_WINI
- 05715 { winchester_task, WINCH_STACK, "WINCH" },
- 05716 #endif
- 05717 { syn_alrm_task, SYN_ALRM_STACK, "SYN_AL" },
- 05718 { idle_task, IDLE_STACK, "IDLE" },
- 05719 { printer_task, PRINTER_STACK, "PRINTER" },
- 05720 { floppy_task, FLOP_STACK, "FLOPPY" },
- 05721 { mem_task, MEM_STACK, "MEMORY" },
- 05722 { clock_task, CLOCK_STACK, "CLOCK" },
- 05723 { sys_task, SYS_STACK, "SYS" },
- 05724 { 0, HARDWARE_STACK, "HARDWAR" },
- 05725 { 0, 0, "MM" },
- 05726 { 0, 0, "FS" },
- 05727 #if ENABLE_NETWORKING
- 05728 { 0, 0, "INET" },
- 05729 #endif
- 05730 { 0, 0, "INIT" },
- 05731 };
- 05732
- 05733 /* Stack space for all the task stacks. (Declared as (char *) to align it.) */
- 05734 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
- 05735
- 05736 /*
- 05737 * The number of kernel tasks must be the same as NR_TASKS.
- 05738 * If NR_TASKS is not correct then you will get the compile error:
- 05739 * "array size is negative"
- 05740 */
- 05741
- 05742 #define NKT (sizeof tasktab / sizeof (struct tasktab) - (INIT_PROC_NR + 1))
- 05743
- 05744 extern int dummy_tasktab_check[NR_TASKS == NKT ? 1 : -1];
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/mpx.s
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05800 #
- 05801 ! Chooses between the 8086 and 386 versions of the Minix startup code.
- 05802
- 05803 #include <minix/config.h>
- 05804 #if _WORD_SIZE == 2
- 05805 #include "mpx88.s"
- 05806 #else
- 05807 #include "mpx386.s"
- 05808 #endif
- .Op 67 src/kernel/mpx386.s
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/mpx386.s
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 05900 #
- 05901 ! This file contains the assembler startup code for Minix and the 32-bit
- 05902 ! interrupt handlers. It cooperates with start.c to set up a good
- 05903 ! environment for main().
- 05904
- 05905 ! This file is part of the lowest layer of the MINIX kernel. The other part
- 05906 ! is "proc.c". The lowest layer does process switching and message handling.
- 05907
- 05908 ! Every transition to the kernel goes through this file. Transitions are
- 05909 ! caused by sending/receiving messages and by most interrupts. (RS232
- 05910 ! interrupts may be handled in the file "rs2.s" and then they rarely enter
- 05911 ! the kernel.)
- 05912
- 05913 ! Transitions to the kernel may be nested. The initial entry may be with a
- 05914 ! system call, exception or hardware interrupt; reentries may only be made
- 05915 ! by hardware interrupts. The count of reentries is kept in "k_reenter".
- 05916 ! It is important for deciding whether to switch to the kernel stack and
- 05917 ! for protecting the message passing code in "proc.c".
- 05918
- 05919 ! For the message passing trap, most of the machine state is saved in the
- 05920 ! proc table. (Some of the registers need not be saved.) Then the stack is
- 05921 ! switched to "k_stack", and interrupts are reenabled. Finally, the system
- 05922 ! call handler (in C) is called. When it returns, interrupts are disabled
- 05923 ! again and the code falls into the restart routine, to finish off held-up
- 05924 ! interrupts and run the process or task whose pointer is in "proc_ptr".
- 05925
- 05926 ! Hardware interrupt handlers do the same, except (1) The entire state must
- 05927 ! be saved. (2) There are too many handlers to do this inline, so the save
- 05928 ! routine is called. A few cycles are saved by pushing the address of the
- 05929 ! appropiate restart routine for a return later. (3) A stack switch is
- 05930 ! avoided when the stack is already switched. (4) The (master) 8259 interrupt
- 05931 ! controller is reenabled centrally in save(). (5) Each interrupt handler
- 05932 ! masks its interrupt line using the 8259 before enabling (other unmasked)
- 05933 ! interrupts, and unmasks it after servicing the interrupt. This limits the
- 05934 ! nest level to the number of lines and protects the handler from itself.
- 05935
- 05936 ! For communication with the boot monitor at startup time some constant
- 05937 ! data are compiled into the beginning of the text segment. This facilitates
- 05938 ! reading the data at the start of the boot process, since only the first
- 05939 ! sector of the file needs to be read.
- 05940
- 05941 ! Some data storage is also allocated at the end of this file. This data
- 05942 ! will be at the start of the data segment of the kernel and will be read
- 05943 ! and modified by the boot monitor before the kernel starts.
- 05944
- 05945 ! sections
- 05946
- 05947 .sect .text
- 05948 begtext:
- 05949 .sect .rom
- 05950 begrom:
- 05951 .sect .data
- 05952 begdata:
- 05953 .sect .bss
- 05954 begbss:
- .Ep 68 src/kernel/mpx386.s
- 05955
- 05956 #include <minix/config.h>
- 05957 #include <minix/const.h>
- 05958 #include <minix/com.h>
- 05959 #include "const.h"
- 05960 #include "protect.h"
- 05961 #include "sconst.h"
- 05962
- 05963 /* Selected 386 tss offsets. */
- 05964 #define TSS3_S_SP0 4
- 05965
- 05966 ! Exported functions
- 05967 ! Note: in assembly language the .define statement applied to a function name
- 05968 ! is loosely equivalent to a prototype in C code -- it makes it possible to
- 05969 ! link to an entity declared in the assembly code but does not create
- 05970 ! the entity.
- 05971
- 05972 .define _idle_task
- 05973 .define _restart
- 05974 .define save
- 05975
- 05976 .define _divide_error
- 05977 .define _single_step_exception
- 05978 .define _nmi
- 05979 .define _breakpoint_exception
- 05980 .define _overflow
- 05981 .define _bounds_check
- 05982 .define _inval_opcode
- 05983 .define _copr_not_available
- 05984 .define _double_fault
- 05985 .define _copr_seg_overrun
- 05986 .define _inval_tss
- 05987 .define _segment_not_present
- 05988 .define _stack_exception
- 05989 .define _general_protection
- 05990 .define _page_fault
- 05991 .define _copr_error
- 05992
- 05993 .define _hwint00 ! handlers for hardware interrupts
- 05994 .define _hwint01
- 05995 .define _hwint02
- 05996 .define _hwint03
- 05997 .define _hwint04
- 05998 .define _hwint05
- 05999 .define _hwint06
- 06000 .define _hwint07
- 06001 .define _hwint08
- 06002 .define _hwint09
- 06003 .define _hwint10
- 06004 .define _hwint11
- 06005 .define _hwint12
- 06006 .define _hwint13
- 06007 .define _hwint14
- 06008 .define _hwint15
- 06009
- 06010 .define _s_call
- 06011 .define _p_s_call
- 06012 .define _level0_call
- 06013
- 06014 ! Imported functions.
- .Op 69 src/kernel/mpx386.s
- 06015
- 06016 .extern _cstart
- 06017 .extern _main
- 06018 .extern _exception
- 06019 .extern _interrupt
- 06020 .extern _sys_call
- 06021 .extern _unhold
- 06022
- 06023 ! Exported variables.
- 06024 ! Note: when used with a variable the .define does not reserve storage,
- 06025 ! it makes the name externally visible so it may be linked to.
- 06026
- 06027 .define begbss
- 06028 .define begdata
- 06029 .define _sizes
- 06030
- 06031 ! Imported variables.
- 06032
- 06033 .extern _gdt
- 06034 .extern _code_base
- 06035 .extern _data_base
- 06036 .extern _held_head
- 06037 .extern _k_reenter
- 06038 .extern _pc_at
- 06039 .extern _proc_ptr
- 06040 .extern _ps_mca
- 06041 .extern _tss
- 06042 .extern _level0_func
- 06043 .extern _mon_sp
- 06044 .extern _mon_return
- 06045 .extern _reboot_code
- 06046
- 06047 .sect .text
- 06048 !*===========================================================================*
- 06049 !* MINIX *
- 06050 !*===========================================================================*
- 06051 MINIX: ! this is the entry point for the MINIX kernel
- 06052 jmp over_flags ! skip over the next few bytes
- 06053 .data2 CLICK_SHIFT ! for the monitor: memory granularity
- 06054 flags:
- 06055 .data2 0x002D ! boot monitor flags:
- 06056 ! call in 386 mode, make stack,
- 06057 ! load high, will return
- 06058 nop ! extra byte to sync up disassembler
- 06059 over_flags:
- 06060
- 06061 ! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds
- 06062 ! right. The ss descriptor still references the monitor data segment.)
- 06063 movzx esp, sp ! monitor stack is a 16 bit stack
- 06064 push ebp
- 06065 mov ebp, esp
- 06066 push esi
- 06067 push edi
- 06068 cmp 4(ebp), 0 ! nonzero if return possible
- 06069 jz noret
- 06070 inc (_mon_return)
- 06071 noret: mov (_mon_sp), esp ! save stack pointer for later return
- 06072
- 06073 ! Copy the monitor global descriptor table to the address space of kernel and
- 06074 ! switch over to it. Prot_init() can then update it with immediate effect.
- .Ep 70 src/kernel/mpx386.s
- 06075
- 06076 sgdt (_gdt+GDT_SELECTOR) ! get the monitor gdtr
- 06077 mov esi, (_gdt+GDT_SELECTOR+2) ! absolute address of GDT
- 06078 mov ebx, _gdt ! address of kernel GDT
- 06079 mov ecx, 8*8 ! copying eight descriptors
- 06080 copygdt:
- 06081 eseg movb al, (esi)
- 06082 movb (ebx), al
- 06083 inc esi
- 06084 inc ebx
- 06085 loop copygdt
- 06086 mov eax, (_gdt+DS_SELECTOR+2) ! base of kernel data
- 06087 and eax, 0x00FFFFFF ! only 24 bits
- 06088 add eax, _gdt ! eax = vir2phys(gdt)
- 06089 mov (_gdt+GDT_SELECTOR+2), eax ! set base of GDT
- 06090 lgdt (_gdt+GDT_SELECTOR) ! switch over to kernel GDT
- 06091
- 06092 ! Locate boot parameters, set up kernel segment registers and stack.
- 06093 mov ebx, 8(ebp) ! boot parameters offset
- 06094 mov edx, 12(ebp) ! boot parameters length
- 06095 mov ax, ds ! kernel data
- 06096 mov es, ax
- 06097 mov fs, ax
- 06098 mov gs, ax
- 06099 mov ss, ax
- 06100 mov esp, k_stktop ! set sp to point to the top of kernel stack
- 06101
- 06102 ! Call C startup code to set up a proper environment to run main().
- 06103 push edx
- 06104 push ebx
- 06105 push SS_SELECTOR
- 06106 push MON_CS_SELECTOR
- 06107 push DS_SELECTOR
- 06108 push CS_SELECTOR
- 06109 call _cstart ! cstart(cs, ds, mcs, mds, parmoff, parmlen)
- 06110 add esp, 6*4
- 06111
- 06112 ! Reload gdtr, idtr and the segment registers to global descriptor table set
- 06113 ! up by prot_init().
- 06114
- 06115 lgdt (_gdt+GDT_SELECTOR)
- 06116 lidt (_gdt+IDT_SELECTOR)
- 06117
- 06118 jmpf CS_SELECTOR:csinit
- 06119 csinit:
- 06120 o16 mov ax, DS_SELECTOR
- 06121 mov ds, ax
- 06122 mov es, ax
- 06123 mov fs, ax
- 06124 mov gs, ax
- 06125 mov ss, ax
- 06126 o16 mov ax, TSS_SELECTOR ! no other TSS is used
- 06127 ltr ax
- 06128 push 0 ! set flags to known good state
- 06129 popf ! esp, clear nested task and int enable
- 06130
- 06131 jmp _main ! main()
- 06132
- 06133
- 06134 !*===========================================================================*
- .Op 71 src/kernel/mpx386.s
- 06135 !* interrupt handlers *
- 06136 !* interrupt handlers for 386 32-bit protected mode *
- 06137 !*===========================================================================*
- 06138
- 06139 !*===========================================================================*
- 06140 !* hwint00 - 07 *
- 06141 !*===========================================================================*
- 06142 ! Note this is a macro, it looks like a subroutine.
- 06143 #define hwint_master(irq)
- 06144 call save /* save interrupted process state */;
- 06145 inb INT_CTLMASK ;
- 06146 orb al, [1<<irq] ;
- 06147 outb INT_CTLMASK /* disable the irq */;
- 06148 movb al, ENABLE ;
- 06149 outb INT_CTL /* reenable master 8259 */;
- 06150 sti /* enable interrupts */;
- 06151 push irq /* irq */;
- 06152 call (_irq_table + 4*irq) /* eax = (*irq_table[irq])(irq) */;
- 06153 pop ecx ;
- 06154 cli /* disable interrupts */;
- 06155 test eax, eax /* need to reenable irq? */;
- 06156 jz 0f ;
- 06157 inb INT_CTLMASK ;
- 06158 andb al, ~[1<<irq] ;
- 06159 outb INT_CTLMASK /* enable the irq */;
- 06160 0: ret /* restart (another) process */
- 06161
- 06162 ! Each of these entry points is an expansion of the hwint_master macro
- 06163 .align 16
- 06164 _hwint00: ! Interrupt routine for irq 0 (the clock).
- 06165 hwint_master(0)
- 06166
- 06167 .align 16
- 06168 _hwint01: ! Interrupt routine for irq 1 (keyboard)
- 06169 hwint_master(1)
- 06170
- 06171 .align 16
- 06172 _hwint02: ! Interrupt routine for irq 2 (cascade!)
- 06173 hwint_master(2)
- 06174
- 06175 .align 16
- 06176 _hwint03: ! Interrupt routine for irq 3 (second serial)
- 06177 hwint_master(3)
- 06178
- 06179 .align 16
- 06180 _hwint04: ! Interrupt routine for irq 4 (first serial)
- 06181 hwint_master(4)
- 06182
- 06183 .align 16
- 06184 _hwint05: ! Interrupt routine for irq 5 (XT winchester)
- 06185 hwint_master(5)
- 06186
- 06187 .align 16
- 06188 _hwint06: ! Interrupt routine for irq 6 (floppy)
- 06189 hwint_master(6)
- 06190
- 06191 .align 16
- 06192 _hwint07: ! Interrupt routine for irq 7 (printer)
- 06193 hwint_master(7)
- 06194
- .Ep 72 src/kernel/mpx386.s
- 06195 !*===========================================================================*
- 06196 !* hwint08 - 15 *
- 06197 !*===========================================================================*
- 06198 ! Note this is a macro, it looks like a subroutine.
- 06199 #define hwint_slave(irq)
- 06200 call save /* save interrupted process state */;
- 06201 inb INT2_CTLMASK ;
- 06202 orb al, [1<<[irq-8]] ;
- 06203 outb INT2_CTLMASK /* disable the irq */;
- 06204 movb al, ENABLE ;
- 06205 outb INT_CTL /* reenable master 8259 */;
- 06206 jmp .+2 /* delay */;
- 06207 outb INT2_CTL /* reenable slave 8259 */;
- 06208 sti /* enable interrupts */;
- 06209 push irq /* irq */;
- 06210 call (_irq_table + 4*irq) /* eax = (*irq_table[irq])(irq) */;
- 06211 pop ecx ;
- 06212 cli /* disable interrupts */;
- 06213 test eax, eax /* need to reenable irq? */;
- 06214 jz 0f ;
- 06215 inb INT2_CTLMASK ;
- 06216 andb al, ~[1<<[irq-8]] ;
- 06217 outb INT2_CTLMASK /* enable the irq */;
- 06218 0: ret /* restart (another) process */
- 06219
- 06220 ! Each of these entry points is an expansion of the hwint_slave macro
- 06221 .align 16
- 06222 _hwint08: ! Interrupt routine for irq 8 (realtime clock)
- 06223 hwint_slave(8)
- 06224
- 06225 .align 16
- 06226 _hwint09: ! Interrupt routine for irq 9 (irq 2 redirected)
- 06227 hwint_slave(9)
- 06228
- 06229 .align 16
- 06230 _hwint10: ! Interrupt routine for irq 10
- 06231 hwint_slave(10)
- 06232
- 06233 .align 16
- 06234 _hwint11: ! Interrupt routine for irq 11
- 06235 hwint_slave(11)
- 06236
- 06237 .align 16
- 06238 _hwint12: ! Interrupt routine for irq 12
- 06239 hwint_slave(12)
- 06240
- 06241 .align 16
- 06242 _hwint13: ! Interrupt routine for irq 13 (FPU exception)
- 06243 hwint_slave(13)
- 06244
- 06245 .align 16
- 06246 _hwint14: ! Interrupt routine for irq 14 (AT winchester)
- 06247 hwint_slave(14)
- 06248
- 06249 .align 16
- 06250 _hwint15: ! Interrupt routine for irq 15
- 06251 hwint_slave(15)
- 06252
- 06253 !*===========================================================================*
- 06254 !* save *
- .Op 73 src/kernel/mpx386.s
- 06255 !*===========================================================================*
- 06256 ! Save for protected mode.
- 06257 ! This is much simpler than for 8086 mode, because the stack already points
- 06258 ! into the process table, or has already been switched to the kernel stack.
- 06259
- 06260 .align 16
- 06261 save:
- 06262 cld ! set direction flag to a known value
- 06263 pushad ! save "general" registers
- 06264 o16 push ds ! save ds
- 06265 o16 push es ! save es
- 06266 o16 push fs ! save fs
- 06267 o16 push gs ! save gs
- 06268 mov dx, ss ! ss is kernel data segment
- 06269 mov ds, dx ! load rest of kernel segments
- 06270 mov es, dx ! kernel does not use fs, gs
- 06271 mov eax, esp ! prepare to return
- 06272 incb (_k_reenter) ! from -1 if not reentering
- 06273 jnz set_restart1 ! stack is already kernel stack
- 06274 mov esp, k_stktop
- 06275 push _restart ! build return address for int handler
- 06276 xor ebp, ebp ! for stacktrace
- 06277 jmp RETADR-P_STACKBASE(eax)
- 06278
- 06279 .align 4
- 06280 set_restart1:
- 06281 push restart1
- 06282 jmp RETADR-P_STACKBASE(eax)
- 06283
- 06284 !*===========================================================================*
- 06285 !* _s_call *
- 06286 !*===========================================================================*
- 06287 .align 16
- 06288 _s_call:
- 06289 _p_s_call:
- 06290 cld ! set direction flag to a known value
- 06291 sub esp, 6*4 ! skip RETADR, eax, ecx, edx, ebx, est
- 06292 push ebp ! stack already points into proc table
- 06293 push esi
- 06294 push edi
- 06295 o16 push ds
- 06296 o16 push es
- 06297 o16 push fs
- 06298 o16 push gs
- 06299 mov dx, ss
- 06300 mov ds, dx
- 06301 mov es, dx
- 06302 incb (_k_reenter)
- 06303 mov esi, esp ! assumes P_STACKBASE == 0
- 06304 mov esp, k_stktop
- 06305 xor ebp, ebp ! for stacktrace
- 06306 ! end of inline save
- 06307 sti ! allow SWITCHER to be interrupted
- 06308 ! now set up parameters for sys_call()
- 06309 push ebx ! pointer to user message
- 06310 push eax ! src/dest
- 06311 push ecx ! SEND/RECEIVE/BOTH
- 06312 call _sys_call ! sys_call(function, src_dest, m_ptr)
- 06313 ! caller is now explicitly in proc_ptr
- 06314 mov AXREG(esi), eax ! sys_call MUST PRESERVE si
- .Ep 74 src/kernel/mpx386.s
- 06315 cli ! disable interrupts
- 06316
- 06317 ! Fall into code to restart proc/task running.
- 06318
- 06319 !*===========================================================================*
- 06320 !* restart *
- 06321 !*===========================================================================*
- 06322 _restart:
- 06323
- 06324 ! Flush any held-up interrupts.
- 06325 ! This reenables interrupts, so the current interrupt handler may reenter.
- 06326 ! This does not matter, because the current handler is about to exit and no
- 06327 ! other handlers can reenter since flushing is only done when k_reenter == 0.
- 06328
- 06329 cmp (_held_head), 0 ! do fast test to usually avoid function call
- 06330 jz over_call_unhold
- 06331 call _unhold ! this is rare so overhead acceptable
- 06332 over_call_unhold:
- 06333 mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
- 06334 lldt P_LDT_SEL(esp) ! enable segment descriptors for task
- 06335 lea eax, P_STACKTOP(esp) ! arrange for next interrupt
- 06336 mov (_tss+TSS3_S_SP0), eax ! to save state in process table
- 06337 restart1:
- 06338 decb (_k_reenter)
- 06339 o16 pop gs
- 06340 o16 pop fs
- 06341 o16 pop es
- 06342 o16 pop ds
- 06343 popad
- 06344 add esp, 4 ! skip return adr
- 06345 iretd ! continue process
- 06346
- 06347 !*===========================================================================*
- 06348 !* exception handlers *
- 06349 !*===========================================================================*
- 06350 _divide_error:
- 06351 push DIVIDE_VECTOR
- 06352 jmp exception
- 06353
- 06354 _single_step_exception:
- 06355 push DEBUG_VECTOR
- 06356 jmp exception
- 06357
- 06358 _nmi:
- 06359 push NMI_VECTOR
- 06360 jmp exception
- 06361
- 06362 _breakpoint_exception:
- 06363 push BREAKPOINT_VECTOR
- 06364 jmp exception
- 06365
- 06366 _overflow:
- 06367 push OVERFLOW_VECTOR
- 06368 jmp exception
- 06369
- 06370 _bounds_check:
- 06371 push BOUNDS_VECTOR
- 06372 jmp exception
- 06373
- 06374 _inval_opcode:
- .Op 75 src/kernel/mpx386.s
- 06375 push INVAL_OP_VECTOR
- 06376 jmp exception
- 06377
- 06378 _copr_not_available:
- 06379 push COPROC_NOT_VECTOR
- 06380 jmp exception
- 06381
- 06382 _double_fault:
- 06383 push DOUBLE_FAULT_VECTOR
- 06384 jmp errexception
- 06385
- 06386 _copr_seg_overrun:
- 06387 push COPROC_SEG_VECTOR
- 06388 jmp exception
- 06389
- 06390 _inval_tss:
- 06391 push INVAL_TSS_VECTOR
- 06392 jmp errexception
- 06393
- 06394 _segment_not_present:
- 06395 push SEG_NOT_VECTOR
- 06396 jmp errexception
- 06397
- 06398 _stack_exception:
- 06399 push STACK_FAULT_VECTOR
- 06400 jmp errexception
- 06401
- 06402 _general_protection:
- 06403 push PROTECTION_VECTOR
- 06404 jmp errexception
- 06405
- 06406 _page_fault:
- 06407 push PAGE_FAULT_VECTOR
- 06408 jmp errexception
- 06409
- 06410 _copr_error:
- 06411 push COPROC_ERR_VECTOR
- 06412 jmp exception
- 06413
- 06414 !*===========================================================================*
- 06415 !* exception *
- 06416 !*===========================================================================*
- 06417 ! This is called for all exceptions which do not push an error code.
- 06418
- 06419 .align 16
- 06420 exception:
- 06421 sseg mov (trap_errno), 0 ! clear trap_errno
- 06422 sseg pop (ex_number)
- 06423 jmp exception1
- 06424
- 06425 !*===========================================================================*
- 06426 !* errexception *
- 06427 !*===========================================================================*
- 06428 ! This is called for all exceptions which push an error code.
- 06429
- 06430 .align 16
- 06431 errexception:
- 06432 sseg pop (ex_number)
- 06433 sseg pop (trap_errno)
- 06434 exception1: ! Common for all exceptions.
- .Ep 76 src/kernel/mpx386.s
- 06435 push eax ! eax is scratch register
- 06436 mov eax, 0+4(esp) ! old eip
- 06437 sseg mov (old_eip), eax
- 06438 movzx eax, 4+4(esp) ! old cs
- 06439 sseg mov (old_cs), eax
- 06440 mov eax, 8+4(esp) ! old eflags
- 06441 sseg mov (old_eflags), eax
- 06442 pop eax
- 06443 call save
- 06444 push (old_eflags)
- 06445 push (old_cs)
- 06446 push (old_eip)
- 06447 push (trap_errno)
- 06448 push (ex_number)
- 06449 call _exception ! (ex_number, trap_errno, old_eip,
- 06450 ! old_cs, old_eflags)
- 06451 add esp, 5*4
- 06452 cli
- 06453 ret
- 06454
- 06455 !*===========================================================================*
- 06456 !* level0_call *
- 06457 !*===========================================================================*
- 06458 _level0_call:
- 06459 call save
- 06460 jmp (_level0_func)
- 06461
- 06462 !*===========================================================================*
- 06463 !* idle_task *
- 06464 !*===========================================================================*
- 06465 _idle_task: ! executed when there is no work
- 06466 jmp _idle_task ! a "hlt" before this fails in protected mode
- 06467
- 06468 !*===========================================================================*
- 06469 !* data *
- 06470 !*===========================================================================*
- 06471 ! These declarations assure that storage will be allocated at the very
- 06472 ! beginning of the kernel data section, so the boot monitor can be easily
- 06473 ! told how to patch these locations. Note that the magic number is put
- 06474 ! here by the compiler, but will be read by, and then overwritten by,
- 06475 ! the boot monitor. When the kernel starts the sizes array will be
- 06476 ! found here, as if it had been initialized by the compiler.
- 06477
- 06478 .sect .rom ! Before the string table please
- 06479 _sizes: ! sizes of kernel, mm, fs filled in by boot
- 06480 .data2 0x526F ! this must be the first data entry (magic #)
- 06481 .space 16*2*2-2 ! monitor uses previous word and this space
- 06482 ! extra space allows for additional servers
- 06483 .sect .bss
- 06484 k_stack:
- 06485 .space K_STACK_BYTES ! kernel stack
- 06486 k_stktop: ! top of kernel stack
- 06487 .comm ex_number, 4
- 06488 .comm trap_errno, 4
- 06489 .comm old_eip, 4
- 06490 .comm old_cs, 4
- 06491 .comm old_eflags, 4
- .Op 77 src/kernel/start.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/start.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 06500 /* This file contains the C startup code for Minix on Intel processors.
- 06501 * It cooperates with mpx.s to set up a good environment for main().
- 06502 *
- 06503 * This code runs in real mode for a 16 bit kernel and may have to switch
- 06504 * to protected mode for a 286.
- 06505 *
- 06506 * For a 32 bit kernel this already runs in protected mode, but the selectors
- 06507 * are still those given by the BIOS with interrupts disabled, so the
- 06508 * descriptors need to be reloaded and interrupt descriptors made.
- 06509 */
- 06510
- 06511 #include "kernel.h"
- 06512 #include <stdlib.h>
- 06513 #include <minix/boot.h>
- 06514 #include "protect.h"
- 06515
- 06516 PRIVATE char k_environ[256]; /* environment strings passed by loader */
- 06517
- 06518 FORWARD _PROTOTYPE( int k_atoi, (char *s) );
- 06519
- 06520
- 06521 /*==========================================================================*
- 06522 * cstart *
- 06523 *==========================================================================*/
- 06524 PUBLIC void cstart(cs, ds, mcs, mds, parmoff, parmsize)
- 06525 U16_t cs, ds; /* Kernel code and data segment */
- 06526 U16_t mcs, mds; /* Monitor code and data segment */
- 06527 U16_t parmoff, parmsize; /* boot parameters offset and length */
- 06528 {
- 06529 /* Perform system initializations prior to calling main(). */
- 06530
- 06531 register char *envp;
- 06532 phys_bytes mcode_base, mdata_base;
- 06533 unsigned mon_start;
- 06534
- 06535 /* Record where the kernel and the monitor are. */
- 06536 code_base = seg2phys(cs);
- 06537 data_base = seg2phys(ds);
- 06538 mcode_base = seg2phys(mcs);
- 06539 mdata_base = seg2phys(mds);
- 06540
- 06541 /* Initialize protected mode descriptors. */
- 06542 prot_init();
- 06543
- 06544 /* Copy the boot parameters to kernel memory. */
- 06545 if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
- 06546 phys_copy(mdata_base + parmoff, vir2phys(k_environ), (phys_bytes) parmsize);
- 06547
- 06548 /* Convert important boot environment variables. */
- 06549 boot_parameters.bp_rootdev = k_atoi(k_getenv("rootdev"));
- 06550 boot_parameters.bp_ramimagedev = k_atoi(k_getenv("ramimagedev"));
- 06551 boot_parameters.bp_ramsize = k_atoi(k_getenv("ramsize"));
- 06552 boot_parameters.bp_processor = k_atoi(k_getenv("processor"));
- 06553
- 06554 /* Type of VDU: */
- .Ep 78 src/kernel/start.c
- 06555 envp = k_getenv("video");
- 06556 if (strcmp(envp, "ega") == 0) ega = TRUE;
- 06557 if (strcmp(envp, "vga") == 0) vga = ega = TRUE;
- 06558
- 06559 /* Memory sizes: */
- 06560 low_memsize = k_atoi(k_getenv("memsize"));
- 06561 ext_memsize = k_atoi(k_getenv("emssize"));
- 06562
- 06563 /* Processor? */
- 06564 processor = boot_parameters.bp_processor; /* 86, 186, 286, 386, ... */
- 06565
- 06566 /* XT, AT or MCA bus? */
- 06567 envp = k_getenv("bus");
- 06568 if (envp == NIL_PTR || strcmp(envp, "at") == 0) {
- 06569 pc_at = TRUE;
- 06570 } else
- 06571 if (strcmp(envp, "mca") == 0) {
- 06572 pc_at = ps_mca = TRUE;
- 06573 }
- 06574
- 06575 /* Decide if mode is protected. */
- 06576 #if _WORD_SIZE == 2
- 06577 protected_mode = processor >= 286;
- 06578 #endif
- 06579
- 06580 /* Is there a monitor to return to? If so then keep it safe. */
- 06581 if (!protected_mode) mon_return = 0;
- 06582 mon_start = mcode_base / 1024;
- 06583 if (mon_return && low_memsize > mon_start) low_memsize = mon_start;
- 06584
- 06585 /* Return to assembler code to switch to protected mode (if 286), reload
- 06586 * selectors and call main().
- 06587 */
- 06588 }
-
-
- 06591 /*==========================================================================*
- 06592 * k_atoi *
- 06593 *==========================================================================*/
- 06594 PRIVATE int k_atoi(s)
- 06595 register char *s;
- 06596 {
- 06597 /* Convert string to integer. */
- 06598
- 06599 return strtol(s, (char **) NULL, 10);
- 06600 }
-
-
- 06603 /*==========================================================================*
- 06604 * k_getenv *
- 06605 *==========================================================================*/
- 06606 PUBLIC char *k_getenv(name)
- 06607 char *name;
- 06608 {
- 06609 /* Get environment value - kernel version of getenv to avoid setting up the
- 06610 * usual environment array.
- 06611 */
- 06612
- 06613 register char *namep;
- 06614 register char *envp;
- .Op 79 src/kernel/start.c
- 06615
- 06616 for (envp = k_environ; *envp != 0;) {
- 06617 for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
- 06618 ;
- 06619 if (*namep == ' ' && *envp == '=') return(envp + 1);
- 06620 while (*envp++ != 0)
- 06621 ;
- 06622 }
- 06623 return(NIL_PTR);
- 06624 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/main.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 06700 /* This file contains the main program of MINIX. The routine main()
- 06701 * initializes the system and starts the ball rolling by setting up the proc
- 06702 * table, interrupt vectors, and scheduling each task to run to initialize
- 06703 * itself.
- 06704 *
- 06705 * The entries into this file are:
- 06706 * main: MINIX main program
- 06707 * panic: abort MINIX due to a fatal error
- 06708 */
- 06709
- 06710 #include "kernel.h"
- 06711 #include <signal.h>
- 06712 #include <unistd.h>
- 06713 #include <minix/callnr.h>
- 06714 #include <minix/com.h>
- 06715 #include "proc.h"
- 06716
- 06717
- 06718 /*===========================================================================*
- 06719 * main *
- 06720 *===========================================================================*/
- 06721 PUBLIC void main()
- 06722 {
- 06723 /* Start the ball rolling. */
- 06724
- 06725 register struct proc *rp;
- 06726 register int t;
- 06727 int sizeindex;
- 06728 phys_clicks text_base;
- 06729 vir_clicks text_clicks;
- 06730 vir_clicks data_clicks;
- 06731 phys_bytes phys_b;
- 06732 reg_t ktsb; /* kernel task stack base */
- 06733 struct memory *memp;
- 06734 struct tasktab *ttp;
- 06735
- 06736 /* Initialize the interrupt controller. */
- 06737 intr_init(1);
- 06738
- 06739 /* Interpret memory sizes. */
- .Ep 80 src/kernel/main.c
- 06740 mem_init();
- 06741
- 06742 /* Clear the process table.
- 06743 * Set up mappings for proc_addr() and proc_number() macros.
- 06744 */
- 06745 for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
- 06746 rp->p_flags = P_SLOT_FREE;
- 06747 rp->p_nr = t; /* proc number from ptr */
- 06748 (pproc_addr + NR_TASKS)[t] = rp; /* proc ptr from number */
- 06749 }
- 06750
- 06751 /* Set up proc table entries for tasks and servers. The stacks of the
- 06752 * kernel tasks are initialized to an array in data space. The stacks
- 06753 * of the servers have been added to the data segment by the monitor, so
- 06754 * the stack pointer is set to the end of the data segment. All the
- 06755 * processes are in low memory on the 8086. On the 386 only the kernel
- 06756 * is in low memory, the rest if loaded in extended memory.
- 06757 */
- 06758
- 06759 /* Task stacks. */
- 06760 ktsb = (reg_t) t_stack;
- 06761
- 06762 for (t = -NR_TASKS; t <= LOW_USER; ++t) {
- 06763 rp = proc_addr(t); /* t's process slot */
- 06764 ttp = &tasktab[t + NR_TASKS]; /* t's task attributes */
- 06765 strcpy(rp->p_name, ttp->name);
- 06766 if (t < 0) {
- 06767 if (ttp->stksize > 0) {
- 06768 rp->p_stguard = (reg_t *) ktsb;
- 06769 *rp->p_stguard = STACK_GUARD;
- 06770 }
- 06771 ktsb += ttp->stksize;
- 06772 rp->p_reg.sp = ktsb;
- 06773 text_base = code_base >> CLICK_SHIFT;
- 06774 /* tasks are all in the kernel */
- 06775 sizeindex = 0; /* and use the full kernel sizes */
- 06776 memp = &mem[0]; /* remove from this memory chunk */
- 06777 } else {
- 06778 sizeindex = 2 * t + 2; /* MM, FS, INIT have their own sizes */
- 06779 }
- 06780 rp->p_reg.pc = (reg_t) ttp->initial_pc;
- 06781 rp->p_reg.psw = istaskp(rp) ? INIT_TASK_PSW : INIT_PSW;
- 06782
- 06783 text_clicks = sizes[sizeindex];
- 06784 data_clicks = sizes[sizeindex + 1];
- 06785 rp->p_map[T].mem_phys = text_base;
- 06786 rp->p_map[T].mem_len = text_clicks;
- 06787 rp->p_map[D].mem_phys = text_base + text_clicks;
- 06788 rp->p_map[D].mem_len = data_clicks;
- 06789 rp->p_map[S].mem_phys = text_base + text_clicks + data_clicks;
- 06790 rp->p_map[S].mem_vir = data_clicks; /* empty - stack is in data */
- 06791 text_base += text_clicks + data_clicks; /* ready for next, if server */
- 06792 memp->size -= (text_base - memp->base);
- 06793 memp->base = text_base; /* memory no longer free */
- 06794
- 06795 if (t >= 0) {
- 06796 /* Initialize the server stack pointer. Take it down one word
- 06797 * to give crtso.s something to use as "argc".
- 06798 */
- 06799 rp->p_reg.sp = (rp->p_map[S].mem_vir +
- .Op 81 src/kernel/main.c
- 06800 rp->p_map[S].mem_len) << CLICK_SHIFT;
- 06801 rp->p_reg.sp -= sizeof(reg_t);
- 06802 }
- 06803
- 06804 #if _WORD_SIZE == 4
- 06805 /* Servers are loaded in extended memory if in 386 mode. */
- 06806 if (t < 0) {
- 06807 memp = &mem[1];
- 06808 text_base = 0x100000 >> CLICK_SHIFT;
- 06809 }
- 06810 #endif
- 06811 if (!isidlehardware(t)) lock_ready(rp); /* IDLE, HARDWARE neveready */
- 06812 rp->p_flags = 0;
- 06813
- 06814 alloc_segments(rp);
- 06815 }
- 06816
- 06817 proc[NR_TASKS+INIT_PROC_NR].p_pid = 1;/* INIT of course has pid 1 */
- 06818 bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
- 06819 lock_pick_proc();
- 06820
- 06821 /* Now go to the assembly code to start running the current process. */
- 06822 restart();
- 06823 }
-
-
- 06826 /*===========================================================================*
- 06827 * panic *
- 06828 *===========================================================================*/
- 06829 PUBLIC void panic(s,n)
- 06830 _CONST char *s;
- 06831 int n;
- 06832 {
- 06833 /* The system has run aground of a fatal error. Terminate execution.
- 06834 * If the panic originated in MM or FS, the string will be empty and the
- 06835 * file system already syncked. If the panic originates in the kernel, we are
- 06836 * kind of stuck.
- 06837 */
- 06838
- 06839 if (*s != 0) {
- 06840 printf("nKernel panic: %s",s);
- 06841 if (n != NO_NUM) printf(" %d", n);
- 06842 printf("n");
- 06843 }
- 06844 wreboot(RBT_PANIC);
- 06845 }
- .Ep 82 src/kernel/proc.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/proc.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 06900 /* This file contains essentially all of the process and message handling.
- 06901 * It has two main entry points from the outside:
- 06902 *
- 06903 * sys_call: called when a process or task does SEND, RECEIVE or SENDREC
- 06904 * interrupt: called by interrupt routines to send a message to task
- 06905 *
- 06906 * It also has several minor entry points:
- 06907 *
- 06908 * lock_ready: put a process on one of the ready queues so it can be run
- 06909 * lock_unready: remove a process from the ready queues
- 06910 * lock_sched: a process has run too long; schedule another one
- 06911 * lock_mini_send: send a message (used by interrupt signals, etc.)
- 06912 * lock_pick_proc: pick a process to run (used by system initialization)
- 06913 * unhold: repeat all held-up interrupts
- 06914 */
- 06915
- 06916 #include "kernel.h"
- 06917 #include <minix/callnr.h>
- 06918 #include <minix/com.h>
- 06919 #include "proc.h"
- 06920
- 06921 PRIVATE unsigned char switching; /* nonzero to inhibit interrupt() */
- 06922
- 06923 FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dest,
- 06924 message *m_ptr) );
- 06925 FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
- 06926 message *m_ptr) );
- 06927 FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
- 06928 FORWARD _PROTOTYPE( void sched, (void) );
- 06929 FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
- 06930 FORWARD _PROTOTYPE( void pick_proc, (void) );
- 06931
- 06932 #define CopyMess(s,sp,sm,dp,dm)
- 06933 cp_mess(s, (sp)->p_map[D].mem_phys, (vir_bytes)sm, (dp)->p_map[D].mem_phys, (vir_bytes)dm)
- 06934
- 06935 /*===========================================================================*
- 06936 * interrupt *
- 06937 *===========================================================================*/
- 06938 PUBLIC void interrupt(task)
- 06939 int task; /* number of task to be started */
- 06940 {
- 06941 /* An interrupt has occurred. Schedule the task that handles it. */
- 06942
- 06943 register struct proc *rp; /* pointer to task's proc entry */
- 06944
- 06945 rp = proc_addr(task);
- 06946
- 06947 /* If this call would compete with other process-switching functions, put
- 06948 * it on the 'held' queue to be flushed at the next non-competing restart().
- 06949 * The competing conditions are:
- 06950 * (1) k_reenter == (typeof k_reenter) -1:
- 06951 * Call from the task level, typically from an output interrupt
- 06952 * routine. An interrupt handler might reenter interrupt(). Rare,
- 06953 * so not worth special treatment.
- 06954 * (2) k_reenter > 0:
- .Op 83 src/kernel/proc.c
- 06955 * Call from a nested interrupt handler. A previous interrupt handler
- 06956 * might be inside interrupt() or sys_call().
- 06957 * (3) switching != 0:
- 06958 * Some process-switching function other than interrupt() is being
- 06959 * called from the task level, typically sched() from CLOCK. An
- 06960 * interrupt handler might call interrupt and pass the k_reenter test.
- 06961 */
- 06962 if (k_reenter != 0 || switching) {
- 06963 lock();
- 06964 if (!rp->p_int_held) {
- 06965 rp->p_int_held = TRUE;
- 06966 if (held_head != NIL_PROC)
- 06967 held_tail->p_nextheld = rp;
- 06968 else
- 06969 held_head = rp;
- 06970 held_tail = rp;
- 06971 rp->p_nextheld = NIL_PROC;
- 06972 }
- 06973 unlock();
- 06974 return;
- 06975 }
- 06976
- 06977 /* If task is not waiting for an interrupt, record the blockage. */
- 06978 if ( (rp->p_flags & (RECEIVING | SENDING)) != RECEIVING ||
- 06979 !isrxhardware(rp->p_getfrom)) {
- 06980 rp->p_int_blocked = TRUE;
- 06981 return;
- 06982 }
- 06983
- 06984 /* Destination is waiting for an interrupt.
- 06985 * Send it a message with source HARDWARE and type HARD_INT.
- 06986 * No more information can be reliably provided since interrupt messages
- 06987 * are not queued.
- 06988 */
- 06989 rp->p_messbuf->m_source = HARDWARE;
- 06990 rp->p_messbuf->m_type = HARD_INT;
- 06991 rp->p_flags &= ~RECEIVING;
- 06992 rp->p_int_blocked = FALSE;
- 06993
- 06994 /* Make rp ready and run it unless a task is already running. This is
- 06995 * ready(rp) in-line for speed.
- 06996 */
- 06997 if (rdy_head[TASK_Q] != NIL_PROC)
- 06998 rdy_tail[TASK_Q]->p_nextready = rp;
- 06999 else
- 07000 proc_ptr = rdy_head[TASK_Q] = rp;
- 07001 rdy_tail[TASK_Q] = rp;
- 07002 rp->p_nextready = NIL_PROC;
- 07003 }
-
- 07005 /*===========================================================================*
- 07006 * sys_call *
- 07007 *===========================================================================*/
- 07008 PUBLIC int sys_call(function, src_dest, m_ptr)
- 07009 int function; /* SEND, RECEIVE, or BOTH */
- 07010 int src_dest; /* source to receive from or dest to send to */
- 07011 message *m_ptr; /* pointer to message */
- 07012 {
- 07013 /* The only system calls that exist in MINIX are sending and receiving
- 07014 * messages. These are done by trapping to the kernel with an INT instruction.
- .Ep 84 src/kernel/proc.c
- 07015 * The trap is caught and sys_call() is called to send or receive a message
- 07016 * (or both). The caller is always given by proc_ptr.
- 07017 */
- 07018
- 07019 register struct proc *rp;
- 07020 int n;
- 07021
- 07022 /* Check for bad system call parameters. */
- 07023 if (!isoksrc_dest(src_dest)) return(E_BAD_SRC);
- 07024 rp = proc_ptr;
- 07025
- 07026 if (isuserp(rp) && function != BOTH) return(E_NO_PERM);
- 07027
- 07028 /* The parameters are ok. Do the call. */
- 07029 if (function & SEND) {
- 07030 /* Function = SEND or BOTH. */
- 07031 n = mini_send(rp, src_dest, m_ptr);
- 07032 if (function == SEND || n != OK)
- 07033 return(n); /* done, or SEND failed */
- 07034 }
- 07035
- 07036 /* Function = RECEIVE or BOTH.
- 07037 * We have checked user calls are BOTH, and trust 'function' otherwise.
- 07038 */
- 07039 return(mini_rec(rp, src_dest, m_ptr));
- 07040 }
-
- 07042 /*===========================================================================*
- 07043 * mini_send *
- 07044 *===========================================================================*/
- 07045 PRIVATE int mini_send(caller_ptr, dest, m_ptr)
- 07046 register struct proc *caller_ptr; /* who is trying to send a message? */
- 07047 int dest; /* to whom is message being sent? */
- 07048 message *m_ptr; /* pointer to message buffer */
- 07049 {
- 07050 /* Send a message from 'caller_ptr' to 'dest'. If 'dest' is blocked waiting
- 07051 * for this message, copy the message to it and unblock 'dest'. If 'dest' is
- 07052 * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
- 07053 */
- 07054
- 07055 register struct proc *dest_ptr, *next_ptr;
- 07056 vir_bytes vb; /* message buffer pointer as vir_bytes */
- 07057 vir_clicks vlo, vhi; /* virtual clicks containing message to send */
- 07058
- 07059 /* User processes are only allowed to send to FS and MM. Check for this. */
- 07060 if (isuserp(caller_ptr) && !issysentn(dest)) return(E_BAD_DEST);
- 07061 dest_ptr = proc_addr(dest); /* pointer to destination's proc entry */
- 07062 if (dest_ptr->p_flags & P_SLOT_FREE) return(E_BAD_DEST); /* dead dest */
- 07063
- 07064 /* This check allows a message to be anywhere in data or stack or gap.
- 07065 * It will have to be made more elaborate later for machines which
- 07066 * don't have the gap mapped.
- 07067 */
- 07068 vb = (vir_bytes) m_ptr;
- 07069 vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
- 07070 vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT; /* vir click for top of msg */
- 07071 if (vlo < caller_ptr->p_map[D].mem_vir || vlo > vhi ||
- 07072 vhi >= caller_ptr->p_map[S].mem_vir + caller_ptr->p_map[S].mem_len)
- 07073 return(EFAULT);
- 07074
- .Op 85 src/kernel/proc.c
- 07075 /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
- 07076 if (dest_ptr->p_flags & SENDING) {
- 07077 next_ptr = proc_addr(dest_ptr->p_sendto);
- 07078 while (TRUE) {
- 07079 if (next_ptr == caller_ptr) return(ELOCKED);
- 07080 if (next_ptr->p_flags & SENDING)
- 07081 next_ptr = proc_addr(next_ptr->p_sendto);
- 07082 else
- 07083 break;
- 07084 }
- 07085 }
- 07086
- 07087 /* Check to see if 'dest' is blocked waiting for this message. */
- 07088 if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
- 07089 (dest_ptr->p_getfrom == ANY ||
- 07090 dest_ptr->p_getfrom == proc_number(caller_ptr))) {
- 07091 /* Destination is indeed waiting for this message. */
- 07092 CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
- 07093 dest_ptr->p_messbuf);
- 07094 dest_ptr->p_flags &= ~RECEIVING; /* deblock destination */
- 07095 if (dest_ptr->p_flags == 0) ready(dest_ptr);
- 07096 } else {
- 07097 /* Destination is not waiting. Block and queue caller. */
- 07098 caller_ptr->p_messbuf = m_ptr;
- 07099 if (caller_ptr->p_flags == 0) unready(caller_ptr);
- 07100 caller_ptr->p_flags |= SENDING;
- 07101 caller_ptr->p_sendto= dest;
- 07102
- 07103 /* Process is now blocked. Put in on the destination's queue. */
- 07104 if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
- 07105 dest_ptr->p_callerq = caller_ptr;
- 07106 else {
- 07107 while (next_ptr->p_sendlink != NIL_PROC)
- 07108 next_ptr = next_ptr->p_sendlink;
- 07109 next_ptr->p_sendlink = caller_ptr;
- 07110 }
- 07111 caller_ptr->p_sendlink = NIL_PROC;
- 07112 }
- 07113 return(OK);
- 07114 }
-
- 07116 /*===========================================================================*
- 07117 * mini_rec *
- 07118 *===========================================================================*/
- 07119 PRIVATE int mini_rec(caller_ptr, src, m_ptr)
- 07120 register struct proc *caller_ptr; /* process trying to get message */
- 07121 int src; /* which message source is wanted (or ANY) */
- 07122 message *m_ptr; /* pointer to message buffer */
- 07123 {
- 07124 /* A process or task wants to get a message. If one is already queued,
- 07125 * acquire it and deblock the sender. If no message from the desired source
- 07126 * is available, block the caller. No need to check parameters for validity.
- 07127 * Users calls are always sendrec(), and mini_send() has checked already.
- 07128 * Calls from the tasks, MM, and FS are trusted.
- 07129 */
- 07130
- 07131 register struct proc *sender_ptr;
- 07132 register struct proc *previous_ptr;
- 07133
- 07134 /* Check to see if a message from desired source is already available. */
- .Ep 86 src/kernel/proc.c
- 07135 if (!(caller_ptr->p_flags & SENDING)) {
- 07136 /* Check caller queue. */
- 07137 for (sender_ptr = caller_ptr->p_callerq; sender_ptr != NIL_PROC;
- 07138 previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) {
- 07139 if (src == ANY || src == proc_number(sender_ptr)) {
- 07140 /* An acceptable message has been found. */
- 07141 CopyMess(proc_number(sender_ptr), sender_ptr,
- 07142 sender_ptr->p_messbuf, caller_ptr, m_ptr);
- 07143 if (sender_ptr == caller_ptr->p_callerq)
- 07144 caller_ptr->p_callerq = sender_ptr->p_sendlink;
- 07145 else
- 07146 previous_ptr->p_sendlink = sender_ptr->p_sendlink;
- 07147 if ((sender_ptr->p_flags &= ~SENDING) == 0)
- 07148 ready(sender_ptr); /* deblock sender */
- 07149 return(OK);
- 07150 }
- 07151 }
- 07152
- 07153 /* Check for blocked interrupt. */
- 07154 if (caller_ptr->p_int_blocked && isrxhardware(src)) {
- 07155 m_ptr->m_source = HARDWARE;
- 07156 m_ptr->m_type = HARD_INT;
- 07157 caller_ptr->p_int_blocked = FALSE;
- 07158 return(OK);
- 07159 }
- 07160 }
- 07161
- 07162 /* No suitable message is available. Block the process trying to receive. */
- 07163 caller_ptr->p_getfrom = src;
- 07164 caller_ptr->p_messbuf = m_ptr;
- 07165 if (caller_ptr->p_flags == 0) unready(caller_ptr);
- 07166 caller_ptr->p_flags |= RECEIVING;
- 07167
- 07168 /* If MM has just blocked and there are kernel signals pending, now is the
- 07169 * time to tell MM about them, since it will be able to accept the message.
- 07170 */
- 07171 if (sig_procs > 0 && proc_number(caller_ptr) == MM_PROC_NR && src == ANY)
- 07172 inform();
- 07173 return(OK);
- 07174 }
-
- 07176 /*===========================================================================*
- 07177 * pick_proc *
- 07178 *===========================================================================*/
- 07179 PRIVATE void pick_proc()
- 07180 {
- 07181 /* Decide who to run now. A new process is selected by setting 'proc_ptr'.
- 07182 * When a fresh user (or idle) process is selected, record it in 'bill_ptr',
- 07183 * so the clock task can tell who to bill for system time.
- 07184 */
- 07185
- 07186 register struct proc *rp; /* process to run */
- 07187
- 07188 if ( (rp = rdy_head[TASK_Q]) != NIL_PROC) {
- 07189 proc_ptr = rp;
- 07190 return;
- 07191 }
- 07192 if ( (rp = rdy_head[SERVER_Q]) != NIL_PROC) {
- 07193 proc_ptr = rp;
- 07194 return;
- .Op 87 src/kernel/proc.c
- 07195 }
- 07196 if ( (rp = rdy_head[USER_Q]) != NIL_PROC) {
- 07197 proc_ptr = rp;
- 07198 bill_ptr = rp;
- 07199 return;
- 07200 }
- 07201 /* No one is ready. Run the idle task. The idle task might be made an
- 07202 * always-ready user task to avoid this special case.
- 07203 */
- 07204 bill_ptr = proc_ptr = proc_addr(IDLE);
- 07205 }
-
- 07207 /*===========================================================================*
- 07208 * ready *
- 07209 *===========================================================================*/
- 07210 PRIVATE void ready(rp)
- 07211 register struct proc *rp; /* this process is now runnable */
- 07212 {
- 07213 /* Add 'rp' to the end of one of the queues of runnable processes. Three
- 07214 * queues are maintained:
- 07215 * TASK_Q - (highest priority) for runnable tasks
- 07216 * SERVER_Q - (middle priority) for MM and FS only
- 07217 * USER_Q - (lowest priority) for user processes
- 07218 */
- 07219
- 07220 if (istaskp(rp)) {
- 07221 if (rdy_head[TASK_Q] != NIL_PROC)
- 07222 /* Add to tail of nonempty queue. */
- 07223 rdy_tail[TASK_Q]->p_nextready = rp;
- 07224 else {
- 07225 proc_ptr = /* run fresh task next */
- 07226 rdy_head[TASK_Q] = rp; /* add to empty queue */
- 07227 }
- 07228 rdy_tail[TASK_Q] = rp;
- 07229 rp->p_nextready = NIL_PROC; /* new entry has no successor */
- 07230 return;
- 07231 }
- 07232 if (!isuserp(rp)) { /* others are similar */
- 07233 if (rdy_head[SERVER_Q] != NIL_PROC)
- 07234 rdy_tail[SERVER_Q]->p_nextready = rp;
- 07235 else
- 07236 rdy_head[SERVER_Q] = rp;
- 07237 rdy_tail[SERVER_Q] = rp;
- 07238 rp->p_nextready = NIL_PROC;
- 07239 return;
- 07240 }
- 07241 if (rdy_head[USER_Q] == NIL_PROC)
- 07242 rdy_tail[USER_Q] = rp;
- 07243 rp->p_nextready = rdy_head[USER_Q];
- 07244 rdy_head[USER_Q] = rp;
- 07245 /*
- 07246 if (rdy_head[USER_Q] != NIL_PROC)
- 07247 rdy_tail[USER_Q]->p_nextready = rp;
- 07248 else
- 07249 rdy_head[USER_Q] = rp;
- 07250 rdy_tail[USER_Q] = rp;
- 07251 rp->p_nextready = NIL_PROC;
- 07252 */
- 07253 }
-
- .Ep 88 src/kernel/proc.c
- 07255 /*===========================================================================*
- 07256 * unready *
- 07257 *===========================================================================*/
- 07258 PRIVATE void unready(rp)
- 07259 register struct proc *rp; /* this process is no longer runnable */
- 07260 {
- 07261 /* A process has blocked. */
- 07262
- 07263 register struct proc *xp;
- 07264 register struct proc **qtail; /* TASK_Q, SERVER_Q, or USER_Q rdy_tail */
- 07265
- 07266 if (istaskp(rp)) {
- 07267 /* task stack still ok? */
- 07268 if (*rp->p_stguard != STACK_GUARD)
- 07269 panic("stack overrun by task", proc_number(rp));
- 07270
- 07271 if ( (xp = rdy_head[TASK_Q]) == NIL_PROC) return;
- 07272 if (xp == rp) {
- 07273 /* Remove head of queue */
- 07274 rdy_head[TASK_Q] = xp->p_nextready;
- 07275 if (rp == proc_ptr) pick_proc();
- 07276 return;
- 07277 }
- 07278 qtail = &rdy_tail[TASK_Q];
- 07279 }
- 07280 else if (!isuserp(rp)) {
- 07281 if ( (xp = rdy_head[SERVER_Q]) == NIL_PROC) return;
- 07282 if (xp == rp) {
- 07283 rdy_head[SERVER_Q] = xp->p_nextready;
- 07284 pick_proc();
- 07285 return;
- 07286 }
- 07287 qtail = &rdy_tail[SERVER_Q];
- 07288 } else
- 07289 {
- 07290 if ( (xp = rdy_head[USER_Q]) == NIL_PROC) return;
- 07291 if (xp == rp) {
- 07292 rdy_head[USER_Q] = xp->p_nextready;
- 07293 pick_proc();
- 07294 return;
- 07295 }
- 07296 qtail = &rdy_tail[USER_Q];
- 07297 }
- 07298
- 07299 /* Search body of queue. A process can be made unready even if it is
- 07300 * not running by being sent a signal that kills it.
- 07301 */
- 07302 while (xp->p_nextready != rp)
- 07303 if ( (xp = xp->p_nextready) == NIL_PROC) return;
- 07304 xp->p_nextready = xp->p_nextready->p_nextready;
- 07305 if (*qtail == rp) *qtail = xp;
- 07306 }
-
- 07308 /*===========================================================================*
- 07309 * sched *
- 07310 *===========================================================================*/
- 07311 PRIVATE void sched()
- 07312 {
- 07313 /* The current process has run too long. If another low priority (user)
- 07314 * process is runnable, put the current process on the end of the user queue,
- .Op 89 src/kernel/proc.c
- 07315 * possibly promoting another user to head of the queue.
- 07316 */
- 07317
- 07318 if (rdy_head[USER_Q] == NIL_PROC) return;
- 07319
- 07320 /* One or more user processes queued. */
- 07321 rdy_tail[USER_Q]->p_nextready = rdy_head[USER_Q];
- 07322 rdy_tail[USER_Q] = rdy_head[USER_Q];
- 07323 rdy_head[USER_Q] = rdy_head[USER_Q]->p_nextready;
- 07324 rdy_tail[USER_Q]->p_nextready = NIL_PROC;
- 07325 pick_proc();
- 07326 }
-
- 07328 /*==========================================================================*
- 07329 * lock_mini_send *
- 07330 *==========================================================================*/
- 07331 PUBLIC int lock_mini_send(caller_ptr, dest, m_ptr)
- 07332 struct proc *caller_ptr; /* who is trying to send a message? */
- 07333 int dest; /* to whom is message being sent? */
- 07334 message *m_ptr; /* pointer to message buffer */
- 07335 {
- 07336 /* Safe gateway to mini_send() for tasks. */
- 07337
- 07338 int result;
- 07339
- 07340 switching = TRUE;
- 07341 result = mini_send(caller_ptr, dest, m_ptr);
- 07342 switching = FALSE;
- 07343 return(result);
- 07344 }
-
- 07346 /*==========================================================================*
- 07347 * lock_pick_proc *
- 07348 *==========================================================================*/
- 07349 PUBLIC void lock_pick_proc()
- 07350 {
- 07351 /* Safe gateway to pick_proc() for tasks. */
- 07352
- 07353 switching = TRUE;
- 07354 pick_proc();
- 07355 switching = FALSE;
- 07356 }
-
- 07358 /*==========================================================================*
- 07359 * lock_ready *
- 07360 *==========================================================================*/
- 07361 PUBLIC void lock_ready(rp)
- 07362 struct proc *rp; /* this process is now runnable */
- 07363 {
- 07364 /* Safe gateway to ready() for tasks. */
- 07365
- 07366 switching = TRUE;
- 07367 ready(rp);
- 07368 switching = FALSE;
- 07369 }
-
-
- 07372 /*==========================================================================*
- 07373 * lock_unready *
- 07374 *==========================================================================*/
- .Ep 90 src/kernel/proc.c
- 07375 PUBLIC void lock_unready(rp)
- 07376 struct proc *rp; /* this process is no longer runnable */
- 07377 {
- 07378 /* Safe gateway to unready() for tasks. */
- 07379
- 07380 switching = TRUE;
- 07381 unready(rp);
- 07382 switching = FALSE;
- 07383 }
-
- 07385 /*==========================================================================*
- 07386 * lock_sched *
- 07387 *==========================================================================*/
- 07388 PUBLIC void lock_sched()
- 07389 {
- 07390 /* Safe gateway to sched() for tasks. */
- 07391
- 07392 switching = TRUE;
- 07393 sched();
- 07394 switching = FALSE;
- 07395 }
-
- 07397 /*==========================================================================*
- 07398 * unhold *
- 07399 *==========================================================================*/
- 07400 PUBLIC void unhold()
- 07401 {
- 07402 /* Flush any held-up interrupts. k_reenter must be 0. held_head must not
- 07403 * be NIL_PROC. Interrupts must be disabled. They will be enabled but will
- 07404 * be disabled when this returns.
- 07405 */
- 07406
- 07407 register struct proc *rp; /* current head of held queue */
- 07408
- 07409 if (switching) return;
- 07410 rp = held_head;
- 07411 do {
- 07412 if ( (held_head = rp->p_nextheld) == NIL_PROC) held_tail = NIL_PROC;
- 07413 rp->p_int_held = FALSE;
- 07414 unlock(); /* reduce latency; held queue may change! */
- 07415 interrupt(proc_number(rp));
- 07416 lock(); /* protect the held queue again */
- 07417 }
- 07418 while ( (rp = held_head) != NIL_PROC);
- 07419 }
- .Op 91 src/kernel/exception.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/exception.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 07500 /* This file contains a simple exception handler. Exceptions in user
- 07501 * processes are converted to signals. Exceptions in the kernel, MM and
- 07502 * FS cause a panic.
- 07503 */
- 07504
- 07505 #include "kernel.h"
- 07506 #include <signal.h>
- 07507 #include "proc.h"
- 07508
- 07509 /*==========================================================================*
- 07510 * exception *
- 07511 *==========================================================================*/
- 07512 PUBLIC void exception(vec_nr)
- 07513 unsigned vec_nr;
- 07514 {
- 07515 /* An exception or unexpected interrupt has occurred. */
- 07516
- 07517 struct ex_s {
- 07518 char *msg;
- 07519 int signum;
- 07520 int minprocessor;
- 07521 };
- 07522 static struct ex_s ex_data[] = {
- 07523 "Divide error", SIGFPE, 86,
- 07524 "Debug exception", SIGTRAP, 86,
- 07525 "Nonmaskable interrupt", SIGBUS, 86,
- 07526 "Breakpoint", SIGEMT, 86,
- 07527 "Overflow", SIGFPE, 86,
- 07528 "Bounds check", SIGFPE, 186,
- 07529 "Invalid opcode", SIGILL, 186,
- 07530 "Coprocessor not available", SIGFPE, 186,
- 07531 "Double fault", SIGBUS, 286,
- 07532 "Copressor segment overrun", SIGSEGV, 286,
- 07533 "Invalid TSS", SIGSEGV, 286,
- 07534 "Segment not present", SIGSEGV, 286,
- 07535 "Stack exception", SIGSEGV, 286, /* STACK_FAULT already used */
- 07536 "General protection", SIGSEGV, 286,
- 07537 "Page fault", SIGSEGV, 386, /* not close */
- 07538 NIL_PTR, SIGILL, 0, /* probably software trap */
- 07539 "Coprocessor error", SIGFPE, 386,
- 07540 };
- 07541 register struct ex_s *ep;
- 07542 struct proc *saved_proc;
- 07543
- 07544 saved_proc= proc_ptr; /* Save proc_ptr, because it may be changed by debug
- 07545 * statements.
- 07546 */
- 07547
- 07548 ep = &ex_data[vec_nr];
- 07549
- 07550 if (vec_nr == 2) { /* spurious NMI on some machines */
- 07551 printf("got spurious NMIn");
- 07552 return;
- 07553 }
- 07554
- .Ep 92 src/kernel/exception.c
- 07555 if (k_reenter == 0 && isuserp(saved_proc)) {
- 07556 unlock(); /* this is protected like sys_call() */
- 07557 cause_sig(proc_number(saved_proc), ep->signum);
- 07558 return;
- 07559 }
- 07560
- 07561 /* This is not supposed to happen. */
- 07562 if (ep->msg == NIL_PTR || processor < ep->minprocessor)
- 07563 printf("nIntel-reserved exception %dn", vec_nr);
- 07564 else
- 07565 printf("n%sn", ep->msg);
- 07566 printf("process number %d, pc = 0x%04x:0x%08xn",
- 07567 proc_number(saved_proc),
- 07568 (unsigned) saved_proc->p_reg.cs,
- 07569 (unsigned) saved_proc->p_reg.pc);
- 07570 panic("exception in system code", NO_NUM);
- 07571 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/i8259.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 07600 /* This file contains routines for initializing the 8259 interrupt controller:
- 07601 * get_irq_handler: address of handler for a given interrupt
- 07602 * put_irq_handler: register an interrupt handler
- 07603 * intr_init: initialize the interrupt controller(s)
- 07604 */
- 07605
- 07606 #include "kernel.h"
- 07607
- 07608 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
- 07609 #define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
- 07610 #define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
- 07611 #define ICW4_AT 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
- 07612 #define ICW4_PC 0x09 /* not SFNM, buffered, normal EOI, 8086 */
- 07613
- 07614 FORWARD _PROTOTYPE( int spurious_irq, (int irq) );
- 07615
- 07616 #define set_vec(nr, addr) ((void)0) /* kluge for protected mode */
- 07617
- 07618 /*==========================================================================*
- 07619 * intr_init *
- 07620 *==========================================================================*/
- 07621 PUBLIC void intr_init(mine)
- 07622 int mine;
- 07623 {
- 07624 /* Initialize the 8259s, finishing with all interrupts disabled. This is
- 07625 * only done in protected mode, in real mode we don't touch the 8259s, but
- 07626 * use the BIOS locations instead. The flag "mine" is set if the 8259s are
- 07627 * to be programmed for Minix, or to be reset to what the BIOS expects.
- 07628 */
- 07629
- 07630 int i;
- 07631
- 07632 lock();
- 07633 /* The AT and newer PS/2 have two interrupt controllers, one master,
- 07634 * one slaved at IRQ 2. (We don't have to deal with the PC that
- .Op 93 src/kernel/i8259.c
- 07635 * has just one controller, because it must run in real mode.)
- 07636 */
- 07637 out_byte(INT_CTL, ps_mca ? ICW1_PS : ICW1_AT);
- 07638 out_byte(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
- 07639 /* ICW2 for master */
- 07640 out_byte(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
- 07641 out_byte(INT_CTLMASK, ICW4_AT);
- 07642 out_byte(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
- 07643 out_byte(INT2_CTL, ps_mca ? ICW1_PS : ICW1_AT);
- 07644 out_byte(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
- 07645 /* ICW2 for slave */
- 07646 out_byte(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
- 07647 out_byte(INT2_CTLMASK, ICW4_AT);
- 07648 out_byte(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
- 07649
- 07650 /* Initialize the table of interrupt handlers. */
- 07651 for (i = 0; i < NR_IRQ_VECTORS; i++) irq_table[i] = spurious_irq;
- 07652 }
-
- 07654 /*=========================================================================*
- 07655 * spurious_irq *
- 07656 *=========================================================================*/
- 07657 PRIVATE int spurious_irq(irq)
- 07658 int irq;
- 07659 {
- 07660 /* Default interrupt handler. It complains a lot. */
- 07661
- 07662 if (irq < 0 || irq >= NR_IRQ_VECTORS)
- 07663 panic("invalid call to spurious_irq", irq);
- 07664
- 07665 printf("spurious irq %dn", irq);
- 07666
- 07667 return 1; /* Reenable interrupt */
- 07668 }
-
- 07670 /*=========================================================================*
- 07671 * put_irq_handler *
- 07672 *=========================================================================*/
- 07673 PUBLIC void put_irq_handler(irq, handler)
- 07674 int irq;
- 07675 irq_handler_t handler;
- 07676 {
- 07677 /* Register an interrupt handler. */
- 07678
- 07679 if (irq < 0 || irq >= NR_IRQ_VECTORS)
- 07680 panic("invalid call to put_irq_handler", irq);
- 07681
- 07682 if (irq_table[irq] == handler)
- 07683 return; /* extra initialization */
- 07684
- 07685 if (irq_table[irq] != spurious_irq)
- 07686 panic("attempt to register second irq handler for irq", irq);
- 07687
- 07688 disable_irq(irq);
- 07689 if (!protected_mode) set_vec(BIOS_VECTOR(irq), irq_vec[irq]);
- 07690 irq_table[irq]= handler;
- 07691 irq_use |= 1 << irq;
- 07692 }
-
- .Ep 94 src/kernel/protect.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/protect.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 07700 /* This file contains code for initialization of protected mode, to initialize
- 07701 * code and data segment descriptors, and to initialize global descriptors
- 07702 * for local descriptors in the process table.
- 07703 */
- 07704
- 07705 #include "kernel.h"
- 07706 #include "proc.h"
- 07707 #include "protect.h"
- 07708
- 07709 #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
- 07710 #define TSS_TYPE (AVL_286_TSS | DESC_386_BIT)
- 07711
- 07712 struct desctableptr_s {
- 07713 char limit[sizeof(u16_t)];
- 07714 char base[sizeof(u32_t)]; /* really u24_t + pad for 286 */
- 07715 };
- 07716
- 07717 struct gatedesc_s {
- 07718 u16_t offset_low;
- 07719 u16_t selector;
- 07720 u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
- 07721 u8_t p_dpl_type; /* |P|DL|0|TYPE| */
- 07722 u16_t offset_high;
- 07723 };
- 07724
- 07725 struct tss_s {
- 07726 reg_t backlink;
- 07727 reg_t sp0; /* stack pointer to use during interrupt */
- 07728 reg_t ss0; /* " segment " " " " */
- 07729 reg_t sp1;
- 07730 reg_t ss1;
- 07731 reg_t sp2;
- 07732 reg_t ss2;
- 07733 reg_t cr3;
- 07734 reg_t ip;
- 07735 reg_t flags;
- 07736 reg_t ax;
- 07737 reg_t cx;
- 07738 reg_t dx;
- 07739 reg_t bx;
- 07740 reg_t sp;
- 07741 reg_t bp;
- 07742 reg_t si;
- 07743 reg_t di;
- 07744 reg_t es;
- 07745 reg_t cs;
- 07746 reg_t ss;
- 07747 reg_t ds;
- 07748 reg_t fs;
- 07749 reg_t gs;
- 07750 reg_t ldt;
- 07751 u16_t trap;
- 07752 u16_t iobase;
- 07753 };
- 07754
- .Op 95 src/kernel/protect.c
- 07755 PUBLIC struct segdesc_s gdt[GDT_SIZE];
- 07756 PRIVATE struct gatedesc_s idt[IDT_SIZE]; /* zero-init so none present */
- 07757 PUBLIC struct tss_s tss; /* zero init */
- 07758
- 07759 FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, phys_bytes base,
- 07760 unsigned dpl_type) );
- 07761 FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
- 07762 phys_bytes size) );
- 07763
- 07764 /*=========================================================================*
- 07765 * prot_init *
- 07766 *=========================================================================*/
- 07767 PUBLIC void prot_init()
- 07768 {
- 07769 /* Set up tables for protected mode.
- 07770 * All GDT slots are allocated at compile time.
- 07771 */
- 07772
- 07773 phys_bytes code_bytes;
- 07774 phys_bytes data_bytes;
- 07775 struct gate_table_s *gtp;
- 07776 struct desctableptr_s *dtp;
- 07777 unsigned ldt_selector;
- 07778 register struct proc *rp;
- 07779
- 07780 static struct gate_table_s {
- 07781 _PROTOTYPE( void (*gate), (void) );
- 07782 unsigned char vec_nr;
- 07783 unsigned char privilege;
- 07784 }
- 07785 gate_table[] = {
- 07786 divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE,
- 07787 single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE,
- 07788 nmi, NMI_VECTOR, INTR_PRIVILEGE,
- 07789 breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE,
- 07790 overflow, OVERFLOW_VECTOR, USER_PRIVILEGE,
- 07791 bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE,
- 07792 inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE,
- 07793 copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE,
- 07794 double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE,
- 07795 copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE,
- 07796 inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE,
- 07797 segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE,
- 07798 stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE,
- 07799 general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE,
- 07800 page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE,
- 07801 copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE,
- 07802 { hwint00, VECTOR( 0), INTR_PRIVILEGE },
- 07803 { hwint01, VECTOR( 1), INTR_PRIVILEGE },
- 07804 { hwint02, VECTOR( 2), INTR_PRIVILEGE },
- 07805 { hwint03, VECTOR( 3), INTR_PRIVILEGE },
- 07806 { hwint04, VECTOR( 4), INTR_PRIVILEGE },
- 07807 { hwint05, VECTOR( 5), INTR_PRIVILEGE },
- 07808 { hwint06, VECTOR( 6), INTR_PRIVILEGE },
- 07809 { hwint07, VECTOR( 7), INTR_PRIVILEGE },
- 07810 { hwint08, VECTOR( 8), INTR_PRIVILEGE },
- 07811 { hwint09, VECTOR( 9), INTR_PRIVILEGE },
- 07812 { hwint10, VECTOR(10), INTR_PRIVILEGE },
- 07813 { hwint11, VECTOR(11), INTR_PRIVILEGE },
- 07814 { hwint12, VECTOR(12), INTR_PRIVILEGE },
- .Ep 96 src/kernel/protect.c
- 07815 { hwint13, VECTOR(13), INTR_PRIVILEGE },
- 07816 { hwint14, VECTOR(14), INTR_PRIVILEGE },
- 07817 { hwint15, VECTOR(15), INTR_PRIVILEGE },
- 07818 };
- 07819
- 07820 /* This is called early and can't use tables set up by main(). */
- 07821 data_bytes = (phys_bytes) sizes[1] << CLICK_SHIFT;
- 07822 if (sizes[0] == 0)
- 07823 code_bytes = data_bytes; /* common I&D */
- 07824 else
- 07825 code_bytes = (phys_bytes) sizes[0] << CLICK_SHIFT;