CS代考 FFFF0013 $k1, 1

MIPS Assembler
A Little Operating System

Operating Systems

Copyright By PowCoder代写 加微信 powcoder

We would like to execute multiple processes concurrently Code for multiple processes can be placed in .text memory How can we run these processes in parallel?
The Operating System
• Starts processes
• Schedules processes to access the CPU (Scheduler)
• Organises access to hardware for multiple processes • … and does many more things

Process Scheduling
What makes a process?
• Code defining the behaviour (instructions in .text) • State of the system (registers and memory)
Scheduling multiple processes
Use a periodic interrupt (timer) to interrupt running process
Save the state of the process • save all register content
• save instruction pointer
Load the state of a saved process • load all register content
• load saved instruction pointer
Return from interrupt to the restored (loaded) process

Process Scheduling – example
Init/Kernel

MARS OS Example
A MARS OS example
• Not a full OS, a simple process scheduler
• Not taking all issues into account (suspending IRQ, all registers, …)
• Inspiration taken from (similar example for his course)
Uses the periodic IRQ of the MARS tool Digital Lab Sim
• Amongst other things provides an IRQ every 30 instructions • Can be used for a scheduler
Main function acts as init/boot loader of some sort
3 special syscall functions
• 100: register a new process • 101: start scheduler
• 102: get process ID
No proper error handling (hope all goes well and as planned) Setup of processes but no removal/termination implemented

Exception Handling
Control is transferred to an exception handler
• Handling in MIPS is implemented by Coprocessor0 • Exception handling registers of CP0:
Vaddr ($8)
The invalid memory address caused by load, store, or fetch
Status ($12)
The interrupt mask and enable bits
Cause ($13)
The type of exception and any pending bits
The address of the instruction when the exception occurred

Cause Register
For handling we need to know what the exception is Exception code:
Pending Interrupt:
Description
HW Interrupt
address exception load
address exception store
Description

Exception Handler
pcb: .word 0 : 25 # each Process Control Block (PCB) has PC,a0,v0,t0,t1
# we assume we can have room for 5 processes
curpcb: .word 0
.ktext 0x80000180 mfc0 $k0, $13
srl $k0, $k0, 2
andi $k0, $k0, 0x1f
beqz $k0, int_hdlr
beq $k0, 8, sys_hdlr # cause is a syscall (encoded as 8)
li $v0, 10 # if anything else, we terminate (should not happen) syscall
# offset to the current PCB (multiple of 20) # can be used as process_id too
# move cause from coproc0 reg $13 to $k0 # shift right by 2
# cause is encoded in 5 bit
# cause is hardware interrupt (encoded as 0)

Interrupt Handler (1)
int_hdlr: #clock used to switch to next process (we do not check exact interrupt)
#save the current process state in pcb
mfc0 $k1, $14 sw $k1, 0($k0) sw $a0, 4($k0) sw $v0, 8($k0) sw $t0, 12($k0) sw $t1, 16($k0)
# load the offest to current pcb (in multiples of 20) # load start address of the pcb array
# get address of the current active pcb
# get the current program counter
# save program counter so process can resume later # save all other relevant process state in pcb
$k1, curpcb $k0, pcb
$k0, $k0, $k1

Interrupt Handler (2)
…#load the next process state from pcb
lw $k0, curpcb # load current pcb offset
addiu $k0, $k0, 20 # add 20 to get to next pcb
blt $k0, 100, int_skip# go to 0 if we wrap around the pcb array addu $k0, $zero, $zero
lw $k1, pcb + 0($k0) # get the stored PC from the next pcb
bnez $k1, int_restore # if that PC is not 0 we can switch to this process
b int_next # go back and fetch the next pcb, this one was invalid
int_restore:
sw $k0, curpcb # save the offset for the pcb we switch to lw $k1, pcb + 0($k0) # load PC from that pcb
mtc0 $k1, $14 # put PC in EPC
lw lw lw lw
$a0, pcb + 4($k0) # restore all registers (restore process state) $v0, pcb + 8($k0)
$t0, pcb + 12($k0)
$t1, pcb + 16($k0)
# continue execution of the stored process

