460 Lab Assignment #5.1

                      460 LAB Assignment #5.1
                        DUE : TO BE POSTED

1. OBJECTIVES:
   Kernel/User mode images and system calls

2. REQUIREMENTS:

   Implement the following system call functions for the MTX system:
   For each syscall, the return value >= 0 for OK, or -1 for BAD.
***************************************************************************
(0). pid = getpid()  : return the tasks's pid

(1). ps()        : enter Kerenl to print the status info of the tasks
 
(2). chname(char *s) : ask for a string *s, enter Kernel to change the
                       running task's name to *s.
(3). kmode()         : enter Kernel to execute body() function.

(4). kswitch()       : enter Kernel to switch task (call tswitch()).

(5). pid = wait(int *exitValue) : enter Kernel to wait for death of a child,
                                  return its pid (or -1 if no child) and its
                                  exitValue.

(6). exit(int exitValue) : enter Kernel to die with an exitValue.

***************************************************************************

                    3. HELPS and SUGGESTIONS:

(1). How to generate Umode image files:

   The following u.s file may be combined with a .c file to generate an 
   a.out that can be loaded to and executed from ANYWHERE in memory.
   Naturally, you may add more functions to it as needed.

!=========================== u.s file =======================================
.globl begtext, begdata, begbss                      ! needed by linker

.globl _main, _syscall, _getcs                       ! GLOBALS

.text                                                ! these tell as:	
begtext:                                             ! text,data,bss segments
.data                                                ! are all the same.
begdata:
.bss
begbss:
.text               

!--------------------------------------------------------------------------
!     NOTE: CS,DS,SS,ES and SP will be set up properly in Kernel BEFORE CPU 
      gets to here, we simply call main() in C. 
!     Later, we shall pass a (command-line) string to main(), so that
!     you may even write main() as
!                        main(s) char *s; 
!---------------------------------------------------------------------------

start:  
        call _main

! syscall die(0)
        mov  ax,#0
        push 0             1 push exit value 0
        mov  ax,#99        ! assume 99 for kexit()
        push ax
        call _syscall
! journey of no return
 

!  int  syscall(a,b,c,d)    in C:   LISTEN TO THE LECTURE !!!!!
_syscall   
           int 80          
           ret

! int getcs()
_getcs:    mov  ax, cs
           ret 
!================  end of u.s ==============================================

(2). Combine u.s with the following piece of C code to generate a.out (without
     header). dd or cp a.out to /u1 on the MTX disk.

main()
{ 
  char line[128]; int cmd; 
  while(1){
       pid = getpid();         /* YOUR getpid() function */

       printf("==============================================\n");
       printf("I am task %d in U mode running at segment %x\n",
               getpid(), getcs());
       show_menu();           /* display a command MENU */

       printf("Command ? ");
       gets(line);            /* input a command line */ 

       cmd = find_cmd(line);  /* map command to a number */
       switch(cmd){
           /*************** FOR LAB #5.1 *********************************/
           case 0 : do_getpid();    break;
           case 1 : do_ps();        break;
           case 2 : do_chname()     break;
           case 3 : do_kmode()
           case 4 : do_kswitch();   break;
           case 5 : do_wait();      break;
           case 6 : do_exit();      break;

           /************** For LAB #5.2  **********************************/
           case 7 : do_ufork();     break;
           case 8 : do_exec();      break; 
           /***************************************************************/

           default: printf("invalid command\n"); break;
       }
  }
}

===========================================================================
Each of the do_XYZ() function issues a syscall to enter Kernel to do the 
work as required.

Your   syscall(a,b,c,d);    calls the assembly function (in u.s)

       _syscall:
                 int 80
                 ret
which issues an INT 80 to enter Kernel. 
========================= END OF umode image files ===========================


                          MTX Kernel:

The entry point of  INT 80 handler is (in ts.s file)

       _int80h:
        SAVE:    ! save registers in ustack; switch to Kernel space;
                 ! save uSS, uSP in proc

                 call _kcinth      ! call int kcinth() in C; fix return value

        _goImode:! restore SS, SP from saved uSS, uSP;
                 ! pop ustack to restore CPU registers
                 ! IRET        return to where INT 80 was issured in UMODE.
                           
                  

