#include "../kernel-8086.def"
+/*
+ * How to deal with EMM remains an interesting discussion point
+ */
+
.arch i8086,jumps
.code16
.att_syntax prefix
.globl switchout
.globl dofork
+
+ /* udata transfer functions */
+
+ /* Move the udata for for udata.u_ptab into the process save slot.
+ Preserve bx. We keep udata's in a buffer but that buffer can
+ live outside the kernel so udata_ds may not be in kernel_ds
+
+ All our callers don't mind us trashing es/di/cx
+
+ NOTE: Breaks if we exceeed 128 processes */
+stash_udata:
+ /* TODO */
+ movw P_TAB__P_PAGE(%bx),%al
+ addb %al,%al
+ xchg %al,%ah /* will be 00xx, want xx00 */
+ pushw %es
+ movw %ax,di
+ movw udata_ds,%ax
+ movw %ax,%es
+ movw udata,%si
+ movw $256,%cx
+ cld
+ rep movsw
+ popw %es
+ ret
+
+ /* Restore the udata for process %bx, preserve %bx */
+restore_udata:
+ movb P_TAB__P_PAGE(%bx),%al
+ addb %al,%al
+ xchg %al,%ah
+ pushw %ds
+ movw %ax,%si
+ movw udata_ds,%ax
+ movw udata,%di
+ movw %ax,%ds
+ movw $256,%cx
+ cld
+ rep movsw
+ popw %ds
+ ret
+
+ /* udata.u_ptab is the parent, %bx the child, preserve %bx */
+fork_copy:
+ /* Copy the data from the current instance into the new one
+ BEWARE: it is possible in the EMM case that the two processes
+ data will be in EMM in the same segment. In fact it's likely to
+ be the case. We need an optimised copier and EMM help for this
+ to do split maps (32K/32K) and blast two lots of 32K */
+ ret
+
+ /* Called to give up processor time. We will pop out of this in
+ potentially some other process, but we might also come back
+ directly */
switchout:
cli
call chksigs
- pushw %ax /* Figure out what we actually need to save */
- pushw %bx
- pushw %cx
- pushw %dx
- pushw %es
+ movb nready,%al
+ cmpb $1,%al
+ bne slow_path
+idling:
+ sti
+ call platform_idle
+ cli
+ movb nready,%al
+ cmpb $0,%al
+ je idling
+
+ /* Ok there is something to run - but is it us ? */
+ cmpb $1,%al
+ jne slow_path
+
+ /* Fast path out */
+ ret
+
+slow_path:
+ xorw %ax,%ax
+ pushw %ax
+ pushw %ei
pushw %di
pushw %bp
movw %sp,udata+U_DATA__U_SP
+
+ call stash_udata
+
call getproc
push %ax
call switchin
jmp trap_monitor
switchin:
- push %bp
+ /* We can trash registers here because we'll restore them
+ for the process we return as */
mov %sp,%bp
cli
- movw 4(%bp),%si
- cmpb $0,P_TAB__P_PAGE_OFFSET(%si)
- /*
+ movw 2(%bp),%bx
+ /* No MMU pointer means we are swapped out */
+ movw P_TAB__P_PAGE_OFFSET+2(%bx),%si
+ /* si is now our MMU pointer or 0 */
+ cmpw $0,%si
jne not_swapped
- TODO */
+ /* TODO */
+ movw P_TAB__P_PAGE_OFFSET+2(%bx),%si
+not_swapped:
+ cmpw udata+U_DATA__U_PTAB,%bx
+ je skip_copyback /* this can happen even with idle optimisation
+ consider two processes ready and us winning */
+ call restore_udata
+ cmpw udata+U_DATA__U_PTAB,%bx
+ jne switchfail
+skip_copyback:
+ movb $P_RUNNING,P_TAB__P_STATUS_OFFSET(%bx)
+ xorw %ax,%ax
+ movw %ax,runticks
+ movw udata+U_DATA__U_SP,%sp
+ popw %bp
+ popw %di
+ popw %ei
+ popw %ax
ret
switchfail:
-/* call outaxhex
+ call outaxhex
mov $badswitchmsg,ax
calloutstring
- jmp _trap_monitor */
-
+ jmp _trap_monitor
dofork:
- /* TODO */
- movw $-1,%ax
+ pushw %bp
+ movw %sp,%bp
+ cli
+ movw 4(%bp),%bx
+
+ movw P_TAB__P_PID_OFFSET(%bx),%ax
+ pushw %ax
+ pushw %bp
+ pushw %di
+ pushw %ei
+ movw %sp,udata+U_DATA__U_SP
+
+ /* These two preserve bx */
+ call stash_udata
+
+ /* Stack twice as C code is entitled to mash the first one */
+ pushw %bx
+ pushw %bx
+ call fork_copy
+ popw %bx
+ popw %bx
+
+ popw %ei
+ popw %di
+ popw %bp
+ popw %ax
+
+ pushw %bx
+ call newproc
+ popw %ax
+
+ xorw %ax,%ax /* As child */
+ movw %ax,runticks
ret
.data
swapstack:
.bss 256
+ .byte "_switchin: FAIL",0
+ .even