0

I am working on minix 3.1.7,

I want to use a macro "SAVE_PROCESS_CTX" defined in "/usr/src/kernel/arch/i386/sconst.h" in my assembly file in "/usr/src/kernel/test.s":

/usr/src/kernel/arch/i386/sconst.h:

#ifndef __SCONST_H__
#define __SCONST_H__

#include "kernel/const.h"

/* 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
    FP_SAVE_AREA_P = P_STACKTOP
    P_LDT_SEL = FP_SAVE_AREA_P + 532
    P_CR3 = P_LDT_SEL+W
    P_CR3_V = P_CR3+4
    P_LDT = P_CR3_V+W
    P_MISC_FLAGS = P_LDT + 50
    Msize = 9   /* size of a message in 32-bit words*/


/*
 * offset to current process pointer right after trap, we assume we always have
 * error code on the stack
 */
#define CURR_PROC_PTR       20

/*
 * tests whether the interrupt was triggered in kernel. If so, jump to the
 * label. Displacement tell the macro ha far is the CS value saved by the trap
 * from the current %esp. The kernel code segment selector has the lower 3 bits
 * zeroed
 */
#define TEST_INT_IN_KERNEL(displ, label)    \
    cmpl    $CS_SELECTOR, displ(%esp)   ;\
    je  label               ;

/*
 * saves the basic interrupt context (no error code) to the process structure
 *
 * displ is the displacement of %esp from the original stack after trap
 * pptr is the process structure pointer
 * tmp is an available temporary register
 */
#define SAVE_TRAP_CTX(displ, pptr, tmp)         \
    movl    (0 + displ)(%esp), tmp          ;\
    movl    tmp, PCREG(pptr)            ;\
    movl    (4 + displ)(%esp), tmp          ;\
    movl    tmp, CSREG(pptr)            ;\
    movl    (8 + displ)(%esp), tmp          ;\
    movl    tmp, PSWREG(pptr)           ;\
    movl    (12 + displ)(%esp), tmp         ;\
    movl    tmp, SPREG(pptr)            ;\
    movl    tmp, STREG(pptr)            ;\
    movl    (16 + displ)(%esp), tmp         ;\
    movl    tmp, SSREG(pptr)            ;

#define SAVE_SEGS(pptr)     \
    mov %ds, %ss:DSREG(pptr)    ;\
    mov %es, %ss:ESREG(pptr)    ;\
    mov %fs, %ss:FSREG(pptr)    ;\
    mov %gs, %ss:GSREG(pptr)    ;

#define RESTORE_SEGS(pptr)      \
    movw    %ss:DSREG(pptr), %ds    ;\
    movw    %ss:ESREG(pptr), %es    ;\
    movw    %ss:FSREG(pptr), %fs    ;\
    movw    %ss:GSREG(pptr), %gs    ;

/*
 * restore kernel segments, %ss is kernnel data segment, %cs is aready set and
 * %fs, %gs are not used
 */
#define RESTORE_KERNEL_SEGS \
    mov %ss, %si    ;\
    mov %si, %ds    ;\
    mov %si, %es    ;\
    movw    $0, %si     ;\
    mov %si, %gs    ;\
    mov %si, %fs    ;

#define SAVE_GP_REGS(pptr)  \
    mov %eax, %ss:AXREG(pptr)       ;\
    mov %ecx, %ss:CXREG(pptr)       ;\
    mov %edx, %ss:DXREG(pptr)       ;\
    mov %ebx, %ss:BXREG(pptr)       ;\
    mov %esi, %ss:SIREG(pptr)       ;\
    mov %edi, %ss:DIREG(pptr)       ;

#define RESTORE_GP_REGS(pptr)   \
    movl    %ss:AXREG(pptr), %eax       ;\
    movl    %ss:CXREG(pptr), %ecx       ;\
    movl    %ss:DXREG(pptr), %edx       ;\
    movl    %ss:BXREG(pptr), %ebx       ;\
    movl    %ss:SIREG(pptr), %esi       ;\
    movl    %ss:DIREG(pptr), %edi       ;

/*
 * save the context of the interrupted process to the structure in the process
 * table. It pushses the %ebp to stack to get a scratch register. After %esi is
 * saved, we can use it to get the saved %ebp from stack and save it to the
 * final location
 *
 * displ is the stack displacement. In case of an exception, there are two extra
 * value on the stack - error code and the exception number
 */
#define SAVE_PROCESS_CTX_NON_LAZY(displ) \
                                \
    cld /* set the direction flag to a known state */   ;\
                                \
    push    %ebp                    ;\
                            ;\
    movl    (CURR_PROC_PTR + 4 + displ)(%esp), %ebp ;\
                            ;\
    /* save the segment registers */        \
    SAVE_SEGS(%ebp)                 ;\
                            \
    SAVE_GP_REGS(%ebp)              ;\
    pop %esi            /* get the orig %ebp and save it */ ;\
    mov %esi, %ss:BPREG(%ebp)           ;\
                            \
    RESTORE_KERNEL_SEGS             ;\
    SAVE_TRAP_CTX(displ, %ebp, %esi)        ;