SYSCALL Handler (1)
beq $v0, 100, sys_100
beq $v0, 101, sys_101 beq $v0, 102, sys_102 li $v0, 10
# syscall 100 (register a process) # syscall 101 (start processes)
# syscall 102 (return process id)
# if another syscall, we terminate (should not happen)
#register a new process with the OS # loop counter for pcb
s100_next:
lw $k1, pcb + 0($k0) # get PC stored in pcb
beqz $k1, s100_alloc # if pcb entry free, use it
addiu $k0,$k0,20 # if not free, try next pcb
bne $k0,100, s100_next # we can have up to 5 pcb (5 times 20byte) li $v0, 10 # if it is no free pcb we terminate
s100_alloc:
sw $a0, pcb + 0($k0) # store PC in pcb (initially, start of process)
mfc0 $k0, $14 addiu $k0, $k0, 4 mtc0 $k0, $14 eret
# move EPC to $k0
# skip one instruction, avoid same syscall again # write it back to EPC
# return to process registering this new process

SYSCALL Handler (2)
sys_101: #start scheduling of OS processes
lw $k1, pcb # load address of first process in pcb
bnez $k1, s101_valid # check if the first one is valid (we need one!)
li $v0, 10
s101_valid:
mtc0 $k1, $14
# if it is no valid pcb we terminate
#we have a valid pcb
# copy start PC of process into EPC # enable clock of Digial Lab Sim
# switch to the process now in EPC
# load current pcb offset
# copy current pcb (process id) to $v0
# move EPC to $k0
# skip one instruction, avoid same syscall again # write it back to EPC
$k0, 0xFFFF0013 $k1, 1
$k1, ($k0)
sys_102: #return process id lw $k0, curpcb
add $v0, $zero, $k0 mfc0 $k0, $14 addiu $k0, $k0, 4 mtc0 $k0, $14

pre_txt: post_txt: newline:
.asciiz “(process id=” .asciiz “): ”
.asciiz “\n”
li $v0, 100 la $a0, p1 syscall
la $a0, p2 syscall
la $a0, p2 syscall
li $v0, 101 syscall
li $v0, 10 syscall
# main, a bit like init/boot loader
# syscall 100 to register a new process with the scheduler # $a0 contains the process start address
# register process1 with scheduler
# register process2 with scheduler
# register process2 again (running this one twice) # syscall 101 starts the scheduler
# system exit, we should never reach here

Two Identical Processes (1)
p1: li $v0, 102 syscall
add $t1, $zero, $v0
li $t0, 0 p1_loop:
# get process id and store in $t1
# $t0 as loop counter, start at 0 # print preamble text
la $a0, pre_txt
add $a0,$zero,$t1 # print process id li $v0, 1
la $a0, post_txt # print closing bracket li $v0, 4
add $a0,$zero,$t0 # print counter
la $a0, newline
addi $t0, $t0, 1
# print a newline
# increment counter # run again

Two Identical Processes (2)
p2: li $v0, 102 # get process id and store in $t1 sys call
add $t1, $zero, $v0
li $t0, 1000 # $t0 as loop counter, start at 1000 p2_loop:
la $a0, pre_txt # print preamble text li $v0, 4
add $a0,$zero,$t1 # print process id
la $a0, post_txt # print closing bracket li $v0, 4
add $a0,$zero,$t0 # print counter
la $a0, newline
addi $t0, $t0, 5
# print a newline
# increment counter (by 5) # run again

(process id=0): 0 (process id=20): 1000 (process id=0): 1 (process id=40): 1000 (process id=20): 1005 (process id=0): 2 (process id=20): 1010 (process id=40): 1005 (process id=0): 3 (process id=40): 1010
(process id=0): 0
(process id=(process id=20): 1000 (process id=(process id=40): 1000 (process id=0): 1
(process id=0): 220): 1005
(process id=20): 101040): 1005 (process id=40): 1010(process id=0): 3 (process id=

A small example OS for MARS
Next: C/ Debugging

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com