AFTER SAVE:, the task's ustack contains:


 (LOW)  uSP                         | by INT 80  |   by syscall()    | (HIGH) 
 -------------------------------------------------------------------------
       |uDS|uES|di|si|bp|dx|cx|bx|ax|uPC|uCS|flag|ret| a | b | c | d |XXXX
 --------------------------------------------------------------------------
         0   1  2  3  4  5  6  7  8   9   10  11  12  13  14  15  16 

where the numbers are offsets from the saved uSP.
uSS and uSP are saved in proc.uss and proc.usp, respectively.

From the above diagram and YOUR utility functions

     (int) word = get_word(segment, offset);
                  put_word(word, segment, offset);

you should be able to access ANY item that's of interest. For example, in YOUR

                   int  kcinth(){................. }

           HOW TO GET THE SYSCALL parameters a,b,c,d?

           HOW TO let kcinth() return a value to Umode?

           HOW TO change the saved uCS, uDs, uES, uPC, flag ..........?
etc.

If you understand these, you should have no problem in completing PART 1.
===========================================================================

(4). How to install interrupt handlers:
     In order to issue    INT 80  ,    (or any vector number)
     You MUST install a handler for the interrupt vector. 

                     Here is HOW:
     Assume int80h() is the handler function.
     (1).  Vector 80 means memory locations   80*4,        80*4+2  
           should contain                   PC=int80h     CS=0x1000
     (2).  Use    put_word(w, segment, offset);   to set the vector contents.
           

(5). How to create task with a Umode image:

     Modify your MTX's myfork() function as follows:
            
     myfork()
     {
       ushort segment;
       (1).  /* myfork() as YOU DID before */
              but ADD THE FOLLOWLING FEATURES:

       (2). Let segment = (pid + 1)*0x1000; 

            Example: pid=1 ==> 0x2000, pid=2 ==> 0x3000, etc

            Use YOUR 

                loader(char *filename, ushort segment)  

            function (of LAB#2) to load filename (/u1) to segment. 
            Thus, every nnewly forked task has /u1 as its Umode image BUT in 
            its own segment. 

            IF YOUR loader() does not work, try to use kcloader.o in the
            samples/LAB5.1 directory, which has
                   load("filename", segment);
 
       (3). initialize the new task's Umode environment as follows:
            ==========================================================


 (LOW)  uSP                                | by INT 80  |     HIGH
 -------------------------------------------------------------------------
       |uDS|uES| di| si| bp| dx| cx| bx| ax|uPC|uCS|flag|XXXXXXXXXXXXXXXXX
 --------------------------------------------------------------------------
        -12 -11 -10  -9  -8  -7  -6  -5  -4  -3  -2  -1 | 0 

        Refer to the above diagram.        
               segmentRegisters uCS,uDS,uES = segment;
               all other Umode registers, (ax,bx,cx,dx,bp,si,di) are zeros
               uPC =  0; uFlag=0x0200;

                                    NOTE !!! 
               All these are in the ustack, which is at the HIGH end of 
               the segment. READ the notes carefully again. 
               ===========================================================
                         These are in the proc structure:
               uSS = segment;  and
               uSP = ustack top !!!  (LISTEN TO the LECTURE)
               ===========================================================
               With these, the task will have a Umode image to return to.
        }        


(6). How to test YOUR (new) MTX system:

     As before, let mainProc call   myfork();  to create task1. 
     Then tswitch() to task1. 

(7). Now, each task has a Umode image (/u1) loaded in its own segment.  
     Implement a 'u' command which causes the task to go Umode.

(8). Once in Umode, you should print messages to identify the task, e.g
     
           I am task 1 in U mode running at segment=0x2000

     followed by a menu. e.g.

           ************************  MENU  ***************************
           *  ps  chanme  kmode  switch  wait  exit   |  ufork  exec *
           ***********************************************************
    
   Then, prompt for a user command, do a syscall into the Kernel to 
   execute the command.

============================================================================
4. DEMO PROGRAM:
                  samples/LAB5.1/lab5.bin
   download, dd to a disk and re-boot.
============================================================================