- .s files removed and replaced by .S as the .S is a standard extension for assembly that needs preprocessing
system.o
CPPFLAGS=-Iinclude
-CFLAGS=$(CPPFLAGS) -Wall
+CFLAGS=$(CPPFLAGS) -Wall $(CPROFILE)
build: $(HEAD) $(ARCHAR)
$(ARCHAR): $(OBJS)
- aal cr $@ *.o
+ aal cr $@ $(OBJS)
depend:
- mkdep "$(CC) -E $(CPPFLAGS)" *.c *.s > .depend
+ mkdep "$(CC) -E $(CPPFLAGS)" *.c *.S > .depend
clean:
- rm -f *.a *.o *~
+ rm -f *.a *.o *~ *.tmp *.s
# How to build it
$(ARCHAR)(exception.o): exception.c
$(ARCHAR)(clock.o): clock.c
$(CC) $(CFLAGS) -c $<
-$(ARCHAR)(klib386.o): klib386.s
- $(CC) $(CFLAGS) -c $<
+klib386.o: klib386.S
+ $(CC) $(CFLAGS) -E -D__ASSEMBLY__ -o $@.tmp $<
+ gas2ack $@.tmp $@.s
+ $(CC) $(CFLAGS) -c -o $@ $@.s
-.s.o:
- $(CC) $(CFLAGS) -c -o $@ $<
+mpx386.o: mpx386.S
+ $(CC) $(CFLAGS) -E -D__ASSEMBLY__ -o $@.tmp $<
+ gas2ack $@.tmp $@.s
+ $(CC) $(CFLAGS) -c -o $@ $@.s
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
--- /dev/null
+/* sections */
+
+.text; .data; .data; .bss
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include <ibm/interrupt.h>
+#include <archconst.h>
+#include "../../const.h"
+#include "sconst.h"
+
+/*
+ * This file contains a number of assembly code utility routines needed by the
+ * kernel. They are:
+ */
+
+.globl monitor /* exit Minix and return to the monitor */
+.globl int86 /* let the monitor make an 8086 interrupt call */
+.globl exit /* dummy for library routines */
+.globl _exit /* dummy for library routines */
+.globl __exit /* dummy for library routines */
+.globl __main /* dummy for GCC */
+.globl phys_insw /* transfer data from (disk controller) port to memory */
+.globl phys_insb /* likewise byte by byte */
+.globl phys_outsw /* transfer data from memory to (disk controller) port */
+.globl phys_outsb /* likewise byte by byte */
+.globl intr_unmask /* enable an irq at the 8259 controller */
+.globl intr_mask /* disable an irq */
+.globl phys_copy /* copy data from anywhere to anywhere in memory */
+.globl phys_copy_fault /* phys_copy pagefault */
+.globl phys_memset /* write pattern anywhere in memory */
+.globl mem_rdw /* copy one word from [segment:offset] */
+.globl reset /* reset the system */
+.globl idle_task /* task executed when there is no work */
+.globl level0 /* call a function at level 0 */
+.globl read_cpu_flags /* read the cpu flags */
+.globl read_cr0 /* read cr0 */
+.globl getcr3val
+.globl write_cr0 /* write a value in cr0 */
+.globl read_cr4
+.globl thecr3
+.globl write_cr4
+
+.globl catch_pagefaults
+.globl read_ds
+.globl read_cs
+.globl read_ss
+
+/*
+ * The routines only guarantee to preserve the registers the C compiler
+ * expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
+ * direction bit in the flags).
+ */
+
+.text
+/*===========================================================================*/
+/* monitor */
+/*===========================================================================*/
+/* PUBLIC void monitor(); */
+/* Return to the monitor. */
+
+monitor:
+ movl mon_sp, %esp /* restore monitor stack pointer */
+ movw $SS_SELECTOR, %dx /* monitor data segment */
+ mov %dx, %ds
+ mov %dx, %es
+ mov %dx, %fs
+ mov %dx, %gs
+ mov %dx, %ss
+ pop %edi
+ pop %esi
+ pop %ebp
+ lretw /* return to the monitor */
+
+
+/*===========================================================================*/
+/* int86 */
+/*===========================================================================*/
+/* PUBLIC void int86(); */
+int86:
+ cmpb $0, mon_return /* is the monitor there? */
+ jne 0f
+ movb $0x01, %ah /* an int 13 error seems appropriate */
+ movb %ah, reg86+0 /* reg86.w.f = 1 (set carry flag) */
+ movb %ah, reg86+13 /* reg86.b.ah = 0x01 = "invalid command" */
+ ret
+0:
+ push %ebp /* save C registers */
+ push %esi
+ push %edi
+ push %ebx
+ pushf /* save flags */
+ cli /* no interruptions */
+
+ inb $INT2_CTLMASK
+ movb %al, %ah
+ inb $INT_CTLMASK
+ push %eax /* save interrupt masks */
+ movl irq_use, %eax /* map of in-use IRQ's */
+ and $~(1<<CLOCK_IRQ), %eax /* keep the clock ticking */
+ outb $INT_CTLMASK /* enable all unused IRQ's and vv. */
+ movb %ah, %al
+ outb $INT2_CTLMASK
+
+ mov $SS_SELECTOR, %eax /* monitor data segment */
+ mov %ax, %ss
+ xchgl mon_sp, %esp /* switch stacks */
+ push reg86+36 /* parameters used in INT call */
+ push reg86+32
+ push reg86+28
+ push reg86+24
+ push reg86+20
+ push reg86+16
+ push reg86+12
+ push reg86+8
+ push reg86+4
+ push reg86+0
+ mov %ax, %ds /* remaining data selectors */
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ push %cs
+ push $return /* kernel return address and selector */
+ ljmpw *20+2*4+10*4+2*4(%esp)
+return:
+ pop reg86+0
+ pop reg86+4
+ pop reg86+8
+ pop reg86+12
+ pop reg86+16
+ pop reg86+20
+ pop reg86+24
+ pop reg86+28
+ pop reg86+32
+ pop reg86+36
+ lgdt gdt+GDT_SELECTOR /* reload global descriptor table */
+ ljmp $CS_SELECTOR, $csinit
+csinit:
+ mov $DS_SELECTOR, %eax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+ xchgl mon_sp, %esp /* unswitch stacks */
+ lidt gdt+IDT_SELECTOR /* reload interrupt descriptor table */
+ andb $~0x02, gdt+TSS_SELECTOR+DESC_ACCESS /* clear TSS busy bit */
+ mov $TSS_SELECTOR, %eax
+ ltr %ax /* set TSS register */
+
+ pop %eax
+ outb $INT_CTLMASK /* restore interrupt masks */
+ movb %ah, %al
+ outb $INT2_CTLMASK
+
+ addl %ecx, lost_ticks /* record lost clock ticks */
+
+ popf /* restore flags */
+ pop %ebx /* restore C registers */
+ pop %edi
+ pop %esi
+ pop %ebp
+ ret
+
+/*===========================================================================*/
+/* exit */
+/*===========================================================================*/
+/*
+ * PUBLIC void exit();
+ * Some library routines use exit, so provide a dummy version.
+ * Actual calls to exit cannot occur in the kernel.
+ * GNU CC likes to call ___main from main() for nonobvious reasons.
+ */
+
+exit:
+_exit:
+__exit:
+ sti
+ jmp __exit
+
+__main:
+ ret
+
+
+/*===========================================================================*/
+/* phys_insw */
+/*===========================================================================*/
+/*
+ * PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
+ * Input an array from an I/O port. Absolute address version of insw().
+ */
+
+phys_insw:
+ push %ebp
+ mov %esp, %ebp
+ cld
+ push %edi
+ push %es
+
+ mov $FLAT_DS_SELECTOR, %ecx
+ mov %cx, %es
+ mov 8(%ebp), %edx /* port to read from */
+ mov 12(%ebp), %edi /* destination addr */
+ mov 16(%ebp), %ecx /* byte count */
+ shr $1, %ecx /* word count */
+ rep insw /* input many words */
+ pop %es
+ pop %edi
+ pop %ebp
+ ret
+
+
+/*===========================================================================*/
+/* phys_insb */
+/*===========================================================================*/
+/*
+ * PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
+ * Input an array from an I/O port. Absolute address version of insb().
+ */
+
+phys_insb:
+ push %ebp
+ mov %esp, %ebp
+ cld
+ push %edi
+ push %es
+
+ mov $FLAT_DS_SELECTOR, %ecx
+ mov %cx, %es
+ mov 8(%ebp), %edx /* port to read from */
+ mov 12(%ebp), %edi /* destination addr */
+ mov 16(%ebp), %ecx /* byte count */
+ rep insb /* input many bytes */
+ pop %es
+ pop %edi
+ pop %ebp
+ ret
+
+
+/*===========================================================================*/
+/* phys_outsw */
+/*===========================================================================*/
+/*
+ * PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
+ * Output an array to an I/O port. Absolute address version of outsw().
+ */
+
+.balign 16
+phys_outsw:
+ push %ebp
+ mov %esp, %ebp
+ cld
+ push %esi
+ push %ds
+
+ mov $FLAT_DS_SELECTOR, %ecx
+ mov %cx, %ds
+ mov 8(%ebp), %edx /* port to write to */
+ mov 12(%ebp), %esi /* source addr */
+ mov 16(%ebp), %ecx /* byte count */
+ shr $1, %ecx /* word count */
+ rep outsw /* output many words */
+ pop %ds
+ pop %esi
+ pop %ebp
+ ret
+
+
+/*===========================================================================*/
+/* phys_outsb */
+/*===========================================================================*/
+/*
+ * PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
+ * Output an array to an I/O port. Absolute address version of outsb().
+ */
+
+.balign 16
+phys_outsb:
+ push %ebp
+ mov %esp, %ebp
+ cld
+ push %esi
+ push %ds
+
+ mov $FLAT_DS_SELECTOR, %ecx
+ mov %cx, %ds
+ mov 8(%ebp), %edx /* port to write to */
+ mov 12(%ebp), %esi /* source addr */
+ mov 16(%ebp), %ecx /* byte count */
+ rep outsb /* output many bytes */
+ pop %ds
+ pop %esi
+ pop %ebp
+ ret
+
+
+/*==========================================================================*/
+/* intr_unmask */
+/*==========================================================================*/
+/*
+ * PUBLIC void intr_unmask(irq_hook_t *hook)
+ * Enable an interrupt request line by clearing an 8259 bit.
+ * Equivalent C code for hook->irq < 8:
+ * if ((irq_actids[hook->irq] &= ~hook->id) == 0)
+ * outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq));
+ */
+
+.balign 16
+intr_unmask:
+ push %ebp
+ mov %esp, %ebp
+ pushf
+ cli
+ mov 8(%ebp), %eax /* hook */
+ mov 8(%eax), %ecx /* irq */
+ mov 12(%eax), %eax /* id bit */
+ not %eax
+ and %eax, irq_actids(,%ecx) /* clear this id bit */
+ jne en_done /* still masked by other handlers? */
+ movb $~1, %ah
+ rolb %cl, %ah /* ah = ~(1 << (irq % 8)) */
+ mov $INT_CTLMASK, %edx /* enable irq < 8 at the master 8259 */
+ cmpb $8, %cl
+ jb 0f
+ mov $INT2_CTLMASK, %edx /* enable irq >= 8 at the slave 8259 */
+0:
+ inb %dx
+ andb %ah, %al
+ outb %dx /* clear bit at the 8259 */
+en_done:
+ popf
+ leave
+ ret
+
+
+/*==========================================================================*/
+/* intr_mask */
+/*==========================================================================*/
+/*
+ * PUBLIC int intr_mask(irq_hook_t *hook)
+ * Disable an interrupt request line by setting an 8259 bit.
+ * Equivalent C code for irq < 8:
+ * irq_actids[hook->irq] |= hook->id;
+ * outb(INT_CTLMASK, inb(INT_CTLMASK) | (1 << irq));
+ * Returns true iff the interrupt was not already disabled.
+ */
+
+.balign 16
+intr_mask:
+ push %ebp
+ mov %esp, %ebp
+ pushf
+ cli
+ mov 8(%ebp), %eax /* hook */
+ mov 8(%eax), %ecx /* irq */
+ mov 12(%eax), %eax /* id bit */
+ or %eax, irq_actids(,%ecx) /* set this id bit */
+ movb $1, %ah
+ rolb %cl, %ah /* ah = (1 << (irq % 8)) */
+ mov $INT_CTLMASK, %edx /* disable irq < 8 at the master 8259 */
+ cmpb $8, %cl
+ jb 0f
+ mov $INT2_CTLMASK, %edx /* disable irq >= 8 at the slave 8259 */
+0:
+ inb %dx
+ testb %ah, %al
+ jne dis_already /* already disabled? */
+ orb %ah, %al
+ outb %dx /* set bit at the 8259 */
+ mov $1, %eax /* disabled by this function */
+ popf
+ leave
+ ret
+dis_already:
+ xor %eax, %eax /* already disabled */
+ popf
+ leave
+ ret
+
+
+/*===========================================================================*/
+/* phys_copy */
+/*===========================================================================*/
+/*
+ * PUBLIC phys_bytes phys_copy(phys_bytes source, phys_bytes destination,
+ * phys_bytes bytecount);
+ * Copy a block of physical memory.
+ */
+
+ PC_ARGS = 4+4+4+4 /* 4 + 4 + 4 */
+/* es edi esi eip src dst len */
+
+.balign 16
+phys_copy:
+ cld
+ push %esi
+ push %edi
+ push %es
+
+ mov $FLAT_DS_SELECTOR, %eax
+ mov %ax, %es
+
+ mov PC_ARGS(%esp), %esi
+ mov PC_ARGS+4(%esp), %edi
+ mov PC_ARGS+4+4(%esp), %eax
+
+ cmp $10, %eax /* avoid align overhead for small counts */
+ jb pc_small
+ mov %esi, %ecx /* align source, hope target is too */
+ neg %ecx
+ and $3, %ecx /* count for alignment */
+ sub %ecx, %eax
+
+ rep movsb %es:(%esi), %es:(%edi)
+ mov %eax, %ecx
+ shr $2, %ecx /* count of dwords */
+
+ rep movsl %es:(%esi), %es:(%edi)
+ and $3, %eax
+pc_small:
+ xchg %eax, %ecx /* remainder */
+
+ rep movsb %es:(%esi), %es:(%edi)
+
+ mov $0, %eax /* 0 means: no fault */
+phys_copy_fault: /* kernel can send us here */
+ pop %es
+ pop %edi
+ pop %esi
+ ret
+
+/*===========================================================================*/
+/* phys_memset */
+/*===========================================================================*/
+/*
+ * PUBLIC void phys_memset(phys_bytes source, unsigned long pattern,
+ * phys_bytes bytecount);
+ * Fill a block of physical memory with pattern.
+ */
+
+.balign 16
+phys_memset:
+ push %ebp
+ mov %esp, %ebp
+ push %esi
+ push %ebx
+ push %ds
+
+ mov 8(%ebp), %esi
+ mov 16(%ebp), %eax
+ mov $FLAT_DS_SELECTOR, %ebx
+ mov %bx, %ds
+ mov 12(%ebp), %ebx
+ shr $2, %eax
+fill_start:
+ mov %ebx, (%esi)
+ add $4, %esi
+ dec %eax
+ jne fill_start
+/* Any remaining bytes? */
+ mov 16(%ebp), %eax
+ and $3, %eax
+remain_fill:
+ cmp $0, %eax
+ je fill_done
+ movb 12(%ebp), %bl
+ movb %bl, (%esi)
+ add $1, %esi
+ inc %ebp
+ dec %eax
+ jmp remain_fill
+fill_done:
+ pop %ds
+ pop %ebx
+ pop %esi
+ pop %ebp
+ ret
+
+
+/*===========================================================================*/
+/* mem_rdw */
+/*===========================================================================*/
+/*
+ * PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
+ * Load and return word at far pointer segment:offset.
+ */
+
+.balign 16
+mem_rdw:
+ mov %ds, %cx
+ mov 4(%esp), %ds
+ mov 4+4(%esp), %eax /* offset */
+ movzwl (%eax), %eax /* word to return */
+ mov %cx, %ds
+ ret
+
+
+/*===========================================================================*/
+/* reset */
+/*===========================================================================*/
+/*
+ * PUBLIC void reset();
+ * Reset the system by loading IDT with offset 0 and interrupting.
+ */
+
+reset:
+ lidt idt_zero
+ int $3 /* anything goes, the 386 will not like it */
+.data
+idt_zero:
+.long 0, 0
+.text
+
+
+/*===========================================================================*/
+/* idle_task */
+/*===========================================================================*/
+idle_task:
+/*
+ * This task is called when the system has nothing else to do. The HLT
+ * instruction puts the processor in a state where it draws minimum power.
+ */
+ push $halt
+ call level0 /* level0(halt) */
+ pop %eax
+ jmp idle_task
+halt:
+ sti
+ hlt
+ cli
+ ret
+
+/*===========================================================================*/
+/* level0 */
+/*===========================================================================*/
+/*
+ * PUBLIC void level0(void (*func)(void))
+ * Call a function at permission level 0. This allows kernel tasks to do
+ * things that are only possible at the most privileged CPU level.
+ */
+level0:
+ mov 4(%esp), %eax
+ cmpb $-1, k_reenter
+ jne 0f
+ int $LEVEL0_VECTOR
+ ret
+
+0:
+ call *%eax
+ ret
+
+
+
+
+/*===========================================================================*/
+/* read_flags */
+/*===========================================================================*/
+/*
+ * PUBLIC unsigned long read_cpu_flags(void);
+ * Read CPU status flags from C.
+ */
+.balign 16
+read_cpu_flags:
+ pushf
+ mov (%esp), %eax
+ popf
+ ret
+
+read_ds:
+ mov $0, %eax
+ mov %ds, %ax
+ ret
+
+read_cs:
+ mov $0, %eax
+ mov %cs, %ax
+ ret
+
+read_ss:
+ mov $0, %eax
+ mov %ss, %ax
+ ret
+
+
+/*===========================================================================*/
+/* read_cr0 */
+/*===========================================================================*/
+/* PUBLIC unsigned long read_cr0(void); */
+read_cr0:
+ push %ebp
+ mov %esp, %ebp
+ mov %cr0, %eax
+ pop %ebp
+ ret
+
+/*===========================================================================*/
+/* write_cr0 */
+/*===========================================================================*/
+/* PUBLIC void write_cr0(unsigned long value); */
+write_cr0:
+ push %ebp
+ mov %esp, %ebp
+ mov 8(%ebp), %eax
+ mov %eax, %cr0
+ jmp 0f /* A jump is required for some flags */
+0:
+ pop %ebp
+ ret
+
+/*===========================================================================*/
+/* read_cr4 */
+/*===========================================================================*/
+/* PUBLIC unsigned long read_cr4(void); */
+read_cr4:
+ push %ebp
+ mov %esp, %ebp
+ mov %cr4, %eax
+ pop %ebp
+ ret
+
+/*===========================================================================*/
+/* write_cr4 */
+/*===========================================================================*/
+/* PUBLIC void write_cr4(unsigned long value); */
+write_cr4:
+ push %ebp
+ mov %esp, %ebp
+ mov 8(%ebp), %eax
+ mov %eax, %cr4
+ jmp 0f
+0:
+ pop %ebp
+ ret
+/*===========================================================================*/
+/* getcr3val */
+/*===========================================================================*/
+/* PUBLIC unsigned long getcr3val(void); */
+getcr3val:
+ mov %cr3, %eax
+ mov %eax, thecr3
+ ret
+
+++ /dev/null
-#
-! sections
-
-.sect .text; .sect .rom; .sect .data; .sect .bss
-
-#include <minix/config.h>
-#include <minix/const.h>
-#include <ibm/interrupt.h>
-#include <archconst.h>
-#include "../../const.h"
-#include "sconst.h"
-
-! This file contains a number of assembly code utility routines needed by the
-! kernel. They are:
-
-.define _monitor ! exit Minix and return to the monitor
-.define _int86 ! let the monitor make an 8086 interrupt call
-!.define _cp_mess ! copies messages from source to destination
-.define _exit ! dummy for library routines
-.define __exit ! dummy for library routines
-.define ___exit ! dummy for library routines
-.define ___main ! dummy for GCC
-.define _phys_insw ! transfer data from (disk controller) port to memory
-.define _phys_insb ! likewise byte by byte
-.define _phys_outsw ! transfer data from memory to (disk controller) port
-.define _phys_outsb ! likewise byte by byte
-.define _intr_unmask ! enable an irq at the 8259 controller
-.define _intr_mask ! disable an irq
-.define _phys_copy ! copy data from anywhere to anywhere in memory
-.define _phys_copy_fault! phys_copy pagefault
-.define _phys_memset ! write pattern anywhere in memory
-.define _mem_rdw ! copy one word from [segment:offset]
-.define _reset ! reset the system
-.define _idle_task ! task executed when there is no work
-.define _level0 ! call a function at level 0
-.define _read_cpu_flags ! read the cpu flags
-.define _read_cr0 ! read cr0
-.define _getcr3val
-.define _write_cr0 ! write a value in cr0
-.define _read_cr4
-.define _thecr3
-.define _write_cr4
-.define _catch_pagefaults
-.define _read_ds
-.define _read_cs
-.define _read_ss
-
-! The routines only guarantee to preserve the registers the C compiler
-! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
-! direction bit in the flags).
-
-.sect .text
-!*===========================================================================*
-!* monitor *
-!*===========================================================================*
-! PUBLIC void monitor();
-! Return to the monitor.
-
-_monitor:
- mov esp, (_mon_sp) ! restore monitor stack pointer
- o16 mov dx, SS_SELECTOR ! monitor data segment
- mov ds, dx
- mov es, dx
- mov fs, dx
- mov gs, dx
- mov ss, dx
- pop edi
- pop esi
- pop ebp
- o16 retf ! return to the monitor
-
-
-!*===========================================================================*
-!* int86 *
-!*===========================================================================*
-! PUBLIC void int86();
-_int86:
- cmpb (_mon_return), 0 ! is the monitor there?
- jnz 0f
- movb ah, 0x01 ! an int 13 error seems appropriate
- movb (_reg86+ 0), ah ! reg86.w.f = 1 (set carry flag)
- movb (_reg86+13), ah ! reg86.b.ah = 0x01 = "invalid command"
- ret
-0: push ebp ! save C registers
- push esi
- push edi
- push ebx
- pushf ! save flags
- cli ! no interruptions
-
- inb INT2_CTLMASK
- movb ah, al
- inb INT_CTLMASK
- push eax ! save interrupt masks
- mov eax, (_irq_use) ! map of in-use IRQ's
- and eax, ~[1<<CLOCK_IRQ] ! keep the clock ticking
- outb INT_CTLMASK ! enable all unused IRQ's and vv.
- movb al, ah
- outb INT2_CTLMASK
-
- mov eax, SS_SELECTOR ! monitor data segment
- mov ss, ax
- xchg esp, (_mon_sp) ! switch stacks
- push (_reg86+36) ! parameters used in INT call
- push (_reg86+32)
- push (_reg86+28)
- push (_reg86+24)
- push (_reg86+20)
- push (_reg86+16)
- push (_reg86+12)
- push (_reg86+ 8)
- push (_reg86+ 4)
- push (_reg86+ 0)
- mov ds, ax ! remaining data selectors
- mov es, ax
- mov fs, ax
- mov gs, ax
- push cs
- push return ! kernel return address and selector
- o16 jmpf 20+2*4+10*4+2*4(esp) ! make the call
-return:
- pop (_reg86+ 0)
- pop (_reg86+ 4)
- pop (_reg86+ 8)
- pop (_reg86+12)
- pop (_reg86+16)
- pop (_reg86+20)
- pop (_reg86+24)
- pop (_reg86+28)
- pop (_reg86+32)
- pop (_reg86+36)
- lgdt (_gdt+GDT_SELECTOR) ! reload global descriptor table
- jmpf CS_SELECTOR:csinit ! restore everything
-csinit: mov eax, DS_SELECTOR
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- xchg esp, (_mon_sp) ! unswitch stacks
- lidt (_gdt+IDT_SELECTOR) ! reload interrupt descriptor table
- andb (_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02 ! clear TSS busy bit
- mov eax, TSS_SELECTOR
- ltr ax ! set TSS register
-
- pop eax
- outb INT_CTLMASK ! restore interrupt masks
- movb al, ah
- outb INT2_CTLMASK
-
- add (_lost_ticks), ecx ! record lost clock ticks
-
- popf ! restore flags
- pop ebx ! restore C registers
- pop edi
- pop esi
- pop ebp
- ret
-
-
-!*===========================================================================*
-!* exit *
-!*===========================================================================*
-! PUBLIC void exit();
-! Some library routines use exit, so provide a dummy version.
-! Actual calls to exit cannot occur in the kernel.
-! GNU CC likes to call ___main from main() for nonobvious reasons.
-
-_exit:
-__exit:
-___exit:
- sti
- jmp ___exit
-
-___main:
- ret
-
-
-!*===========================================================================*
-!* phys_insw *
-!*===========================================================================*
-! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
-! Input an array from an I/O port. Absolute address version of insw().
-
-_phys_insw:
- push ebp
- mov ebp, esp
- cld
- push edi
- push es
-
- mov ecx, FLAT_DS_SELECTOR
- mov es, cx
- mov edx, 8(ebp) ! port to read from
- mov edi, 12(ebp) ! destination addr
- mov ecx, 16(ebp) ! byte count
- shr ecx, 1 ! word count
-rep o16 ins ! input many words
- pop es
- pop edi
- pop ebp
- ret
-
-
-!*===========================================================================*
-!* phys_insb *
-!*===========================================================================*
-! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
-! Input an array from an I/O port. Absolute address version of insb().
-
-_phys_insb:
- push ebp
- mov ebp, esp
- cld
- push edi
- push es
-
- mov ecx, FLAT_DS_SELECTOR
- mov es, cx
- mov edx, 8(ebp) ! port to read from
- mov edi, 12(ebp) ! destination addr
- mov ecx, 16(ebp) ! byte count
-! shr ecx, 1 ! word count
- rep insb ! input many bytes
- pop es
- pop edi
- pop ebp
- ret
-
-
-!*===========================================================================*
-!* phys_outsw *
-!*===========================================================================*
-! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
-! Output an array to an I/O port. Absolute address version of outsw().
-
- .align 16
-_phys_outsw:
- push ebp
- mov ebp, esp
- cld
- push esi
- push ds
-
- mov ecx, FLAT_DS_SELECTOR
- mov ds, cx
- mov edx, 8(ebp) ! port to write to
- mov esi, 12(ebp) ! source addr
- mov ecx, 16(ebp) ! byte count
- shr ecx, 1 ! word count
-rep o16 outs ! output many words
- pop ds
- pop esi
- pop ebp
- ret
-
-
-!*===========================================================================*
-!* phys_outsb *
-!*===========================================================================*
-! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
-! Output an array to an I/O port. Absolute address version of outsb().
-
- .align 16
-_phys_outsb:
- push ebp
- mov ebp, esp
- cld
- push esi
- push ds
-
- mov ecx, FLAT_DS_SELECTOR
- mov ds, cx
- mov edx, 8(ebp) ! port to write to
- mov esi, 12(ebp) ! source addr
- mov ecx, 16(ebp) ! byte count
- rep outsb ! output many bytes
- pop ds
- pop esi
- pop ebp
- ret
-
-
-!*==========================================================================*
-!* intr_unmask *
-!*==========================================================================*/
-! PUBLIC void intr_unmask(irq_hook_t *hook)
-! Enable an interrupt request line by clearing an 8259 bit.
-! Equivalent C code for hook->irq < 8:
-! if ((irq_actids[hook->irq] &= ~hook->id) == 0)
-! outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq));
-
- .align 16
-_intr_unmask:
- push ebp
- mov ebp, esp
- pushf
- cli
- mov eax, 8(ebp) ! hook
- mov ecx, 8(eax) ! irq
- mov eax, 12(eax) ! id bit
- not eax
- and _irq_actids(ecx*4), eax ! clear this id bit
- jnz en_done ! still masked by other handlers?
- movb ah, ~1
- rolb ah, cl ! ah = ~(1 << (irq % 8))
- mov edx, INT_CTLMASK ! enable irq < 8 at the master 8259
- cmpb cl, 8
- jb 0f
- mov edx, INT2_CTLMASK ! enable irq >= 8 at the slave 8259
-0: inb dx
- andb al, ah
- outb dx ! clear bit at the 8259
-en_done:popf
- leave
- ret
-
-
-!*==========================================================================*
-!* intr_mask *
-!*==========================================================================*/
-! PUBLIC int intr_mask(irq_hook_t *hook)
-! Disable an interrupt request line by setting an 8259 bit.
-! Equivalent C code for irq < 8:
-! irq_actids[hook->irq] |= hook->id;
-! outb(INT_CTLMASK, inb(INT_CTLMASK) | (1 << irq));
-! Returns true iff the interrupt was not already disabled.
-
- .align 16
-_intr_mask:
- push ebp
- mov ebp, esp
- pushf
- cli
- mov eax, 8(ebp) ! hook
- mov ecx, 8(eax) ! irq
- mov eax, 12(eax) ! id bit
- or _irq_actids(ecx*4), eax ! set this id bit
- movb ah, 1
- rolb ah, cl ! ah = (1 << (irq % 8))
- mov edx, INT_CTLMASK ! disable irq < 8 at the master 8259
- cmpb cl, 8
- jb 0f
- mov edx, INT2_CTLMASK ! disable irq >= 8 at the slave 8259
-0: inb dx
- testb al, ah
- jnz dis_already ! already disabled?
- orb al, ah
- outb dx ! set bit at the 8259
- mov eax, 1 ! disabled by this function
- popf
- leave
- ret
-dis_already:
- xor eax, eax ! already disabled
- popf
- leave
- ret
-
-
-!*===========================================================================*
-!* phys_copy *
-!*===========================================================================*
-! PUBLIC phys_bytes phys_copy(phys_bytes source, phys_bytes destination,
-! phys_bytes bytecount);
-! Copy a block of physical memory.
-
-PC_ARGS = 4 + 4 + 4 + 4 ! 4 + 4 + 4
-! es edi esi eip src dst len
-
- .align 16
-_phys_copy:
- cld
- push esi
- push edi
- push es
-
- mov eax, FLAT_DS_SELECTOR
- mov es, ax
-
- mov esi, PC_ARGS(esp)
- mov edi, PC_ARGS+4(esp)
- mov eax, PC_ARGS+4+4(esp)
-
- cmp eax, 10 ! avoid align overhead for small counts
- jb pc_small
- mov ecx, esi ! align source, hope target is too
- neg ecx
- and ecx, 3 ! count for alignment
- sub eax, ecx
- rep
- eseg movsb
- mov ecx, eax
- shr ecx, 2 ! count of dwords
- rep
- eseg movs
- and eax, 3
-pc_small:
- xchg ecx, eax ! remainder
- rep
- eseg movsb
-
- mov eax, 0 ! 0 means: no fault
-_phys_copy_fault: ! kernel can send us here
- pop es
- pop edi
- pop esi
- ret
-
-!*===========================================================================*
-!* phys_memset *
-!*===========================================================================*
-! PUBLIC void phys_memset(phys_bytes source, unsigned long pattern,
-! phys_bytes bytecount);
-! Fill a block of physical memory with pattern.
-
- .align 16
-_phys_memset:
- push ebp
- mov ebp, esp
- push esi
- push ebx
- push ds
-
- mov esi, 8(ebp)
- mov eax, 16(ebp)
- mov ebx, FLAT_DS_SELECTOR
- mov ds, bx
- mov ebx, 12(ebp)
- shr eax, 2
-fill_start:
- mov (esi), ebx
- add esi, 4
- dec eax
- jnz fill_start
- ! Any remaining bytes?
- mov eax, 16(ebp)
- and eax, 3
-remain_fill:
- cmp eax, 0
- jz fill_done
- movb bl, 12(ebp)
- movb (esi), bl
- add esi, 1
- inc ebp
- dec eax
- jmp remain_fill
-fill_done:
- pop ds
- pop ebx
- pop esi
- pop ebp
- ret
-
-
-!*===========================================================================*
-!* mem_rdw *
-!*===========================================================================*
-! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
-! Load and return word at far pointer segment:offset.
-
- .align 16
-_mem_rdw:
- mov cx, ds
- mov ds, 4(esp) ! segment
- mov eax, 4+4(esp) ! offset
- movzx eax, (eax) ! word to return
- mov ds, cx
- ret
-
-
-!*===========================================================================*
-!* reset *
-!*===========================================================================*
-! PUBLIC void reset();
-! Reset the system by loading IDT with offset 0 and interrupting.
-
-_reset:
- lidt (idt_zero)
- int 3 ! anything goes, the 386 will not like it
-.sect .data
-idt_zero: .data4 0, 0
-.sect .text
-
-
-!*===========================================================================*
-!* idle_task *
-!*===========================================================================*
-_idle_task:
-! This task is called when the system has nothing else to do. The HLT
-! instruction puts the processor in a state where it draws minimum power.
- push _halt
- call _level0 ! level0(halt)
- pop eax
- jmp _idle_task
-_halt:
- sti
- hlt
- cli
- ret
-
-!*===========================================================================*
-!* level0 *
-!*===========================================================================*
-! PUBLIC void level0(void (*func)(void))
-! Call a function at permission level 0. This allows kernel tasks to do
-! things that are only possible at the most privileged CPU level.
-!
-_level0:
- mov eax, 4(esp)
- cmpb (_k_reenter), -1
- jne direct
- int LEVEL0_VECTOR
- ret
-
-direct:
- call eax
- ret
-
-
-!*===========================================================================*
-!* read_flags *
-!*===========================================================================*
-! PUBLIC unsigned long read_cpu_flags(void);
-! Read CPU status flags from C.
-.align 16
-_read_cpu_flags:
- pushf
- mov eax, (esp)
- popf
- ret
-
-
-!*===========================================================================*
-!* read_cr0 *
-!*===========================================================================*
-! PUBLIC unsigned long read_cr0(void);
-_read_cr0:
- push ebp
- mov ebp, esp
- mov eax, cr0
- pop ebp
- ret
-
-!*===========================================================================*
-!* write_cr0 *
-!*===========================================================================*
-! PUBLIC void write_cr0(unsigned long value);
-_write_cr0:
- push ebp
- mov ebp, esp
- mov eax, 8(ebp)
- mov cr0, eax
- jmp 0f ! A jump is required for some flags
-0:
- pop ebp
- ret
-
-!*===========================================================================*
-!* read_cr4 *
-!*===========================================================================*
-! PUBLIC unsigned long read_cr4(void);
-_read_cr4:
- push ebp
- mov ebp, esp
-.data1 0x0f, 0x20, 0xe0 ! mov eax, cr4
- pop ebp
- ret
-
-!*===========================================================================*
-!* write_cr4 *
-!*===========================================================================*
-! PUBLIC void write_cr4(unsigned long value);
-_write_cr4:
- push ebp
- mov ebp, esp
- mov eax, 8(ebp)
-.data1 0x0f, 0x22, 0xe0 ! mov cr4, eax
- jmp 0f
-0:
- pop ebp
- ret
-
-_read_ds:
- mov eax, 0
- mov ax, ds
- ret
-
-_read_cs:
- mov eax, 0
- mov ax, cs
- ret
-
-_read_ss:
- mov eax, 0
- mov ax, ss
- ret
-
-!*===========================================================================*
-!* getcr3val *
-!*===========================================================================*
-! PUBLIC unsigned long getcr3val(void);
-_getcr3val:
- mov eax, cr3
- mov (_thecr3), eax
- ret
-
--- /dev/null
+/*
+ * This file, mpx386.s, is included by mpx.s when Minix is compiled for
+ * 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs.
+ *
+ * This file is part of the lowest layer of the MINIX kernel. (The other part
+ * is "proc.c".) The lowest layer does process switching and message handling.
+ * Furthermore it contains the assembler startup code for Minix and the 32-bit
+ * interrupt handlers. It cooperates with the code in "start.c" to set up a
+ * good environment for main().
+ *
+ * Every transition to the kernel goes through this file. Transitions to the
+ * kernel may be nested. The initial entry may be with a system call (i.e.,
+ * send or receive a message), an exception or a hardware interrupt; kernel
+ * reentries may only be made by hardware interrupts. The count of reentries
+ * is kept in "k_reenter". It is important for deciding whether to switch to
+ * the kernel stack and for protecting the message passing code in "proc.c".
+ *
+ * For the message passing trap, most of the machine state is saved in the
+ * proc table. (Some of the registers need not be saved.) Then the stack is
+ * switched to "k_stack", and interrupts are reenabled. Finally, the system
+ * call handler (in C) is called. When it returns, interrupts are disabled
+ * again and the code falls into the restart routine, to finish off held-up
+ * interrupts and run the process or task whose pointer is in "proc_ptr".
+ *
+ * Hardware interrupt handlers do the same, except (1) The entire state must
+ * be saved. (2) There are too many handlers to do this inline, so the save
+ * routine is called. A few cycles are saved by pushing the address of the
+ * appropiate restart routine for a return later. (3) A stack switch is
+ * avoided when the stack is already switched. (4) The (master) 8259 interrupt
+ * controller is reenabled centrally in save(). (5) Each interrupt handler
+ * masks its interrupt line using the 8259 before enabling (other unmasked)
+ * interrupts, and unmasks it after servicing the interrupt. This limits the
+ * nest level to the number of lines and protects the handler from itself.
+ *
+ * For communication with the boot monitor at startup time some constant
+ * data are compiled into the beginning of the text segment. This facilitates
+ * reading the data at the start of the boot process, since only the first
+ * sector of the file needs to be read.
+ *
+ * Some data storage is also allocated at the end of this file. This data
+ * will be at the start of the data segment of the kernel and will be read
+ * and modified by the boot monitor before the kernel starts.
+ */
+
+/* sections */
+
+#include <sys/vm_i386.h>
+
+#ifdef __ACK__
+.text
+begtext:
+#ifdef __ACK__
+.rom
+#else
+.data
+#endif
+begrom:
+.data
+begdata:
+.bss
+begbss:
+#endif
+
+
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <ibm/interrupt.h>
+#include <archconst.h>
+#include "../../const.h"
+#include "sconst.h"
+
+/* Selected 386 tss offsets. */
+#define TSS3_S_SP0 4
+
+/*
+ * Exported functions
+ * Note: in assembly language the .define statement applied to a function name
+ * is loosely equivalent to a prototype in C code -- it makes it possible to
+ * link to an entity declared in the assembly code but does not create
+ * the entity.
+ */
+
+.globl restart
+.globl save
+.globl reload_cr3
+.globl write_cr3
+
+.globl errexception
+.globl exception1
+.globl exception
+
+.globl divide_error
+.globl single_step_exception
+.globl nmi
+.globl breakpoint_exception
+.globl overflow
+.globl bounds_check
+.globl inval_opcode
+.globl copr_not_available
+.globl double_fault
+.globl copr_seg_overrun
+.globl inval_tss
+.globl segment_not_present
+.globl stack_exception
+.globl general_protection
+.globl page_fault
+.globl copr_error
+.globl params_size
+.globl params_offset
+.globl mon_ds
+.globl schedcheck
+.globl dirtypde
+
+.globl hwint00 /* handlers for hardware interrupts */
+.globl hwint01
+.globl hwint02
+.globl hwint03
+.globl hwint04
+.globl hwint05
+.globl hwint06
+.globl hwint07
+.globl hwint08
+.globl hwint09
+.globl hwint10
+.globl hwint11
+.globl hwint12
+.globl hwint13
+.globl hwint14
+.globl hwint15
+
+.globl s_call
+.globl p_s_call
+.globl level0_call
+
+/* Exported variables. */
+.globl begbss
+.globl begdata
+
+.text
+/*===========================================================================*/
+/* MINIX */
+/*===========================================================================*/
+.global MINIX
+MINIX:
+/* this is the entry point for the MINIX kernel */
+ jmp over_flags /* skip over the next few bytes */
+.short CLICK_SHIFT /* for the monitor: memory granularity */
+
+flags:
+/* boot monitor flags:
+ * call in 386 mode, make bss, make stack,
+ * load high, don't patch, will return,
+ * uses generic INT, memory vector,
+ * new boot code return
+ */
+.short 0x01FD
+ nop /* extra byte to sync up disassembler */
+over_flags:
+
+/* Set up a C stack frame on the monitor stack. (The monitor sets cs and ds */
+/* right. The ss descriptor still references the monitor data segment.) */
+ movzwl %sp, %esp /* monitor stack is a 16 bit stack */
+ push %ebp
+ mov %esp, %ebp
+ push %esi
+ push %edi
+ cmp $0, 4(%ebp) /* monitor return vector is */
+ je noret /* nonzero if return possible */
+ incl mon_return
+noret:
+ movl %esp, mon_sp /* save stack pointer for later return */
+
+/* Copy the monitor global descriptor table to the address space of kernel and */
+/* switch over to it. Prot_init() can then update it with immediate effect. */
+
+ sgdt gdt+GDT_SELECTOR /* get the monitor gdtr */
+ movl gdt+GDT_SELECTOR+2, %esi /* absolute address of GDT */
+ mov $gdt, %ebx /* address of kernel GDT */
+ mov $8*8, %ecx /* copying eight descriptors */
+copygdt:
+ movb %es:(%esi), %al
+ movb %al, (%ebx)
+ inc %esi
+ inc %ebx
+ loop copygdt
+ movl gdt+DS_SELECTOR+2, %eax /* base of kernel data */
+ and $0x00FFFFFF, %eax /* only 24 bits */
+ add $gdt, %eax /* eax = vir2phys(gdt) */
+ movl %eax, gdt+GDT_SELECTOR+2 /* set base of GDT */
+ lgdt gdt+GDT_SELECTOR /* switch over to kernel GDT */
+
+/* Locate boot parameters, set up kernel segment registers and stack. */
+ mov 8(%ebp), %ebx /* boot parameters offset */
+ mov 12(%ebp), %edx /* boot parameters length */
+ mov 16(%ebp), %eax /* address of a.out headers */
+ movl %eax, aout
+ mov %ds, %ax /* kernel data */
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+ mov $k_stktop, %esp /* set sp to point to the top of kernel stack */
+
+/* Save boot parameters into these global variables for i386 code */
+ movl %edx, params_size
+ movl %ebx, params_offset
+ movl $SS_SELECTOR, mon_ds
+
+/* Call C startup code to set up a proper environment to run main(). */
+ push %edx
+ push %ebx
+ push $SS_SELECTOR
+ push $DS_SELECTOR
+ push $CS_SELECTOR
+ call cstart /* cstart(cs, ds, mds, parmoff, parmlen) */
+ add $5*4, %esp
+
+/* Reload gdtr, idtr and the segment registers to global descriptor table set */
+/* up by prot_init(). */
+
+ lgdt gdt+GDT_SELECTOR
+ lidt gdt+IDT_SELECTOR
+
+ ljmp $CS_SELECTOR, $csinit
+csinit:
+ movw $DS_SELECTOR, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+ movw $TSS_SELECTOR, %ax /* no other TSS is used */
+ ltr %ax
+ push $0 /* set flags to known good state */
+ popf /* esp, clear nested task and int enable */
+ jmp main /* main() */
+
+
+/*===========================================================================*/
+/* interrupt handlers */
+/* interrupt handlers for 386 32-bit protected mode */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* hwint00 - 07 */
+/*===========================================================================*/
+/* Note this is a macro, it just looks like a subroutine. */
+#define hwint_master(irq) \
+ call save /* save interrupted process state */;\
+ push (irq_handlers+4*irq) /* irq_handlers[irq] */;\
+ call intr_handle /* intr_handle(irq_handlers[irq]) */;\
+ pop %ecx ;\
+ cmp $0, (irq_actids+4*irq) /* interrupt still active? */;\
+ jz 0f ;\
+ inb $INT_CTLMASK /* get current mask */ ;\
+ orb $(1<<irq), %al /* mask irq */ ;\
+ outb $INT_CTLMASK /* disable the irq */;\
+0: movb $END_OF_INT, %al ;\
+ outb $INT_CTL /* reenable master 8259 */;\
+ ret /* restart (another) process */
+
+/* Each of these entry points is an expansion of the hwint_master macro */
+.balign 16
+hwint00:
+/* Interrupt routine for irq 0 (the clock). */
+ hwint_master(0)
+
+.balign 16
+hwint01:
+/* Interrupt routine for irq 1 (keyboard) */
+ hwint_master(1)
+
+.balign 16
+hwint02:
+/* Interrupt routine for irq 2 (cascade!) */
+ hwint_master(2)
+
+.balign 16
+hwint03:
+/* Interrupt routine for irq 3 (second serial) */
+ hwint_master(3)
+
+.balign 16
+hwint04:
+/* Interrupt routine for irq 4 (first serial) */
+ hwint_master(4)
+
+.balign 16
+hwint05:
+/* Interrupt routine for irq 5 (XT winchester) */
+ hwint_master(5)
+
+.balign 16
+hwint06:
+/* Interrupt routine for irq 6 (floppy) */
+ hwint_master(6)
+
+.balign 16
+hwint07:
+/* Interrupt routine for irq 7 (printer) */
+ hwint_master(7)
+
+/*===========================================================================*/
+/* hwint08 - 15 */
+/*===========================================================================*/
+/* Note this is a macro, it just looks like a subroutine. */
+#define hwint_slave(irq) \
+ call save /* save interrupted process state */;\
+ push (irq_handlers+4*irq) /* irq_handlers[irq] */;\
+ call intr_handle /* intr_handle(irq_handlers[irq]) */;\
+ pop %ecx ;\
+ cmp $0, (irq_actids+4*irq) /* interrupt still active? */;\
+ jz 0f ;\
+ inb $INT2_CTLMASK ;\
+ orb $(1<<(irq-8)), %al ;\
+ outb $INT2_CTLMASK /* disable the irq */;\
+0: movb $END_OF_INT, %al ;\
+ outb $INT_CTL /* reenable master 8259 */;\
+ outb $INT2_CTL /* reenable slave 8259 */;\
+ ret /* restart (another) process */
+
+/* Each of these entry points is an expansion of the hwint_slave macro */
+.balign 16
+hwint08:
+/* Interrupt routine for irq 8 (realtime clock) */
+ hwint_slave(8)
+
+.balign 16
+hwint09:
+/* Interrupt routine for irq 9 (irq 2 redirected) */
+ hwint_slave(9)
+
+.balign 16
+hwint10:
+/* Interrupt routine for irq 10 */
+ hwint_slave(10)
+
+.balign 16
+hwint11:
+/* Interrupt routine for irq 11 */
+ hwint_slave(11)
+
+.balign 16
+hwint12:
+/* Interrupt routine for irq 12 */
+ hwint_slave(12)
+
+.balign 16
+hwint13:
+/* Interrupt routine for irq 13 (FPU exception) */
+ hwint_slave(13)
+
+.balign 16
+hwint14:
+/* Interrupt routine for irq 14 (AT winchester) */
+ hwint_slave(14)
+
+.balign 16
+hwint15:
+/* Interrupt routine for irq 15 */
+ hwint_slave(15)
+
+/*===========================================================================*/
+/* save */
+/*===========================================================================*/
+/*
+ * Save for protected mode.
+ * This is much simpler than for 8086 mode, because the stack already points
+ * into the process table, or has already been switched to the kernel stack.
+ */
+
+.balign 16
+save:
+ cld /* set direction flag to a known value */
+ pushal /* save "general" registers */
+ pushw %ds /* save ds */
+ pushw %es /* save es */
+ pushw %fs /* save fs */
+ pushw %gs /* save gs */
+ mov %ss, %dx /* ss is kernel data segment */
+ mov %dx, %ds /* load rest of kernel segments */
+ mov %dx, %es /* kernel does not use fs, gs */
+ mov %esp, %eax /* prepare to return */
+ incb k_reenter /* from -1 if not reentering */
+ jne set_restart1 /* stack is already kernel stack */
+ mov $k_stktop, %esp
+ push $restart /* build return address for int handler */
+ xor %ebp, %ebp /* for stacktrace */
+ jmp *RETADR-P_STACKBASE(%eax)
+
+.balign 4
+set_restart1:
+ push $restart1
+ jmp *RETADR-P_STACKBASE(%eax)
+
+/*===========================================================================*/
+/* _s_call */
+/*===========================================================================*/
+.balign 16
+s_call:
+p_s_call:
+ cld /* set direction flag to a known value */
+ sub $4, %esp /* skip RETADR */
+ pusha /* save "general" registers */
+ pushw %ds
+ pushw %es
+ pushw %fs
+ pushw %gs
+
+ mov %ss, %si /* ss is kernel data segment */
+ mov %si, %ds /* load rest of kernel segments */
+ mov %si, %es /* kernel does not use fs, gs */
+ incb k_reenter /* increment kernel entry count */
+ mov %esp, %esi /* assumes P_STACKBASE == 0 */
+ mov $k_stktop, %esp
+ xor %ebp, %ebp /* for stacktrace */
+/* end of inline save */
+/* now set up parameters for sys_call() */
+ push %edx /* event set or flags bit map */
+ push %ebx /* pointer to user message */
+ push %eax /* source / destination */
+ push %ecx /* call number (ipc primitive to use) */
+
+ call sys_call /* sys_call(call_nr, src_dst, m_ptr, bit_map) */
+/* caller is now explicitly in proc_ptr */
+ mov %eax, AXREG(%esi)
+
+/* Fall into code to restart proc/task running. */
+
+/*===========================================================================*/
+/* restart */
+/*===========================================================================*/
+restart:
+
+/* Restart the current process or the next process if it is set. */
+
+ cli
+ call schedcheck
+ movl proc_ptr, %esp /* will assume P_STACKBASE == 0 */
+ lldt P_LDT_SEL(%esp) /* enable process' segment descriptors */
+ cmpl $0, P_CR3(%esp)
+ jz 0f
+ mov P_CR3(%esp), %eax
+ cmpl loadedcr3, %eax
+ jz 0f
+ mov %eax, %cr3
+ mov %eax, loadedcr3
+ mov proc_ptr, %eax
+ mov %eax, ptproc
+ movl $0, dirtypde
+0:
+ lea P_STACKTOP(%esp), %eax /* arrange for next interrupt */
+ movl %eax, tss+TSS3_S_SP0 /* to save state in process table */
+restart1:
+ decb k_reenter
+ popw %gs
+ popw %fs
+ popw %es
+ popw %ds
+ popal
+ add $4, %esp /* skip return adr */
+ iret /* continue process */
+
+/*===========================================================================*/
+/* exception handlers */
+/*===========================================================================*/
+divide_error:
+ push $DIVIDE_VECTOR
+ jmp handle_exception
+
+single_step_exception:
+ push $DEBUG_VECTOR
+ jmp handle_exception
+
+nmi:
+ push $NMI_VECTOR
+ jmp handle_exception
+
+breakpoint_exception:
+ push $BREAKPOINT_VECTOR
+ jmp handle_exception
+
+overflow:
+ push $OVERFLOW_VECTOR
+ jmp handle_exception
+
+bounds_check:
+ push $BOUNDS_VECTOR
+ jmp handle_exception
+
+inval_opcode:
+ push $INVAL_OP_VECTOR
+ jmp handle_exception
+
+copr_not_available:
+ push $COPROC_NOT_VECTOR
+ jmp handle_exception
+
+double_fault:
+ push $DOUBLE_FAULT_VECTOR
+ jmp errexception
+
+copr_seg_overrun:
+ push $COPROC_SEG_VECTOR
+ jmp handle_exception
+
+inval_tss:
+ push $INVAL_TSS_VECTOR
+ jmp errexception
+
+segment_not_present:
+ push $SEG_NOT_VECTOR
+ jmp errexception
+
+stack_exception:
+ push $STACK_FAULT_VECTOR
+ jmp errexception
+
+general_protection:
+ push $PROTECTION_VECTOR
+ jmp errexception
+
+page_fault:
+ push $PAGE_FAULT_VECTOR
+ push %eax
+ mov %cr2, %eax
+ movl %eax, %ss:pagefaultcr2
+ pop %eax
+ jmp errexception
+
+copr_error:
+ push $COPROC_ERR_VECTOR
+ jmp handle_exception
+
+/*===========================================================================*/
+/* handle_exception */
+/*===========================================================================*/
+/* This is called for all exceptions which do not push an error code. */
+
+.balign 16
+handle_exception:
+ movl $0, %ss:trap_errno /* clear trap_errno */
+ pop %ss:ex_number
+ jmp exception1
+
+/*===========================================================================*/
+/* errexception */
+/*===========================================================================*/
+/* This is called for all exceptions which push an error code. */
+
+.balign 16
+errexception:
+ pop %ss:ex_number
+ pop %ss:trap_errno
+exception1:
+/* Common for all exceptions. */
+ movl %esp, %ss:old_eax_ptr /* where will eax be saved */
+ subl $PCREG-AXREG, %ss:old_eax_ptr /* here */
+
+ push %eax /* eax is scratch register */
+
+ mov 0+4(%esp), %eax /* old eip */
+ movl %eax, %ss:old_eip
+ mov %esp, %eax
+ add $4, %eax
+ mov %eax, %ss:old_eip_ptr
+ movzwl 4+4(%esp), %eax /* old cs */
+ movl %eax, %ss:old_cs
+ mov 8+4(%esp), %eax /* old eflags */
+ movl %eax, %ss:old_eflags
+
+ pop %eax
+ call save
+ push pagefaultcr2
+ push old_eax_ptr
+ push old_eip_ptr
+ push old_eflags
+ push old_cs
+ push old_eip
+ push trap_errno
+ push ex_number
+ call exception /* (ex_number, trap_errno, old_eip, */
+ /* old_cs, old_eflags) */
+ add $8*4, %esp
+ ret
+
+/*===========================================================================*/
+/* write_cr3 */
+/*===========================================================================*/
+/* PUBLIC void write_cr3(unsigned long value); */
+write_cr3:
+ push %ebp
+ mov %esp, %ebp
+ mov 8(%ebp), %eax
+ cmpl loadedcr3, %eax
+ jz 0f
+ mov %eax, %cr3
+ mov %eax, loadedcr3
+ movl $0, dirtypde
+0:
+ pop %ebp
+ ret
+
+/*===========================================================================*/
+/* level0_call */
+/*===========================================================================*/
+level0_call:
+/*
+ * which level0 function to call was passed here by putting it in eax, so
+ * we get that from the saved state.
+ */
+ call save
+ movl proc_ptr, %eax
+ movl AXREG(%eax), %eax
+ jmp *%eax
+
+
+/*===========================================================================*/
+/* reload_cr3 */
+/*===========================================================================*/
+/* PUBLIC void reload_cr3(void); */
+reload_cr3:
+ push %ebp
+ mov %esp, %ebp
+ movl $0, dirtypde
+ mov %cr3, %eax
+ mov %eax, %cr3
+ pop %ebp
+ ret
+
+/*===========================================================================*/
+/* data */
+/*===========================================================================*/
+
+#ifdef __ACK__
+.rom /* Before the string table please */
+#else
+.data
+#endif
+.short 0x526F /* this must be the first data entry (magic #) */
+
+.bss
+k_stack:
+.space K_STACK_BYTES /* kernel stack */
+k_stktop:
+/* top of kernel stack */
+.lcomm ex_number, 4
+.lcomm trap_errno, 4
+.lcomm old_eip_ptr, 4
+.lcomm old_eax_ptr, 4
+.lcomm old_eip, 4
+.lcomm old_cs, 4
+.lcomm old_eflags, 4
+.lcomm pagefaultcr2, 4
+.lcomm loadedcr3, 4
+++ /dev/null
-#
-! This file, mpx386.s, is included by mpx.s when Minix is compiled for
-! 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs.
-
-! This file is part of the lowest layer of the MINIX kernel. (The other part
-! is "proc.c".) The lowest layer does process switching and message handling.
-! Furthermore it contains the assembler startup code for Minix and the 32-bit
-! interrupt handlers. It cooperates with the code in "start.c" to set up a
-! good environment for main().
-
-! Every transition to the kernel goes through this file. Transitions to the
-! kernel may be nested. The initial entry may be with a system call (i.e.,
-! send or receive a message), an exception or a hardware interrupt; kernel
-! reentries may only be made by hardware interrupts. The count of reentries
-! is kept in "k_reenter". It is important for deciding whether to switch to
-! the kernel stack and for protecting the message passing code in "proc.c".
-
-! For the message passing trap, most of the machine state is saved in the
-! proc table. (Some of the registers need not be saved.) Then the stack is
-! switched to "k_stack", and interrupts are reenabled. Finally, the system
-! call handler (in C) is called. When it returns, interrupts are disabled
-! again and the code falls into the restart routine, to finish off held-up
-! interrupts and run the process or task whose pointer is in "proc_ptr".
-
-! Hardware interrupt handlers do the same, except (1) The entire state must
-! be saved. (2) There are too many handlers to do this inline, so the save
-! routine is called. A few cycles are saved by pushing the address of the
-! appropiate restart routine for a return later. (3) A stack switch is
-! avoided when the stack is already switched. (4) The (master) 8259 interrupt
-! controller is reenabled centrally in save(). (5) Each interrupt handler
-! masks its interrupt line using the 8259 before enabling (other unmasked)
-! interrupts, and unmasks it after servicing the interrupt. This limits the
-! nest level to the number of lines and protects the handler from itself.
-
-! For communication with the boot monitor at startup time some constant
-! data are compiled into the beginning of the text segment. This facilitates
-! reading the data at the start of the boot process, since only the first
-! sector of the file needs to be read.
-
-! Some data storage is also allocated at the end of this file. This data
-! will be at the start of the data segment of the kernel and will be read
-! and modified by the boot monitor before the kernel starts.
-
-! sections
-
-#include <sys/vm_i386.h>
-
-.sect .text
-begtext:
-.sect .rom
-begrom:
-.sect .data
-begdata:
-.sect .bss
-begbss:
-
-#include <minix/config.h>
-#include <minix/const.h>
-#include <minix/com.h>
-#include <ibm/interrupt.h>
-#include <archconst.h>
-#include "../../const.h"
-#include "sconst.h"
-
-/* Selected 386 tss offsets. */
-#define TSS3_S_SP0 4
-
-! Exported functions
-! Note: in assembly language the .define statement applied to a function name
-! is loosely equivalent to a prototype in C code -- it makes it possible to
-! link to an entity declared in the assembly code but does not create
-! the entity.
-
-.define _restart
-.define save
-.define _reload_cr3
-.define _write_cr3 ! write cr3
-
-.define errexception
-.define exception1
-.define exception
-
-.define _divide_error
-.define _single_step_exception
-.define _nmi
-.define _breakpoint_exception
-.define _overflow
-.define _bounds_check
-.define _inval_opcode
-.define _copr_not_available
-.define _double_fault
-.define _copr_seg_overrun
-.define _inval_tss
-.define _segment_not_present
-.define _stack_exception
-.define _general_protection
-.define _page_fault
-.define _copr_error
-.define _params_size
-.define _params_offset
-.define _mon_ds
-.define _schedcheck
-.define _dirtypde
-
-.define _hwint00 ! handlers for hardware interrupts
-.define _hwint01
-.define _hwint02
-.define _hwint03
-.define _hwint04
-.define _hwint05
-.define _hwint06
-.define _hwint07
-.define _hwint08
-.define _hwint09
-.define _hwint10
-.define _hwint11
-.define _hwint12
-.define _hwint13
-.define _hwint14
-.define _hwint15
-
-.define _s_call
-.define _p_s_call
-.define _level0_call
-
-! Exported variables.
-.define begbss
-.define begdata
-
-.sect .text
-!*===========================================================================*
-!* MINIX *
-!*===========================================================================*
-MINIX: ! this is the entry point for the MINIX kernel
- jmp over_flags ! skip over the next few bytes
- .data2 CLICK_SHIFT ! for the monitor: memory granularity
-flags:
- .data2 0x01FD ! boot monitor flags:
- ! call in 386 mode, make bss, make stack,
- ! load high, don't patch, will return,
- ! uses generic INT, memory vector,
- ! new boot code return
- nop ! extra byte to sync up disassembler
-over_flags:
-
-! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds
-! right. The ss descriptor still references the monitor data segment.)
- movzx esp, sp ! monitor stack is a 16 bit stack
- push ebp
- mov ebp, esp
- push esi
- push edi
- cmp 4(ebp), 0 ! monitor return vector is
- jz noret ! nonzero if return possible
- inc (_mon_return)
-noret: mov (_mon_sp), esp ! save stack pointer for later return
-
-! Copy the monitor global descriptor table to the address space of kernel and
-! switch over to it. Prot_init() can then update it with immediate effect.
-
- sgdt (_gdt+GDT_SELECTOR) ! get the monitor gdtr
- mov esi, (_gdt+GDT_SELECTOR+2) ! absolute address of GDT
- mov ebx, _gdt ! address of kernel GDT
- mov ecx, 8*8 ! copying eight descriptors
-copygdt:
- eseg movb al, (esi)
- movb (ebx), al
- inc esi
- inc ebx
- loop copygdt
- mov eax, (_gdt+DS_SELECTOR+2) ! base of kernel data
- and eax, 0x00FFFFFF ! only 24 bits
- add eax, _gdt ! eax = vir2phys(gdt)
- mov (_gdt+GDT_SELECTOR+2), eax ! set base of GDT
- lgdt (_gdt+GDT_SELECTOR) ! switch over to kernel GDT
-
-! Locate boot parameters, set up kernel segment registers and stack.
- mov ebx, 8(ebp) ! boot parameters offset
- mov edx, 12(ebp) ! boot parameters length
- mov eax, 16(ebp) ! address of a.out headers
- mov (_aout), eax
- mov ax, ds ! kernel data
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- mov esp, k_stktop ! set sp to point to the top of kernel stack
-
-! Save boot parameters into these global variables for i386 code
- mov (_params_size), edx
- mov (_params_offset), ebx
- mov (_mon_ds), SS_SELECTOR
-
-! Call C startup code to set up a proper environment to run main().
- push edx
- push ebx
- push SS_SELECTOR
- push DS_SELECTOR
- push CS_SELECTOR
- call _cstart ! cstart(cs, ds, mds, parmoff, parmlen)
- add esp, 5*4
-
-! Reload gdtr, idtr and the segment registers to global descriptor table set
-! up by prot_init().
-
- lgdt (_gdt+GDT_SELECTOR)
- lidt (_gdt+IDT_SELECTOR)
-
- jmpf CS_SELECTOR:csinit
-csinit:
- o16 mov ax, DS_SELECTOR
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- o16 mov ax, TSS_SELECTOR ! no other TSS is used
- ltr ax
- push 0 ! set flags to known good state
- popf ! esp, clear nested task and int enable
- jmp _main ! main()
-
-
-!*===========================================================================*
-!* interrupt handlers *
-!* interrupt handlers for 386 32-bit protected mode *
-!*===========================================================================*
-
-!*===========================================================================*
-!* hwint00 - 07 *
-!*===========================================================================*
-! Note this is a macro, it just looks like a subroutine.
-#define hwint_master(irq) \
- call save /* save interrupted process state */;\
- push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\
- call _intr_handle /* intr_handle(irq_handlers[irq]) */;\
- pop ecx ;\
- cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
- jz 0f ;\
- inb INT_CTLMASK /* get current mask */ ;\
- orb al, [1<<irq] /* mask irq */ ;\
- outb INT_CTLMASK /* disable the irq */;\
-0: movb al, END_OF_INT ;\
- outb INT_CTL /* reenable master 8259 */;\
- ret /* restart (another) process */
-
-! Each of these entry points is an expansion of the hwint_master macro
- .align 16
-_hwint00: ! Interrupt routine for irq 0 (the clock).
- hwint_master(0)
-
- .align 16
-_hwint01: ! Interrupt routine for irq 1 (keyboard)
- hwint_master(1)
-
- .align 16
-_hwint02: ! Interrupt routine for irq 2 (cascade!)
- hwint_master(2)
-
- .align 16
-_hwint03: ! Interrupt routine for irq 3 (second serial)
- hwint_master(3)
-
- .align 16
-_hwint04: ! Interrupt routine for irq 4 (first serial)
- hwint_master(4)
-
- .align 16
-_hwint05: ! Interrupt routine for irq 5 (XT winchester)
- hwint_master(5)
-
- .align 16
-_hwint06: ! Interrupt routine for irq 6 (floppy)
- hwint_master(6)
-
- .align 16
-_hwint07: ! Interrupt routine for irq 7 (printer)
- hwint_master(7)
-
-!*===========================================================================*
-!* hwint08 - 15 *
-!*===========================================================================*
-! Note this is a macro, it just looks like a subroutine.
-#define hwint_slave(irq) \
- call save /* save interrupted process state */;\
- push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\
- call _intr_handle /* intr_handle(irq_handlers[irq]) */;\
- pop ecx ;\
- cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
- jz 0f ;\
- inb INT2_CTLMASK ;\
- orb al, [1<<[irq-8]] ;\
- outb INT2_CTLMASK /* disable the irq */;\
-0: movb al, END_OF_INT ;\
- outb INT_CTL /* reenable master 8259 */;\
- outb INT2_CTL /* reenable slave 8259 */;\
- ret /* restart (another) process */
-
-! Each of these entry points is an expansion of the hwint_slave macro
- .align 16
-_hwint08: ! Interrupt routine for irq 8 (realtime clock)
- hwint_slave(8)
-
- .align 16
-_hwint09: ! Interrupt routine for irq 9 (irq 2 redirected)
- hwint_slave(9)
-
- .align 16
-_hwint10: ! Interrupt routine for irq 10
- hwint_slave(10)
-
- .align 16
-_hwint11: ! Interrupt routine for irq 11
- hwint_slave(11)
-
- .align 16
-_hwint12: ! Interrupt routine for irq 12
- hwint_slave(12)
-
- .align 16
-_hwint13: ! Interrupt routine for irq 13 (FPU exception)
- hwint_slave(13)
-
- .align 16
-_hwint14: ! Interrupt routine for irq 14 (AT winchester)
- hwint_slave(14)
-
- .align 16
-_hwint15: ! Interrupt routine for irq 15
- hwint_slave(15)
-
-!*===========================================================================*
-!* save *
-!*===========================================================================*
-! Save for protected mode.
-! This is much simpler than for 8086 mode, because the stack already points
-! into the process table, or has already been switched to the kernel stack.
-
- .align 16
-save:
- cld ! set direction flag to a known value
- pushad ! save "general" registers
- o16 push ds ! save ds
- o16 push es ! save es
- o16 push fs ! save fs
- o16 push gs ! save gs
- mov dx, ss ! ss is kernel data segment
- mov ds, dx ! load rest of kernel segments
- mov es, dx ! kernel does not use fs, gs
- mov eax, esp ! prepare to return
- incb (_k_reenter) ! from -1 if not reentering
- jnz set_restart1 ! stack is already kernel stack
- mov esp, k_stktop
- push _restart ! build return address for int handler
- xor ebp, ebp ! for stacktrace
- jmp RETADR-P_STACKBASE(eax)
-
- .align 4
-set_restart1:
- push restart1
- jmp RETADR-P_STACKBASE(eax)
-
-!*===========================================================================*
-!* _s_call *
-!*===========================================================================*
- .align 16
-_s_call:
-_p_s_call:
- cld ! set direction flag to a known value
- sub esp, 4 ! skip RETADR
- pushad ! save "general" registers
- o16 push ds
- o16 push es
- o16 push fs
- o16 push gs
-
- mov si, ss ! ss is kernel data segment
- mov ds, si ! load rest of kernel segments
- mov es, si ! kernel does not use fs, gs
- incb (_k_reenter) ! increment kernel entry count
- mov esi, esp ! assumes P_STACKBASE == 0
- mov esp, k_stktop
- xor ebp, ebp ! for stacktrace
- ! end of inline save
- ! now set up parameters for sys_call()
- push edx ! event set or flags bit map
- push ebx ! pointer to user message
- push eax ! source / destination
- push ecx ! call number (ipc primitive to use)
-
- call _sys_call ! sys_call(call_nr, src_dst, m_ptr, bit_map)
- ! caller is now explicitly in proc_ptr
- mov AXREG(esi), eax
-
-! Fall into code to restart proc/task running.
-
-!*===========================================================================*
-!* restart *
-!*===========================================================================*
-_restart:
-
-! Restart the current process or the next process if it is set.
-
- cli
- call _schedcheck ! ask C function who we're running
- mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
- lldt P_LDT_SEL(esp) ! enable process' segment descriptors
- cmp P_CR3(esp), 0 ! process does not have its own PT
- jz 0f
- mov eax, P_CR3(esp)
- cmp eax, (loadedcr3)
- jz 0f
- mov cr3, eax
- mov (loadedcr3), eax
- mov eax, (_proc_ptr)
- mov (_ptproc), eax
- mov (_dirtypde), 0
-0:
- lea eax, P_STACKTOP(esp) ! arrange for next interrupt
- mov (_tss+TSS3_S_SP0), eax ! to save state in process table
-restart1:
- decb (_k_reenter)
- o16 pop gs
- o16 pop fs
- o16 pop es
- o16 pop ds
- popad
- add esp, 4 ! skip return adr
- iretd ! continue process
-
-!*===========================================================================*
-!* exception handlers *
-!*===========================================================================*
-_divide_error:
- push DIVIDE_VECTOR
- jmp exception
-
-_single_step_exception:
- push DEBUG_VECTOR
- jmp exception
-
-_nmi:
- push NMI_VECTOR
- jmp exception
-
-_breakpoint_exception:
- push BREAKPOINT_VECTOR
- jmp exception
-
-_overflow:
- push OVERFLOW_VECTOR
- jmp exception
-
-_bounds_check:
- push BOUNDS_VECTOR
- jmp exception
-
-_inval_opcode:
- push INVAL_OP_VECTOR
- jmp exception
-
-_copr_not_available:
- push COPROC_NOT_VECTOR
- jmp exception
-
-_double_fault:
- push DOUBLE_FAULT_VECTOR
- jmp errexception
-
-_copr_seg_overrun:
- push COPROC_SEG_VECTOR
- jmp exception
-
-_inval_tss:
- push INVAL_TSS_VECTOR
- jmp errexception
-
-_segment_not_present:
- push SEG_NOT_VECTOR
- jmp errexception
-
-_stack_exception:
- push STACK_FAULT_VECTOR
- jmp errexception
-
-_general_protection:
- push PROTECTION_VECTOR
- jmp errexception
-
-_page_fault:
- push PAGE_FAULT_VECTOR
- push eax
- mov eax, cr2
-sseg mov (pagefaultcr2), eax
- pop eax
- jmp errexception
-
-_copr_error:
- push COPROC_ERR_VECTOR
- jmp exception
-
-!*===========================================================================*
-!* exception *
-!*===========================================================================*
-! This is called for all exceptions which do not push an error code.
-
- .align 16
-exception:
- sseg mov (trap_errno), 0 ! clear trap_errno
- sseg pop (ex_number)
- jmp exception1
-
-!*===========================================================================*
-!* errexception *
-!*===========================================================================*
-! This is called for all exceptions which push an error code.
-
- .align 16
-errexception:
- sseg pop (ex_number)
- sseg pop (trap_errno)
-exception1: ! Common for all exceptions.
- sseg mov (old_eax_ptr), esp ! where will eax be saved?
- sseg sub (old_eax_ptr), PCREG-AXREG ! here
-
- push eax ! eax is scratch register
-
- mov eax, 0+4(esp) ! old eip
- sseg mov (old_eip), eax
- mov eax, esp
- add eax, 4
- sseg mov (old_eip_ptr), eax
- movzx eax, 4+4(esp) ! old cs
- sseg mov (old_cs), eax
- mov eax, 8+4(esp) ! old eflags
- sseg mov (old_eflags), eax
-
- pop eax
- call save
- push (pagefaultcr2)
- push (old_eax_ptr)
- push (old_eip_ptr)
- push (old_eflags)
- push (old_cs)
- push (old_eip)
- push (trap_errno)
- push (ex_number)
- call _exception ! (ex_number, trap_errno, old_eip,
- ! old_cs, old_eflags)
- add esp, 8*4
- ret
-
-
-!*===========================================================================*
-!* write_cr3 *
-!*===========================================================================*
-! PUBLIC void write_cr3(unsigned long value);
-_write_cr3:
- push ebp
- mov ebp, esp
- mov eax, 8(ebp)
- cmp eax, (loadedcr3)
- jz 0f
- mov cr3, eax
- mov (loadedcr3), eax
- mov (_dirtypde), 0
-0:
- pop ebp
- ret
-
-!*===========================================================================*
-!* reload_cr3 *
-!*===========================================================================*
-! PUBLIC void reload_cr3(void);
-_reload_cr3:
- push ebp
- mov ebp, esp
- mov (_dirtypde), 0
- mov eax, cr3
- mov cr3, eax
- pop ebp
- ret
-
-!*===========================================================================*
-!* level0_call *
-!*===========================================================================*
-_level0_call:
-! which level0 function to call was passed here by putting it in eax, so
-! we get that from the saved state.
- call save
- mov eax, (_proc_ptr)
- mov eax, AXREG(eax)
- jmp eax
-
-!*===========================================================================*
-!* data *
-!*===========================================================================*
-
-.sect .rom ! Before the string table please
- .data2 0x526F ! this must be the first data entry (magic #)
-
-.sect .bss
-k_stack:
- .space K_STACK_BYTES ! kernel stack
-k_stktop: ! top of kernel stack
- .comm ex_number, 4
- .comm trap_errno, 4
- .comm old_eip_ptr, 4
- .comm old_eax_ptr, 4
- .comm old_eip, 4
- .comm old_cs, 4
- .comm old_eflags, 4
- .comm pagefaultcr2, 4
- .comm loadedcr3, 4
-
-! Miscellaneous constants used in assembler code.
-W = _WORD_SIZE ! Machine word size.
+/* Miscellaneous constants used in assembler code. */
+ W = _WORD_SIZE /* Machine word size. */
-! Offsets in struct proc. They MUST match proc.h.
-P_STACKBASE = 0
-GSREG = P_STACKBASE
-FSREG = GSREG + 2 ! 386 introduces FS and GS segments
-ESREG = FSREG + 2
-DSREG = ESREG + 2
-DIREG = DSREG + 2
-SIREG = DIREG + W
-BPREG = SIREG + W
-STREG = BPREG + W ! hole for another SP
-BXREG = STREG + W
-DXREG = BXREG + W
-CXREG = DXREG + W
-AXREG = CXREG + W
-RETADR = AXREG + W ! return address for save() call
-PCREG = RETADR + W
-CSREG = PCREG + W
-PSWREG = CSREG + W
-SPREG = PSWREG + W
-SSREG = SPREG + W
-P_STACKTOP = SSREG + W
-P_LDT_SEL = P_STACKTOP
-P_CR3 = P_LDT_SEL + W
-P_LDT = P_CR3 + W
-Msize = 9 ! size of a message in 32-bit words
+/* Offsets in struct proc. They MUST match proc.h. */
+ P_STACKBASE = 0
+ GSREG = P_STACKBASE
+ FSREG = GSREG+2 /* 386 introduces FS and GS segments*/
+ ESREG = FSREG+2
+ DSREG = ESREG+2
+ DIREG = DSREG+2
+ SIREG = DIREG+W
+ BPREG = SIREG+W
+ STREG = BPREG+W /* hole for another SP*/
+ BXREG = STREG+W
+ DXREG = BXREG+W
+ CXREG = DXREG+W
+ AXREG = CXREG+W
+ RETADR = AXREG+W /* return address for save() call*/
+ PCREG = RETADR+W
+ CSREG = PCREG+W
+ PSWREG = CSREG+W
+ SPREG = PSWREG+W
+ SSREG = SPREG+W
+ P_STACKTOP = SSREG+W
+ P_LDT_SEL = P_STACKTOP
+ P_CR3 = P_LDT_SEL+W
+ P_LDT = P_CR3+W
+ Msize = 9 /* size of a message in 32-bit words*/