271 lines
6.5 KiB
ArmAsm
271 lines
6.5 KiB
ArmAsm
/*
|
|
* Copyright (c) 2020 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
|
|
* OS-Lab-2020 (i.e., ChCore) is licensed under the Mulan PSL v1.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
* You may obtain a copy of Mulan PSL v1 at:
|
|
* http://license.coscl.org.cn/MulanPSL
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
|
* PURPOSE.
|
|
* See the Mulan PSL v1 for more details.
|
|
*/
|
|
|
|
#include <common/asm.h>
|
|
#include <common/registers.h>
|
|
#include "exception.h"
|
|
#include "esr.h"
|
|
|
|
.extern syscall_table
|
|
.extern hook_syscall
|
|
.extern lock_kernel
|
|
.extern unlock_kernel
|
|
|
|
.macro exception_entry label
|
|
/* Each entry should be 0x80 aligned */
|
|
.align 7
|
|
b \label
|
|
.endm
|
|
|
|
.macro handle_entry el, type
|
|
exception_enter
|
|
mov x0, #\type
|
|
mrs x1, esr_el1
|
|
mrs x2, elr_el1
|
|
bl handle_entry_c
|
|
exception_return
|
|
.endm
|
|
|
|
/* See more details about the bias in registers.h */
|
|
.macro exception_enter
|
|
sub sp, sp, #ARCH_EXEC_CONT_SIZE
|
|
stp x0, x1, [sp, #16 * 0]
|
|
stp x2, x3, [sp, #16 * 1]
|
|
stp x4, x5, [sp, #16 * 2]
|
|
stp x6, x7, [sp, #16 * 3]
|
|
stp x8, x9, [sp, #16 * 4]
|
|
stp x10, x11, [sp, #16 * 5]
|
|
stp x12, x13, [sp, #16 * 6]
|
|
stp x14, x15, [sp, #16 * 7]
|
|
stp x16, x17, [sp, #16 * 8]
|
|
stp x18, x19, [sp, #16 * 9]
|
|
stp x20, x21, [sp, #16 * 10]
|
|
stp x22, x23, [sp, #16 * 11]
|
|
stp x24, x25, [sp, #16 * 12]
|
|
stp x26, x27, [sp, #16 * 13]
|
|
stp x28, x29, [sp, #16 * 14]
|
|
mrs x10, sp_el0
|
|
mrs x11, elr_el1
|
|
mrs x12, spsr_el1
|
|
stp x30, x10, [sp, #16 * 15]
|
|
stp x11, x12, [sp, #16 * 16]
|
|
.endm
|
|
|
|
.macro exception_exit
|
|
ldp x11, x12, [sp, #16 * 16]
|
|
ldp x30, x10, [sp, #16 * 15]
|
|
msr sp_el0, x10
|
|
msr elr_el1, x11
|
|
msr spsr_el1, x12
|
|
ldp x0, x1, [sp, #16 * 0]
|
|
ldp x2, x3, [sp, #16 * 1]
|
|
ldp x4, x5, [sp, #16 * 2]
|
|
ldp x6, x7, [sp, #16 * 3]
|
|
ldp x8, x9, [sp, #16 * 4]
|
|
ldp x10, x11, [sp, #16 * 5]
|
|
ldp x12, x13, [sp, #16 * 6]
|
|
ldp x14, x15, [sp, #16 * 7]
|
|
ldp x16, x17, [sp, #16 * 8]
|
|
ldp x18, x19, [sp, #16 * 9]
|
|
ldp x20, x21, [sp, #16 * 10]
|
|
ldp x22, x23, [sp, #16 * 11]
|
|
ldp x24, x25, [sp, #16 * 12]
|
|
ldp x26, x27, [sp, #16 * 13]
|
|
ldp x28, x29, [sp, #16 * 14]
|
|
add sp, sp, #ARCH_EXEC_CONT_SIZE
|
|
eret
|
|
.endm
|
|
|
|
|
|
/**
|
|
* Lab4
|
|
* unlock the big kernel lock before returning to the user mode
|
|
*/
|
|
.macro exception_return
|
|
|
|
bl unlock_kernel
|
|
|
|
exception_exit
|
|
.endm
|
|
|
|
|
|
/*
|
|
* Vecotr table offsets from vector table base address from ARMv8 Manual
|
|
* Address | Exception Type | Description
|
|
* ============================================================================
|
|
* VBAR_Eln+0x000 | Synchronous | SPSel=0
|
|
* +0x080 | IRQ/vIRQ | Current EL
|
|
* +0x100 | FIQ/vFIQ | with Stack Pointer
|
|
* +0x180 | SError/vSError | shared with EL0
|
|
* ============================================================================
|
|
* VBAR_Eln+0x200 | Synchronous | SPSel=1
|
|
* +0x280 | IRQ/vIRQ | Current EL
|
|
* +0x300 | FIQ/vFIQ | with dedicated
|
|
* +0x380 | SError/vSError | Stack Pointer
|
|
* ============================================================================
|
|
* VBAR_Eln+0x400 | Synchronous |
|
|
* +0x480 | IRQ/vIRQ | Lower EL
|
|
* +0x500 | FIQ/vFIQ | using AArch64
|
|
* +0x580 | SError/vSError |
|
|
* ============================================================================
|
|
* VBAR_Eln+0x600 | Synchronous |
|
|
* +0x680 | IRQ/vIRQ | Lower EL
|
|
* +0x700 | FIQ/vFIQ | using AArch32
|
|
* +0x780 | SError/vSError |
|
|
* ============================================================================
|
|
*/
|
|
|
|
/*
|
|
* Lab3: Your code here
|
|
* Use exception_entry to fill the exception vector table to redirect
|
|
* every entry to cooresponeding entry.
|
|
* NOTE: el1t means SP_EL0 is used as stack before exception and el1h
|
|
* means SP_EL1 is used
|
|
*/
|
|
.align 11
|
|
EXPORT(el1_vector)
|
|
|
|
// ELx SP_EL0
|
|
exception_entry sync_el1t
|
|
exception_entry irq_el1t
|
|
exception_entry fiq_el1t
|
|
exception_entry error_el1t
|
|
|
|
// ELx SP_ELx
|
|
exception_entry sync_el1h
|
|
exception_entry irq_el1h
|
|
exception_entry fiq_el1h
|
|
exception_entry error_el1h
|
|
|
|
// EL0 AArch64
|
|
exception_entry sync_el0_64
|
|
exception_entry irq_el0_64
|
|
exception_entry fiq_el0_64
|
|
exception_entry error_el0_64
|
|
|
|
// EL0 AArch32
|
|
exception_entry sync_el0_32
|
|
exception_entry irq_el0_32
|
|
exception_entry fiq_el0_32
|
|
exception_entry error_el0_32
|
|
|
|
sync_el1t:
|
|
handle_entry 1, SYNC_EL1t
|
|
|
|
irq_el1t:
|
|
handle_entry 1, IRQ_EL1t
|
|
|
|
fiq_el1t:
|
|
handle_entry 1, FIQ_EL1t
|
|
|
|
error_el1t:
|
|
handle_entry 1, ERROR_EL1t
|
|
|
|
sync_el1h:
|
|
handle_entry 1, SYNC_EL1h
|
|
|
|
fiq_el1h:
|
|
handle_entry 1, FIQ_EL1h
|
|
|
|
error_el1h:
|
|
handle_entry 1, ERROR_EL1h
|
|
|
|
sync_el0_64:
|
|
/* Since we cannot touch x0-x7, we need some extra work here */
|
|
exception_enter
|
|
mrs x25, esr_el1
|
|
lsr x24, x25, #ESR_EL1_EC_SHIFT
|
|
cmp x24, #ESR_EL1_EC_SVC_64
|
|
b.eq el0_syscall
|
|
/* Not supported exception */
|
|
mov x0, SYNC_EL0_64
|
|
mrs x1, esr_el1
|
|
mrs x2, elr_el1
|
|
bl handle_entry_c
|
|
exception_return
|
|
|
|
el0_syscall:
|
|
/* Lab4
|
|
* Acquire the big kernel lock for syscall
|
|
*/
|
|
// 保存现场
|
|
sub sp, sp, #16 * 8
|
|
stp x0, x1, [sp, #16 * 0]
|
|
stp x2, x3, [sp, #16 * 1]
|
|
stp x4, x5, [sp, #16 * 2]
|
|
stp x6, x7, [sp, #16 * 3]
|
|
stp x8, x9, [sp, #16 * 4]
|
|
stp x10, x11, [sp, #16 * 5]
|
|
stp x12, x13, [sp, #16 * 6]
|
|
stp x14, x15, [sp, #16 * 7]
|
|
|
|
bl lock_kernel
|
|
|
|
ldp x0, x1, [sp, #16 * 0]
|
|
ldp x2, x3, [sp, #16 * 1]
|
|
ldp x4, x5, [sp, #16 * 2]
|
|
ldp x6, x7, [sp, #16 * 3]
|
|
ldp x8, x9, [sp, #16 * 4]
|
|
ldp x10, x11, [sp, #16 * 5]
|
|
ldp x12, x13, [sp, #16 * 6]
|
|
ldp x14, x15, [sp, #16 * 7]
|
|
add sp, sp, #16 * 8
|
|
|
|
// 系统调用号左移 2 位作为系统调用表偏移
|
|
adr x27, syscall_table // syscall table in x27
|
|
uxtw x16, w8 // syscall number in x16
|
|
ldr x16, [x27, x16, lsl #3] // find the syscall entry
|
|
blr x16
|
|
|
|
/* Ret from syscall */
|
|
// bl disable_irq
|
|
str x0, [sp] /* set the return value of the syscall */
|
|
exception_return
|
|
|
|
irq_el1h:
|
|
exception_enter
|
|
mov x0, IRQ_EL1h
|
|
bl handle_irq
|
|
/* should nerver reach here */
|
|
b .
|
|
|
|
irq_el0_64:
|
|
exception_enter
|
|
mov x0, IRQ_EL0_64
|
|
bl handle_irq
|
|
/* should nerver reach here */
|
|
b .
|
|
|
|
fiq_el0_64:
|
|
handle_entry 0, FIQ_EL0_64
|
|
|
|
error_el0_64:
|
|
handle_entry 0, ERROR_EL0_64
|
|
|
|
sync_el0_32:
|
|
handle_entry 0, SYNC_EL0_32
|
|
|
|
irq_el0_32:
|
|
handle_entry 0, IRQ_EL0_32
|
|
|
|
fiq_el0_32:
|
|
handle_entry 0, FIQ_EL0_32
|
|
|
|
error_el0_32:
|
|
handle_entry 0, ERROR_EL0_32
|
|
|
|
/* void eret_to_thread(u64 sp) */
|
|
BEGIN_FUNC(eret_to_thread)
|
|
mov sp, x0
|
|
exception_return
|
|
END_FUNC(eret_to_thread)
|