#define SAVE_PROCESS_CTX(displ)             \
    SAVE_PROCESS_CTX_NON_LAZY(displ)        ;\
    push    %eax                    ;\
    push    %ebx                    ;\
    push    %ecx                    ;\
    push    %edx                    ;\
    push    %ebp                    ;\
    call    _save_fpu               ;\
    pop %ebp                    ;\
    pop %edx                    ;\
    pop %ecx                    ;\
    pop %ebx                    ;\
    pop %eax                    ;

/*
 * clear the IF flag in eflags which are stored somewhere in memory, e.g. on
 * stack. iret or popf will load the new value later
 */
#define CLEAR_IF(where) \
    mov where, %eax                     ;\
    andl    $0xfffffdff, %eax                   ;\
    mov %eax, where                     ;

#endif /* __SCONST_H__ */

in my file "/usr/src/kernel/test.s":

#include "arch/i386/sconst.h"
.sect .text
.align 16
save_context:

    SAVE_PROCESS_CTX(0)

But I recieve error :syntax error at the line where i call macro SAVE_PROCESS_CTX(0)

What is wrong?

here's a file "mpx.S"that already exist in "usr/src/kernel/arch/i386" and uses the same macro "SAVE_PROCESS_CTX"and it compiles with no problem ,but when call the same macro "SAVE_PROCESS_CTX" i can't compile the file ,here's the file :

/*
 * 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(). 
 *
 * Kernel is entered either because of kernel-calls, ipc-calls, interrupts or
 * exceptions. TSS is set so that the kernel stack is loaded. The user cotext is
 * saved to the proc table and the handler of the event is called. Once the
 * handler is done, switch_to_user() function is called to pick a new process,
 * finish what needs to be done for the next process to run, sets its context
 * and switch to userspace.
 *
 * For communication with the boot monitor at startup time some constant 
 * data are compiled into the beginning of the text segment. This facilitates  
 * reading the data at the start of the boot process, since only the first 
 * sector of the file needs to be read. 
 *
 * Some data storage is also allocated at the end of this file. This data  
 * will be at the start of the data segment of the kernel and will be read 
 * and modified by the boot monitor before the kernel starts.
 */

#include "kernel/kernel.h" /* configures the kernel */

/* sections */

#include <machine/vm.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 <machine/interrupt.h>
#include "archconst.h"
#include "kernel/const.h"
#include "kernel/proc.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  _restore_user_context
.globl  _reload_cr3

.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  _alignment_check
.globl  _machine_check
.globl  _simd_exception
.globl  _params_size
.globl  _params_offset
.globl  _mon_ds
.globl  _switch_to_user
.globl  _save_fpu

.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

/* Exported variables. */
.globl  begbss
.globl  begdata

.text
/*===========================================================================*/
/*              MINIX                        */
/*===========================================================================*/
.globl 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_boot_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         */
/*===========================================================================*/

#define PIC_IRQ_HANDLER(irq)    \
    push    $irq                                    ;\
    call    _irq_handle     /* intr_handle(irq_handlers[irq]) */    ;\
    add $4, %esp                                ;

/*===========================================================================*/
/*              hwint00 - 07                     */
/*===========================================================================*/
/* Note this is a macro, it just looks like a subroutine. */

#define hwint_master(irq) \
    TEST_INT_IN_KERNEL(4, 0f)                   ;\
                                    \
    **SAVE_PROCESS_CTX(0)**                     ;\
    push    %ebp                            ;\
    movl    $0, %ebp    /* for stack trace */           ;\
    call    _context_stop                       ;\
    add $4, %esp                        ;\
    PIC_IRQ_HANDLER(irq)                        ;\
    movb    $END_OF_INT, %al                    ;\
    outb    $INT_CTL    /* reenable interrupts in master pic */ ;\
    jmp _switch_to_user                     ;\
                                    \
0:                                  \
    pusha                               ;\
    call    _context_stop_idle                  ;\
    PIC_IRQ_HANDLER(irq)                        ;\
    movb    $END_OF_INT, %al                    ;\
    outb    $INT_CTL    /* reenable interrupts in master pic */ ;\
    CLEAR_IF(10*4(%esp))                        ;\
    popa                                ;\
    iret                                ;

and this is the file "sconst.h" in"usr/src/kernel/arch/i386" which contains the macro definition:

#ifndef __SCONST_H__
#define __SCONST_H__

#include "kernel/const.h"

/* 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
    FP_SAVE_AREA_P = P_STACKTOP
    P_LDT_SEL = FP_SAVE_AREA_P + 532
    P_CR3 = P_LDT_SEL+W
    P_CR3_V = P_CR3+4
    P_LDT = P_CR3_V+W
    P_MISC_FLAGS = P_LDT + 50
    Msize = 9   /* size of a message in 32-bit words*/


/*
 * offset to current process pointer right after trap, we assume we always have
 * error code on the stack
 */
#define CURR_PROC_PTR       20

/*
 * tests whether the interrupt was triggered in kernel. If so, jump to the
 * label. Displacement tell the macro ha far is the CS value saved by the trap
 * from the current %esp. The kernel code segment selector has the lower 3 bits
 * zeroed
 */
