forked from Github_Repos/cvw
		
	
		
			
				
	
	
		
			132 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| // trap.S
 | |
| // David_Harris@hmc.edu 11 May 2022
 | |
| //
 | |
| // Demonstrates setting up traps and invoking a trap handler.
 | |
| // The trap handler accepts timer interrupts and ecalls.
 | |
| // Saves cause and mtval into the signature
 | |
| // Ecall takes one argument in a0
 | |
| //   0: change privilege mode to user
 | |
| //   1: change privilege mode to supervisor
 | |
| //   3: change privilege mode to machine
 | |
| //   4: exit program with write tohost
 | |
| 
 | |
| .EQU MTIME,    0x200bff8
 | |
| .EQU MTIMECMP, 0x2004000
 | |
| 
 | |
| .global rvtest_entry_point
 | |
| 
 | |
| rvtest_entry_point:
 | |
|     la sp, topofstack   # Initialize stack pointer (not used)
 | |
|     la s6, begin_signature  # s6 points to signature
 | |
| 
 | |
|     # Set up timer
 | |
|     jal set_timecmp
 | |
| 
 | |
|     # Set up interrupts
 | |
|     la t0, trap_handler
 | |
|     csrw mtvec, t0      # Initialize MTVEC to trap_handler
 | |
|     csrw mideleg, zero  # Don't delegate interrupts
 | |
|     csrw medeleg, zero  # Don't delegate exceptions
 | |
|     li t0, 0x080       
 | |
|     csrw mie, t0        # Enable machine timer interrupt
 | |
|     la t0, topoftrapstack 
 | |
|     csrw mscratch, t0   # MSCRATCH holds trap stack pointer
 | |
|     csrsi mstatus, 0x8  # Turn on mstatus.MIE global interrupt enable
 | |
| 
 | |
| main:
 | |
|     # Change to user mode
 | |
|     li a0, 0            # a0 = 0: argument to enter user mode
 | |
|     ecall               # System call to enter user mode
 | |
| 
 | |
|     # Wait for timer interrupts
 | |
|     li t0, 0x1000       # loop counter start value
 | |
| loop: 
 | |
|     addi t0, t0, -1     # decrement counter
 | |
|     bne t0, zero, loop  # and repeat until zero
 | |
| 
 | |
| done:
 | |
|     li a0, 4            # argument to finish program    
 | |
|     ecall               # system call to finish program
 | |
|     j self_loop         # wait forever (not taken)
 | |
| 
 | |
| set_timecmp:            # Set timer compare to 800 ticks later
 | |
|     la t0, MTIME
 | |
|     la t1, MTIMECMP
 | |
|     ld t0, 0(t0)        # Read current timer
 | |
|     addi t0, t0, 0x60   # Increment timer
 | |
|     sd t0, 0(t1)        # Set MTIMECMP = MTIME + 0x800
 | |
|     ret
 | |
| 
 | |
| .align 4                # trap handlers must be aligned to multiple of 4
 | |
| trap_handler:
 | |
|     # Load trap handler stack pointer tp
 | |
|     csrrw tp, mscratch, tp  # swap MSCRATCH and tp
 | |
|     sd t0, 0(tp)        # Save t0 and t1 on the stack
 | |
|     sd t1, -8(tp)
 | |
|     csrr t0, mcause     # Check the cause
 | |
|     csrr t1, mtval      # And the trap value
 | |
|     sd t0, 0(s6)        # Save MCAUSE and MTVAL in the signature
 | |
|     sd t1, 8(s6)            
 | |
|     addi s6, s6, 16     
 | |
|     bgez t0, exception  # if msb is clear, it is an exception
 | |
| 
 | |
| interrupt:              # must be a timer interrupt 
 | |
|     jal set_timecmp     # Increment compare for next timer interrupt
 | |
|     j trap_return       # clean up and return
 | |
| 
 | |
| exception:
 | |
|     csrr t1, mepc   # add 4 to MEPC to determine return Address
 | |
|     addi t1, t1, 4
 | |
|     csrw mepc, t1
 | |
|     li t1, 8            # is it an ecall trap?
 | |
|     andi t0, t0, 0xFC # if CAUSE = 8, 9, or 11
 | |
|     bne t0, t1, trap_return # ignore other exceptions
 | |
| 
 | |
| ecall:
 | |
|     li t0, 4
 | |
|     beq a0, t0, write_tohost    # call 4: terminate program
 | |
|     bltu a0, t0, changeprivilege    # calls 0-3: change privilege level
 | |
|     j trap_return       # ignore other ecalls
 | |
| 
 | |
| changeprivilege:
 | |
|     li t0, 0x00001800   # mask off mstatus.MPP in bits 11-12
 | |
|     csrc mstatus, t0
 | |
|     andi a0, a0, 0x003  # only keep bottom two bits of argument
 | |
|     slli a0, a0, 11     # move into mstatus.MPP position
 | |
|     csrs mstatus, a0    # set mstatus.MPP with desired privilege
 | |
| 
 | |
| trap_return:            # return from trap handler
 | |
|     ld t1, -8(tp)       # restore t1 and t0
 | |
|     ld t0, 0(tp)
 | |
|     csrrw tp, mscratch, tp  # restore tp
 | |
|     mret                # return from trap
 | |
| 
 | |
| write_tohost:
 | |
|     la t1, tohost
 | |
|     li t0, 1            # 1 for success, 3 for failure
 | |
|     sd t0, 0(t1)        # send success code
 | |
| 
 | |
| self_loop:
 | |
|     j self_loop         # wait
 | |
|     
 | |
| .section .tohost 
 | |
| tohost:                 # write to HTIF
 | |
|     .dword 0
 | |
| fromhost:
 | |
|     .dword 0
 | |
| 
 | |
| .EQU XLEN,64
 | |
| begin_signature:
 | |
|     .fill 6*(XLEN/32),4,0xdeadbeef    # 
 | |
| end_signature:
 | |
| 
 | |
| # Initialize stack with room for 512 bytes
 | |
| .bss
 | |
|     .space 512
 | |
| topofstack:
 | |
| # And another stack for the trap handler
 | |
| .bss   
 | |
|     .space 512
 | |
| topoftrapstack:
 | |
| 
 |