162 lines
3.0 KiB
ArmAsm
162 lines
3.0 KiB
ArmAsm
/*
|
|
* \brief Transition between kernel/userland
|
|
* \author Sebastian Sumpf
|
|
* \author Mark Vels
|
|
* \date 2015-06-22
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2015-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
.set CPU_IP, 0
|
|
.set CPU_EXCEPTION, 8
|
|
.set CPU_X1, 2*8
|
|
.set CPU_SP, 3*8
|
|
.set CPU_SPTBR, 33*8
|
|
|
|
.p2align 12
|
|
.global _mt_begin
|
|
_mt_begin:
|
|
|
|
# 0x100 user mode
|
|
j _mt_kernel_entry_pic
|
|
.space 0x3c
|
|
# 0x140 supervisor
|
|
1: j 1b
|
|
.space 0x3c
|
|
# 0x180 hypervisor
|
|
1: j 1b
|
|
.space 0x3c
|
|
# 0x1c0 machine
|
|
1: j 1b
|
|
.space 0x38
|
|
# 0x1fc non-maksable interrupt
|
|
1: j 1b
|
|
|
|
/* space for a client context-pointer per CPU */
|
|
.p2align 3
|
|
.global _mt_client_context_ptr
|
|
_mt_client_context_ptr:
|
|
.space 8
|
|
|
|
/* space for a copy of the kernel context */
|
|
.global _mt_master_context_begin
|
|
_mt_master_context_begin:
|
|
|
|
/* space must be at least as large as 'Context' */
|
|
.space 35*8
|
|
|
|
.global _mt_master_context_end
|
|
_mt_master_context_end:
|
|
|
|
.global _mt_kernel_entry_pic
|
|
_mt_kernel_entry_pic:
|
|
|
|
# master context
|
|
csrrw x31, sscratch, x31
|
|
addi x31, x31, 8
|
|
|
|
# save x30 in master
|
|
sd x30, CPU_X1 + 8 * 28(x31)
|
|
|
|
# load kernel page table
|
|
ld x30, CPU_SPTBR(x31)
|
|
csrw sptbr, x30
|
|
|
|
#
|
|
# FIXME
|
|
# A TLB flush. Might be necessary to remove this in the near future again
|
|
# because on real hardware we currently get problems without.
|
|
#
|
|
sfence.vm x0
|
|
|
|
# save x29 - x31 in user context
|
|
mv x29, x31
|
|
addi x29, x29, -8
|
|
ld x29, (x29)
|
|
|
|
.irp reg,29,30
|
|
ld x30, CPU_X1 + 8 * (\reg - 1)(x31)
|
|
sd x30, CPU_X1 + 8 * (\reg - 1)(x29)
|
|
.endr
|
|
|
|
csrr x30, sscratch /* x31 */
|
|
sd x30, CPU_X1 + 8 * 30(x29)
|
|
|
|
# save x1 - x28
|
|
.irp reg,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
|
|
sd x\reg, CPU_X1 + 8 * (\reg - 1)(x29)
|
|
.endr
|
|
|
|
# trap reason
|
|
csrr x30, scause
|
|
sd x30, CPU_EXCEPTION(x29)
|
|
|
|
# ip
|
|
csrr x30, sepc
|
|
sd x30, CPU_IP(x29)
|
|
|
|
# load kernel stack and ip
|
|
ld sp, CPU_SP(x31)
|
|
ld x30, CPU_IP(x31)
|
|
|
|
# restore scratch
|
|
addi x31, x31, -8
|
|
csrw sscratch, x31
|
|
|
|
jalr x30
|
|
|
|
|
|
.global _mt_user_entry_pic
|
|
_mt_user_entry_pic:
|
|
|
|
# client context pointer
|
|
csrr x30, sscratch
|
|
ld x30, (x30)
|
|
|
|
# set return IP
|
|
ld x31, CPU_IP(x30)
|
|
csrw sepc, x31
|
|
|
|
# restore x1-x28
|
|
.irp reg,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
|
|
ld x\reg, CPU_X1 + 8 * (\reg - 1)(x30)
|
|
.endr
|
|
|
|
# save x29, x30, x31 to master context
|
|
csrr x29, sscratch
|
|
addi x29, x29, 8 # master context
|
|
|
|
.irp reg,29,30,31
|
|
ld x31, CPU_X1 + 8 * (\reg - 1)(x30)
|
|
sd x31, CPU_X1 + 8 * (\reg - 1)(x29)
|
|
.endr
|
|
|
|
# switch page table
|
|
ld x31, CPU_SPTBR(x30)
|
|
|
|
csrw sptbr, x31
|
|
|
|
#
|
|
# FIXME
|
|
# A TLB flush. Might be necessary to remove this in the near future again
|
|
# because on real hardware we currently get problems without.
|
|
#
|
|
|
|
sfence.vm x0
|
|
|
|
# restore x29 - x31 from master context
|
|
.irp reg,31,30,29
|
|
ld x\reg, CPU_X1 + 8 * (\reg - 1)(x29)
|
|
.endr
|
|
|
|
sret
|
|
|
|
# end of the mode transition code
|
|
.global _mt_end
|
|
_mt_end:
|