|
Listing 13:
test386(){
...
/* transfer to user mode to test system call */
printf("touser "); getchar();
touser (LSEL(LUCODE_SEL,SEL_UPL), LSEL(LUDATA_SEL, SEL_UPL), &usercode);
...
# [excerpted from srt.s]
/* touser (cs,ds,func) */
.globl _touser
_touser:
pushal
movl %esp,_myspback
movl 32+4(%esp),%eax
movl 32+8(%esp),%edx
movl 32+12(%esp),%ecx
# build outer stack frame
pushl %edx # user ss
pushl %esp # user esp
pushl %eax # cs
pushl %ecx # ip
movw %dx,%ds
movw %dx,%es
lret # goto user!
/* code to execute in user mode */
.globl _usercode
#define LCALL(x,y) .byte 0x9a ; .long y; .word x
_usercode:
LCALL(0x7,0x0) /* would be lcall $0x7,0x0 except for assembler bug */
IDTVEC(syscall)
pushal
movw $0x10,%ax
movw %ax,%ds
movw %ax,%es
call _syscall
movl _myspback,%esp /* non-local goto touser() exit */
popal
ret
/* back to i386.c */
...
/* System call processing */
syscall() {
printf("syscall\n");
}
Normally, at the end of the system call assembly stub we would return to the user ring program, but since we have concluded testing the user ring transition, we instead return to the touserp() function caller via a nonlocal goto. We have carefully preserved the stack frame further up the stack, so we can test other parts of the kernel mechanism in the test386() function.
|