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.
============================================================================