2019-05-29 07:18:00 -07:00
/* SPDX-License-Identifier: GPL-2.0-only */
2017-07-10 18:04:30 -07:00
/ *
* Copyright ( C ) 2 0 1 2 R e g e n t s o f t h e U n i v e r s i t y o f C a l i f o r n i a
* Copyright ( C ) 2 0 1 7 S i F i v e
* /
# include < l i n u x / i n i t . h >
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s m . h >
# include < a s m / c s r . h >
# include < a s m / u n i s t d . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / a s m - o f f s e t s . h >
2020-02-27 11:15:03 -08:00
# if ! I S _ E N A B L E D ( C O N F I G _ P R E E M P T I O N )
.set resume_ k e r n e l , r e s t o r e _ a l l
# endif
2017-07-10 18:04:30 -07:00
2020-02-27 11:15:03 -08:00
ENTRY( h a n d l e _ e x c e p t i o n )
2017-07-10 18:04:30 -07:00
/ *
* If c o m i n g f r o m u s e r s p a c e , p r e s e r v e t h e u s e r t h r e a d p o i n t e r a n d l o a d
2019-10-28 13:10:32 +01:00
* the k e r n e l t h r e a d p o i n t e r . I f w e c a m e f r o m t h e k e r n e l , t h e s c r a t c h
* register w i l l c o n t a i n 0 , a n d w e s h o u l d c o n t i n u e o n t h e c u r r e n t T P .
2017-07-10 18:04:30 -07:00
* /
2019-10-28 13:10:32 +01:00
csrrw t p , C S R _ S C R A T C H , t p
2017-07-10 18:04:30 -07:00
bnez t p , _ s a v e _ c o n t e x t
_restore_kernel_tpsp :
2019-10-28 13:10:32 +01:00
csrr t p , C S R _ S C R A T C H
2017-07-10 18:04:30 -07:00
REG_ S s p , T A S K _ T I _ K E R N E L _ S P ( t p )
_save_context :
REG_ S s p , T A S K _ T I _ U S E R _ S P ( t p )
REG_ L s p , T A S K _ T I _ K E R N E L _ S P ( t p )
addi s p , s p , - ( P T _ S I Z E _ O N _ S T A C K )
REG_ S x1 , P T _ R A ( s p )
REG_ S x3 , P T _ G P ( s p )
REG_ S x5 , P T _ T 0 ( s p )
REG_ S x6 , P T _ T 1 ( s p )
REG_ S x7 , P T _ T 2 ( s p )
REG_ S x8 , P T _ S 0 ( s p )
REG_ S x9 , P T _ S 1 ( s p )
REG_ S x10 , P T _ A 0 ( s p )
REG_ S x11 , P T _ A 1 ( s p )
REG_ S x12 , P T _ A 2 ( s p )
REG_ S x13 , P T _ A 3 ( s p )
REG_ S x14 , P T _ A 4 ( s p )
REG_ S x15 , P T _ A 5 ( s p )
REG_ S x16 , P T _ A 6 ( s p )
REG_ S x17 , P T _ A 7 ( s p )
REG_ S x18 , P T _ S 2 ( s p )
REG_ S x19 , P T _ S 3 ( s p )
REG_ S x20 , P T _ S 4 ( s p )
REG_ S x21 , P T _ S 5 ( s p )
REG_ S x22 , P T _ S 6 ( s p )
REG_ S x23 , P T _ S 7 ( s p )
REG_ S x24 , P T _ S 8 ( s p )
REG_ S x25 , P T _ S 9 ( s p )
REG_ S x26 , P T _ S 1 0 ( s p )
REG_ S x27 , P T _ S 1 1 ( s p )
REG_ S x28 , P T _ T 3 ( s p )
REG_ S x29 , P T _ T 4 ( s p )
REG_ S x30 , P T _ T 5 ( s p )
REG_ S x31 , P T _ T 6 ( s p )
/ *
2018-01-04 19:55:55 +01:00
* Disable u s e r - m o d e m e m o r y a c c e s s a s i t s h o u l d o n l y b e s e t i n t h e
* actual u s e r c o p y r o u t i n e s .
*
* Disable t h e F P U t o d e t e c t i l l e g a l u s a g e o f f l o a t i n g p o i n t i n k e r n e l
* space.
2017-07-10 18:04:30 -07:00
* /
2018-01-04 19:55:55 +01:00
li t 0 , S R _ S U M | S R _ F S
2017-07-10 18:04:30 -07:00
REG_ L s0 , T A S K _ T I _ U S E R _ S P ( t p )
2019-10-28 13:10:32 +01:00
csrrc s1 , C S R _ S T A T U S , t 0
csrr s2 , C S R _ E P C
csrr s3 , C S R _ T V A L
csrr s4 , C S R _ C A U S E
csrr s5 , C S R _ S C R A T C H
2017-07-10 18:04:30 -07:00
REG_ S s0 , P T _ S P ( s p )
2019-10-28 13:10:32 +01:00
REG_ S s1 , P T _ S T A T U S ( s p )
REG_ S s2 , P T _ E P C ( s p )
REG_ S s3 , P T _ B A D A D D R ( s p )
REG_ S s4 , P T _ C A U S E ( s p )
2017-07-10 18:04:30 -07:00
REG_ S s5 , P T _ T P ( s p )
/ *
2019-10-28 13:10:32 +01:00
* Set t h e s c r a t c h r e g i s t e r t o 0 , s o t h a t i f a r e c u r s i v e e x c e p t i o n
2017-07-10 18:04:30 -07:00
* occurs, t h e e x c e p t i o n v e c t o r k n o w s i t c a m e f r o m t h e k e r n e l
* /
2019-10-28 13:10:32 +01:00
csrw C S R _ S C R A T C H , x0
2017-07-10 18:04:30 -07:00
/* Load the global pointer */
.option push
.option norelax
la g p , _ _ g l o b a l _ p o i n t e r $
.option pop
la r a , r e t _ f r o m _ e x c e p t i o n
/ *
* MSB o f c a u s e d i f f e r e n t i a t e s b e t w e e n
* interrupts a n d e x c e p t i o n s
* /
bge s4 , z e r o , 1 f
/* Handle interrupts */
2018-03-07 15:57:28 -08:00
move a0 , s p / * p t _ r e g s * /
2020-06-01 14:45:42 +05:30
la a1 , h a n d l e _ a r c h _ i r q
REG_ L a1 , ( a1 )
jr a1
2017-07-10 18:04:30 -07:00
1 :
2019-10-28 13:10:32 +01:00
/ *
* Exceptions r u n w i t h i n t e r r u p t s e n a b l e d o r d i s a b l e d d e p e n d i n g o n t h e
* state o f S R _ P I E i n m / s s t a t u s .
* /
andi t 0 , s1 , S R _ P I E
2019-09-16 16:47:41 +08:00
beqz t 0 , 1 f
2019-10-28 13:10:32 +01:00
csrs C S R _ S T A T U S , S R _ I E
2018-01-29 23:51:45 -08:00
2019-09-16 16:47:41 +08:00
1 :
2017-07-10 18:04:30 -07:00
/* Handle syscalls */
li t 0 , E X C _ S Y S C A L L
beq s4 , t 0 , h a n d l e _ s y s c a l l
/* Handle other exceptions */
slli t 0 , s4 , R I S C V _ L G P T R
la t 1 , e x c p _ v e c t _ t a b l e
la t 2 , e x c p _ v e c t _ t a b l e _ e n d
move a0 , s p / * p t _ r e g s * /
add t 0 , t 1 , t 0
/* Check if exception code lies within bounds */
bgeu t 0 , t 2 , 1 f
REG_ L t 0 , 0 ( t 0 )
jr t 0
1 :
tail d o _ t r a p _ u n k n o w n
handle_syscall :
/* save the initial A0 value (needed in signal handlers) */
REG_ S a0 , P T _ O R I G _ A 0 ( s p )
/ *
* Advance S E P C t o a v o i d e x e c u t i n g t h e o r i g i n a l
* scall i n s t r u c t i o n o n s r e t
* /
addi s2 , s2 , 0 x4
2019-10-28 13:10:32 +01:00
REG_ S s2 , P T _ E P C ( s p )
2017-07-10 18:04:30 -07:00
/* Trace syscalls, but only if requested by the user. */
REG_ L t 0 , T A S K _ T I _ F L A G S ( t p )
2018-10-29 11:48:53 +01:00
andi t 0 , t 0 , _ T I F _ S Y S C A L L _ W O R K
2017-07-10 18:04:30 -07:00
bnez t 0 , h a n d l e _ s y s c a l l _ t r a c e _ e n t e r
check_syscall_nr :
/* Check to make sure we don't jump to a bogus syscall number. */
li t 0 , _ _ N R _ s y s c a l l s
la s0 , s y s _ n i _ s y s c a l l
2019-10-04 17:12:22 -07:00
/ *
* Syscall n u m b e r h e l d i n a7 .
* If s y s c a l l n u m b e r i s a b o v e a l l o w e d v a l u e , r e d i r e c t t o n i _ s y s c a l l .
* /
bge a7 , t 0 , 1 f
/ *
riscv: fix seccomp reject syscall code path
If secure_computing() rejected a system call, we were previously setting
the system call number to -1, to indicate to later code that the syscall
failed. However, if something (e.g. a user notification) was sleeping, and
received a signal, we may set a0 to -ERESTARTSYS and re-try the system call
again.
In this case, seccomp "denies" the syscall (because of the signal), and we
would set a7 to -1, thus losing the value of the system call we want to
restart.
Instead, let's return -1 from do_syscall_trace_enter() to indicate that the
syscall was rejected, so we don't clobber the value in case of -ERESTARTSYS
or whatever.
This commit fixes the user_notification_signal seccomp selftest on riscv to
no longer hang. That test expects the system call to be re-issued after the
signal, and it wasn't due to the above bug. Now that it is, everything
works normally.
Note that in the ptrace (tracer) case, the tracer can set the register
values to whatever they want, so we still need to keep the code that
handles out-of-bounds syscalls. However, we can drop the comment.
We can also drop syscall_set_nr(), since it is no longer used anywhere, and
the code that re-loads the value in a7 because of it.
Reported in: https://lore.kernel.org/bpf/CAEn-LTp=ss0Dfv6J00=rCAy+N78U2AmhqJNjfqjr2FDpPYjxEQ@mail.gmail.com/
Reported-by: David Abdurachmanov <david.abdurachmanov@gmail.com>
Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
2020-02-08 08:18:17 -07:00
* Check i f s y s c a l l i s r e j e c t e d b y t r a c e r , i . e . , a7 = = - 1 .
2019-10-04 17:12:22 -07:00
* If y e s , w e p r e t e n d i t w a s e x e c u t e d .
* /
li t 1 , - 1
beq a7 , t 1 , r e t _ f r o m _ s y s c a l l _ r e j e c t e d
2019-12-18 10:47:56 +02:00
blt a7 , t 1 , 1 f
2019-10-04 17:12:22 -07:00
/* Call syscall */
2017-07-10 18:04:30 -07:00
la s0 , s y s _ c a l l _ t a b l e
slli t 0 , a7 , R I S C V _ L G P T R
add s0 , s0 , t 0
REG_ L s0 , 0 ( s0 )
1 :
jalr s0
ret_from_syscall :
/* Set user a0 to kernel a0 */
REG_ S a0 , P T _ A 0 ( s p )
2019-10-04 17:12:22 -07:00
/ *
* We d i d n ' t e x e c u t e t h e a c t u a l s y s c a l l .
* Seccomp a l r e a d y s e t r e t u r n v a l u e f o r t h e c u r r e n t t a s k p t _ r e g s .
* ( If i t w a s c o n f i g u r e d w i t h S E C C O M P _ R E T _ E R R N O / T R A C E )
* /
ret_from_syscall_rejected :
2017-07-10 18:04:30 -07:00
/* Trace syscalls, but only if requested by the user. */
REG_ L t 0 , T A S K _ T I _ F L A G S ( t p )
2018-10-29 11:48:53 +01:00
andi t 0 , t 0 , _ T I F _ S Y S C A L L _ W O R K
2017-07-10 18:04:30 -07:00
bnez t 0 , h a n d l e _ s y s c a l l _ t r a c e _ e x i t
ret_from_exception :
2019-10-28 13:10:32 +01:00
REG_ L s0 , P T _ S T A T U S ( s p )
csrc C S R _ S T A T U S , S R _ I E
# ifdef C O N F I G _ R I S C V _ M _ M O D E
/* the MPP value is too large to be used as an immediate arg for addi */
li t 0 , S R _ M P P
and s0 , s0 , t 0
# else
2018-01-04 18:35:03 +01:00
andi s0 , s0 , S R _ S P P
2019-10-28 13:10:32 +01:00
# endif
2019-01-03 11:32:33 +08:00
bnez s0 , r e s u m e _ k e r n e l
2017-07-10 18:04:30 -07:00
resume_userspace :
/* Interrupts must be disabled here so flags are checked atomically */
REG_ L s0 , T A S K _ T I _ F L A G S ( t p ) / * c u r r e n t _ t h r e a d _ i n f o - > f l a g s * /
andi s1 , s0 , _ T I F _ W O R K _ M A S K
bnez s1 , w o r k _ p e n d i n g
/* Save unwound kernel stack pointer in thread_info */
addi s0 , s p , P T _ S I Z E _ O N _ S T A C K
REG_ S s0 , T A S K _ T I _ K E R N E L _ S P ( t p )
/ *
2019-10-28 13:10:32 +01:00
* Save T P i n t o t h e s c r a t c h r e g i s t e r , s o w e c a n f i n d t h e k e r n e l d a t a
* structures a g a i n .
2017-07-10 18:04:30 -07:00
* /
2019-10-28 13:10:32 +01:00
csrw C S R _ S C R A T C H , t p
2017-07-10 18:04:30 -07:00
restore_all :
2020-02-27 11:15:03 -08:00
REG_ L a0 , P T _ S T A T U S ( s p )
/ *
* The c u r r e n t l o a d r e s e r v a t i o n i s e f f e c t i v e l y p a r t o f t h e p r o c e s s o r ' s
* state, i n t h e s e n s e t h a t l o a d r e s e r v a t i o n s c a n n o t b e s h a r e d b e t w e e n
* different h a r t c o n t e x t s . W e c a n ' t a c t u a l l y s a v e a n d r e s t o r e a l o a d
* reservation, s o i n s t e a d h e r e w e c l e a r a n y e x i s t i n g r e s e r v a t i o n - -
* it' s a l w a y s l e g a l f o r i m p l e m e n t a t i o n s t o c l e a r l o a d r e s e r v a t i o n s a t
* any p o i n t ( a s l o n g a s t h e f o r w a r d p r o g r e s s g u a r a n t e e i s k e p t , b u t
* we' l l i g n o r e t h a t h e r e ) .
*
* Dangling l o a d r e s e r v a t i o n s c a n b e t h e r e s u l t o f t a k i n g a t r a p i n t h e
* middle o f a n L R / S C s e q u e n c e , b u t c a n a l s o b e t h e r e s u l t o f a t a k e n
* forward b r a n c h a r o u n d a n S C - - w h i c h i s h o w w e i m p l e m e n t C A S . A s a
* result w e n e e d t o c l e a r r e s e r v a t i o n s b e t w e e n t h e l a s t C A S a n d t h e
* jump b a c k t o t h e n e w c o n t e x t . W h i l e i t i s u n l i k e l y t h e s t o r e
* completes, i m p l e m e n t a t i o n s a r e a l l o w e d t o e x p a n d r e s e r v a t i o n s t o b e
* arbitrarily l a r g e .
* /
REG_ L a2 , P T _ E P C ( s p )
REG_ S C x0 , a2 , P T _ E P C ( s p )
csrw C S R _ S T A T U S , a0
csrw C S R _ E P C , a2
REG_ L x1 , P T _ R A ( s p )
REG_ L x3 , P T _ G P ( s p )
REG_ L x4 , P T _ T P ( s p )
REG_ L x5 , P T _ T 0 ( s p )
REG_ L x6 , P T _ T 1 ( s p )
REG_ L x7 , P T _ T 2 ( s p )
REG_ L x8 , P T _ S 0 ( s p )
REG_ L x9 , P T _ S 1 ( s p )
REG_ L x10 , P T _ A 0 ( s p )
REG_ L x11 , P T _ A 1 ( s p )
REG_ L x12 , P T _ A 2 ( s p )
REG_ L x13 , P T _ A 3 ( s p )
REG_ L x14 , P T _ A 4 ( s p )
REG_ L x15 , P T _ A 5 ( s p )
REG_ L x16 , P T _ A 6 ( s p )
REG_ L x17 , P T _ A 7 ( s p )
REG_ L x18 , P T _ S 2 ( s p )
REG_ L x19 , P T _ S 3 ( s p )
REG_ L x20 , P T _ S 4 ( s p )
REG_ L x21 , P T _ S 5 ( s p )
REG_ L x22 , P T _ S 6 ( s p )
REG_ L x23 , P T _ S 7 ( s p )
REG_ L x24 , P T _ S 8 ( s p )
REG_ L x25 , P T _ S 9 ( s p )
REG_ L x26 , P T _ S 1 0 ( s p )
REG_ L x27 , P T _ S 1 1 ( s p )
REG_ L x28 , P T _ T 3 ( s p )
REG_ L x29 , P T _ T 4 ( s p )
REG_ L x30 , P T _ T 5 ( s p )
REG_ L x31 , P T _ T 6 ( s p )
REG_ L x2 , P T _ S P ( s p )
2019-10-28 13:10:32 +01:00
# ifdef C O N F I G _ R I S C V _ M _ M O D E
mret
# else
2017-07-10 18:04:30 -07:00
sret
2019-10-28 13:10:32 +01:00
# endif
2017-07-10 18:04:30 -07:00
2019-10-15 21:18:03 +02:00
# if I S _ E N A B L E D ( C O N F I G _ P R E E M P T I O N )
2019-01-03 11:32:33 +08:00
resume_kernel :
REG_ L s0 , T A S K _ T I _ P R E E M P T _ C O U N T ( t p )
bnez s0 , r e s t o r e _ a l l
REG_ L s0 , T A S K _ T I _ F L A G S ( t p )
andi s0 , s0 , _ T I F _ N E E D _ R E S C H E D
beqz s0 , r e s t o r e _ a l l
call p r e e m p t _ s c h e d u l e _ i r q
2019-09-23 15:36:17 +01:00
j r e s t o r e _ a l l
2019-01-03 11:32:33 +08:00
# endif
2017-07-10 18:04:30 -07:00
work_pending :
/* Enter slow path for supplementary processing */
la r a , r e t _ f r o m _ e x c e p t i o n
andi s1 , s0 , _ T I F _ N E E D _ R E S C H E D
bnez s1 , w o r k _ r e s c h e d
work_notifysig :
/* Handle pending signals and notify-resume requests */
2019-10-28 13:10:32 +01:00
csrs C S R _ S T A T U S , S R _ I E / * E n a b l e i n t e r r u p t s f o r d o _ n o t i f y _ r e s u m e ( ) * /
2017-07-10 18:04:30 -07:00
move a0 , s p / * p t _ r e g s * /
move a1 , s0 / * c u r r e n t _ t h r e a d _ i n f o - > f l a g s * /
tail d o _ n o t i f y _ r e s u m e
work_resched :
tail s c h e d u l e
/* Slow paths for ptrace. */
handle_syscall_trace_enter :
move a0 , s p
call d o _ s y s c a l l _ t r a c e _ e n t e r
riscv: fix seccomp reject syscall code path
If secure_computing() rejected a system call, we were previously setting
the system call number to -1, to indicate to later code that the syscall
failed. However, if something (e.g. a user notification) was sleeping, and
received a signal, we may set a0 to -ERESTARTSYS and re-try the system call
again.
In this case, seccomp "denies" the syscall (because of the signal), and we
would set a7 to -1, thus losing the value of the system call we want to
restart.
Instead, let's return -1 from do_syscall_trace_enter() to indicate that the
syscall was rejected, so we don't clobber the value in case of -ERESTARTSYS
or whatever.
This commit fixes the user_notification_signal seccomp selftest on riscv to
no longer hang. That test expects the system call to be re-issued after the
signal, and it wasn't due to the above bug. Now that it is, everything
works normally.
Note that in the ptrace (tracer) case, the tracer can set the register
values to whatever they want, so we still need to keep the code that
handles out-of-bounds syscalls. However, we can drop the comment.
We can also drop syscall_set_nr(), since it is no longer used anywhere, and
the code that re-loads the value in a7 because of it.
Reported in: https://lore.kernel.org/bpf/CAEn-LTp=ss0Dfv6J00=rCAy+N78U2AmhqJNjfqjr2FDpPYjxEQ@mail.gmail.com/
Reported-by: David Abdurachmanov <david.abdurachmanov@gmail.com>
Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
2020-02-08 08:18:17 -07:00
move t 0 , a0
2017-07-10 18:04:30 -07:00
REG_ L a0 , P T _ A 0 ( s p )
REG_ L a1 , P T _ A 1 ( s p )
REG_ L a2 , P T _ A 2 ( s p )
REG_ L a3 , P T _ A 3 ( s p )
REG_ L a4 , P T _ A 4 ( s p )
REG_ L a5 , P T _ A 5 ( s p )
REG_ L a6 , P T _ A 6 ( s p )
REG_ L a7 , P T _ A 7 ( s p )
riscv: fix seccomp reject syscall code path
If secure_computing() rejected a system call, we were previously setting
the system call number to -1, to indicate to later code that the syscall
failed. However, if something (e.g. a user notification) was sleeping, and
received a signal, we may set a0 to -ERESTARTSYS and re-try the system call
again.
In this case, seccomp "denies" the syscall (because of the signal), and we
would set a7 to -1, thus losing the value of the system call we want to
restart.
Instead, let's return -1 from do_syscall_trace_enter() to indicate that the
syscall was rejected, so we don't clobber the value in case of -ERESTARTSYS
or whatever.
This commit fixes the user_notification_signal seccomp selftest on riscv to
no longer hang. That test expects the system call to be re-issued after the
signal, and it wasn't due to the above bug. Now that it is, everything
works normally.
Note that in the ptrace (tracer) case, the tracer can set the register
values to whatever they want, so we still need to keep the code that
handles out-of-bounds syscalls. However, we can drop the comment.
We can also drop syscall_set_nr(), since it is no longer used anywhere, and
the code that re-loads the value in a7 because of it.
Reported in: https://lore.kernel.org/bpf/CAEn-LTp=ss0Dfv6J00=rCAy+N78U2AmhqJNjfqjr2FDpPYjxEQ@mail.gmail.com/
Reported-by: David Abdurachmanov <david.abdurachmanov@gmail.com>
Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
2020-02-08 08:18:17 -07:00
bnez t 0 , r e t _ f r o m _ s y s c a l l _ r e j e c t e d
2017-07-10 18:04:30 -07:00
j c h e c k _ s y s c a l l _ n r
handle_syscall_trace_exit :
move a0 , s p
call d o _ s y s c a l l _ t r a c e _ e x i t
j r e t _ f r o m _ e x c e p t i o n
END( h a n d l e _ e x c e p t i o n )
ENTRY( r e t _ f r o m _ f o r k )
la r a , r e t _ f r o m _ e x c e p t i o n
tail s c h e d u l e _ t a i l
ENDPROC( r e t _ f r o m _ f o r k )
ENTRY( r e t _ f r o m _ k e r n e l _ t h r e a d )
call s c h e d u l e _ t a i l
/* Call fn(arg) */
la r a , r e t _ f r o m _ e x c e p t i o n
move a0 , s1
jr s0
ENDPROC( r e t _ f r o m _ k e r n e l _ t h r e a d )
/ *
* Integer r e g i s t e r c o n t e x t s w i t c h
* The c a l l e e - s a v e d r e g i s t e r s m u s t b e s a v e d a n d r e s t o r e d .
*
* a0 : previous t a s k _ s t r u c t ( m u s t b e p r e s e r v e d a c r o s s t h e s w i t c h )
* a1 : next t a s k _ s t r u c t
*
* The v a l u e o f a0 a n d a1 m u s t b e p r e s e r v e d b y t h i s f u n c t i o n , a s t h a t ' s h o w
* arguments a r e p a s s e d t o s c h e d u l e _ t a i l .
* /
ENTRY( _ _ s w i t c h _ t o )
/* Save context into prev->thread */
li a4 , T A S K _ T H R E A D _ R A
add a3 , a0 , a4
add a4 , a1 , a4
REG_ S r a , T A S K _ T H R E A D _ R A _ R A ( a3 )
REG_ S s p , T A S K _ T H R E A D _ S P _ R A ( a3 )
REG_ S s0 , T A S K _ T H R E A D _ S 0 _ R A ( a3 )
REG_ S s1 , T A S K _ T H R E A D _ S 1 _ R A ( a3 )
REG_ S s2 , T A S K _ T H R E A D _ S 2 _ R A ( a3 )
REG_ S s3 , T A S K _ T H R E A D _ S 3 _ R A ( a3 )
REG_ S s4 , T A S K _ T H R E A D _ S 4 _ R A ( a3 )
REG_ S s5 , T A S K _ T H R E A D _ S 5 _ R A ( a3 )
REG_ S s6 , T A S K _ T H R E A D _ S 6 _ R A ( a3 )
REG_ S s7 , T A S K _ T H R E A D _ S 7 _ R A ( a3 )
REG_ S s8 , T A S K _ T H R E A D _ S 8 _ R A ( a3 )
REG_ S s9 , T A S K _ T H R E A D _ S 9 _ R A ( a3 )
REG_ S s10 , T A S K _ T H R E A D _ S 1 0 _ R A ( a3 )
REG_ S s11 , T A S K _ T H R E A D _ S 1 1 _ R A ( a3 )
/* Restore context from next->thread */
REG_ L r a , T A S K _ T H R E A D _ R A _ R A ( a4 )
REG_ L s p , T A S K _ T H R E A D _ S P _ R A ( a4 )
REG_ L s0 , T A S K _ T H R E A D _ S 0 _ R A ( a4 )
REG_ L s1 , T A S K _ T H R E A D _ S 1 _ R A ( a4 )
REG_ L s2 , T A S K _ T H R E A D _ S 2 _ R A ( a4 )
REG_ L s3 , T A S K _ T H R E A D _ S 3 _ R A ( a4 )
REG_ L s4 , T A S K _ T H R E A D _ S 4 _ R A ( a4 )
REG_ L s5 , T A S K _ T H R E A D _ S 5 _ R A ( a4 )
REG_ L s6 , T A S K _ T H R E A D _ S 6 _ R A ( a4 )
REG_ L s7 , T A S K _ T H R E A D _ S 7 _ R A ( a4 )
REG_ L s8 , T A S K _ T H R E A D _ S 8 _ R A ( a4 )
REG_ L s9 , T A S K _ T H R E A D _ S 9 _ R A ( a4 )
REG_ L s10 , T A S K _ T H R E A D _ S 1 0 _ R A ( a4 )
REG_ L s11 , T A S K _ T H R E A D _ S 1 1 _ R A ( a4 )
/* Swap the CPU entry around. */
lw a3 , T A S K _ T I _ C P U ( a0 )
lw a4 , T A S K _ T I _ C P U ( a1 )
sw a3 , T A S K _ T I _ C P U ( a1 )
sw a4 , T A S K _ T I _ C P U ( a0 )
# if T A S K _ T I ! = 0
# error " T A S K _ T I ! = 0 : t p w i l l c o n t a i n a ' s t r u c t t h r e a d _ i n f o ' , n o t a ' s t r u c t t a s k _ s t r u c t ' s o g e t _ c u r r e n t ( ) w o n ' t w o r k . "
addi t p , a1 , T A S K _ T I
# else
move t p , a1
# endif
ret
ENDPROC( _ _ s w i t c h _ t o )
2019-10-28 13:10:41 +01:00
# ifndef C O N F I G _ M M U
# define d o _ p a g e _ f a u l t d o _ t r a p _ u n k n o w n
# endif
2017-07-10 18:04:30 -07:00
.section " .rodata "
/* Exception vector table */
ENTRY( e x c p _ v e c t _ t a b l e )
RISCV_ P T R d o _ t r a p _ i n s n _ m i s a l i g n e d
RISCV_ P T R d o _ t r a p _ i n s n _ f a u l t
RISCV_ P T R d o _ t r a p _ i n s n _ i l l e g a l
RISCV_ P T R d o _ t r a p _ b r e a k
RISCV_ P T R d o _ t r a p _ l o a d _ m i s a l i g n e d
RISCV_ P T R d o _ t r a p _ l o a d _ f a u l t
RISCV_ P T R d o _ t r a p _ s t o r e _ m i s a l i g n e d
RISCV_ P T R d o _ t r a p _ s t o r e _ f a u l t
RISCV_ P T R d o _ t r a p _ e c a l l _ u / * s y s t e m c a l l , g e t s i n t e r c e p t e d * /
RISCV_ P T R d o _ t r a p _ e c a l l _ s
RISCV_ P T R d o _ t r a p _ u n k n o w n
RISCV_ P T R d o _ t r a p _ e c a l l _ m
RISCV_ P T R d o _ p a g e _ f a u l t / * i n s t r u c t i o n p a g e f a u l t * /
RISCV_ P T R d o _ p a g e _ f a u l t / * l o a d p a g e f a u l t * /
RISCV_ P T R d o _ t r a p _ u n k n o w n
RISCV_ P T R d o _ p a g e _ f a u l t / * s t o r e p a g e f a u l t * /
excp_vect_table_end :
END( e x c p _ v e c t _ t a b l e )
2019-10-28 13:10:41 +01:00
# ifndef C O N F I G _ M M U
ENTRY( _ _ u s e r _ r t _ s i g r e t u r n )
li a7 , _ _ N R _ r t _ s i g r e t u r n
scall
END( _ _ u s e r _ r t _ s i g r e t u r n )
# endif