#define TEST_INT_IN_KERNEL(displ, label)    \
    cmpl    $CS_SELECTOR, displ(%esp)   ;\
    je  label               ;

/*
 * saves the basic interrupt context (no error code) to the process structure
 *
 * displ is the displacement of %esp from the original stack after trap
 * pptr is the process structure pointer
 * tmp is an available temporary register
 */
#define SAVE_TRAP_CTX(displ, pptr, tmp)         \
    movl    (0 + displ)(%esp), tmp          ;\
    movl    tmp, PCREG(pptr)            ;\
    movl    (4 + displ)(%esp), tmp          ;\
    movl    tmp, CSREG(pptr)            ;\
    movl    (8 + displ)(%esp), tmp          ;\
    movl    tmp, PSWREG(pptr)           ;\
    movl    (12 + displ)(%esp), tmp         ;\
    movl    tmp, SPREG(pptr)            ;\
    movl    tmp, STREG(pptr)            ;\
    movl    (16 + displ)(%esp), tmp         ;\
    movl    tmp, SSREG(pptr)            ;

#define SAVE_SEGS(pptr)     \
    mov %ds, %ss:DSREG(pptr)    ;\
    mov %es, %ss:ESREG(pptr)    ;\
    mov %fs, %ss:FSREG(pptr)    ;\
    mov %gs, %ss:GSREG(pptr)    ;

#define RESTORE_SEGS(pptr)      \
    movw    %ss:DSREG(pptr), %ds    ;\
    movw    %ss:ESREG(pptr), %es    ;\
    movw    %ss:FSREG(pptr), %fs    ;\
    movw    %ss:GSREG(pptr), %gs    ;

/*
 * restore kernel segments, %ss is kernnel data segment, %cs is aready set and
 * %fs, %gs are not used
 */
#define RESTORE_KERNEL_SEGS \
    mov %ss, %si    ;\
    mov %si, %ds    ;\
    mov %si, %es    ;\
    movw    $0, %si     ;\
    mov %si, %gs    ;\
    mov %si, %fs    ;

#define SAVE_GP_REGS(pptr)  \
    mov %eax, %ss:AXREG(pptr)       ;\
    mov %ecx, %ss:CXREG(pptr)       ;\
    mov %edx, %ss:DXREG(pptr)       ;\
    mov %ebx, %ss:BXREG(pptr)       ;\
    mov %esi, %ss:SIREG(pptr)       ;\
    mov %edi, %ss:DIREG(pptr)       ;

#define RESTORE_GP_REGS(pptr)   \
    movl    %ss:AXREG(pptr), %eax       ;\
    movl    %ss:CXREG(pptr), %ecx       ;\
    movl    %ss:DXREG(pptr), %edx       ;\
    movl    %ss:BXREG(pptr), %ebx       ;\
    movl    %ss:SIREG(pptr), %esi       ;\
    movl    %ss:DIREG(pptr), %edi       ;

/*
 * save the context of the interrupted process to the structure in the process
 * table. It pushses the %ebp to stack to get a scratch register. After %esi is
 * saved, we can use it to get the saved %ebp from stack and save it to the
 * final location
 *
 * displ is the stack displacement. In case of an exception, there are two extra
 * value on the stack - error code and the exception number
 */
#define SAVE_PROCESS_CTX_NON_LAZY(displ) \
                                \
    cld /* set the direction flag to a known state */   ;\
                                \
    push    %ebp                    ;\
                            ;\
    movl    (CURR_PROC_PTR + 4 + displ)(%esp), %ebp ;\
                            ;\
    /* save the segment registers */        \
    SAVE_SEGS(%ebp)                 ;\
                            \
    SAVE_GP_REGS(%ebp)              ;\
    pop %esi            /* get the orig %ebp and save it */ ;\
    mov %esi, %ss:BPREG(%ebp)           ;\
                            \
    RESTORE_KERNEL_SEGS             ;\
    SAVE_TRAP_CTX(displ, %ebp, %esi)        ;

**#define SAVE_PROCESS_CTX(displ)               \**
    SAVE_PROCESS_CTX_NON_LAZY(displ)        ;\
    push    %eax                    ;\
    push    %ebx                    ;\
    push    %ecx                    ;\
    push    %edx                    ;\
    push    %ebp                    ;\
    call    _save_fpu               ;\
    pop %ebp                    ;\
    pop %edx                    ;\
    pop %ecx                    ;\
    pop %ebx                    ;\
    pop %eax                    ;
user2963216
  • 391
  • 2
  • 4
  • 11
  • 1
    Make sure you are running this through the C preprocessor. Some build tools (such as `gcc`) require extension `.S` (capital). – Jester Apr 28 '15 at 11:14
  • i changed the file extension from test.s to test.S ,also changed in Makefile ,then compile now the gnu can't compile the file and give syntax error for each and every line . – user2963216 Apr 28 '15 at 19:54
  • I only have linux, not minix, but here it works fine. BTW, edit the information from your answer into the question then delete it. You shouldn't use answers to supply more information. – Jester Apr 28 '15 at 20:11

0 Answers0