xref: /openbmc/linux/arch/mips/include/asm/dsemul.h (revision 2874c5fd)
12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
2432c6bacSPaul Burton /*
3432c6bacSPaul Burton  * Copyright (C) 2016 Imagination Technologies
4fb615d61SPaul Burton  * Author: Paul Burton <paul.burton@mips.com>
5432c6bacSPaul Burton  */
6432c6bacSPaul Burton 
7432c6bacSPaul Burton #ifndef __MIPS_ASM_DSEMUL_H__
8432c6bacSPaul Burton #define __MIPS_ASM_DSEMUL_H__
9432c6bacSPaul Burton 
10432c6bacSPaul Burton #include <asm/break.h>
11432c6bacSPaul Burton #include <asm/inst.h>
12432c6bacSPaul Burton 
13432c6bacSPaul Burton /* Break instruction with special math emu break code set */
14432c6bacSPaul Burton #define BREAK_MATH(micromips)	(((micromips) ? 0x7 : 0xd) | (BRK_MEMU << 16))
15432c6bacSPaul Burton 
16432c6bacSPaul Burton /* When used as a frame index, indicates the lack of a frame */
17432c6bacSPaul Burton #define BD_EMUFRAME_NONE	((int)BIT(31))
18432c6bacSPaul Burton 
19432c6bacSPaul Burton struct mm_struct;
20432c6bacSPaul Burton struct pt_regs;
21432c6bacSPaul Burton struct task_struct;
22432c6bacSPaul Burton 
23432c6bacSPaul Burton /**
24432c6bacSPaul Burton  * mips_dsemul() - 'Emulate' an instruction from a branch delay slot
25432c6bacSPaul Burton  * @regs:	User thread register context.
26432c6bacSPaul Burton  * @ir:		The instruction to be 'emulated'.
27432c6bacSPaul Burton  * @branch_pc:	The PC of the branch instruction.
28432c6bacSPaul Burton  * @cont_pc:	The PC to continue at following 'emulation'.
29432c6bacSPaul Burton  *
30432c6bacSPaul Burton  * Emulate or execute an arbitrary MIPS instruction within the context of
31432c6bacSPaul Burton  * the current user thread. This is used primarily to handle instructions
32432c6bacSPaul Burton  * in the delay slots of emulated branch instructions, for example FP
33432c6bacSPaul Burton  * branch instructions on systems without an FPU.
34432c6bacSPaul Burton  *
35432c6bacSPaul Burton  * Return: Zero on success, negative if ir is a NOP, signal number on failure.
36432c6bacSPaul Burton  */
37432c6bacSPaul Burton extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
38432c6bacSPaul Burton 		       unsigned long branch_pc, unsigned long cont_pc);
39432c6bacSPaul Burton 
40432c6bacSPaul Burton /**
41432c6bacSPaul Burton  * do_dsemulret() - Return from a delay slot 'emulation' frame
42432c6bacSPaul Burton  * @xcp:	User thread register context.
43432c6bacSPaul Burton  *
44432c6bacSPaul Burton  * Call in response to the BRK_MEMU break instruction used to return to
45432c6bacSPaul Burton  * the kernel from branch delay slot 'emulation' frames following a call
46432c6bacSPaul Burton  * to mips_dsemul(). Restores the user thread PC to the value that was
47432c6bacSPaul Burton  * passed as the cpc parameter to mips_dsemul().
48432c6bacSPaul Burton  *
49432c6bacSPaul Burton  * Return: True if an emulation frame was returned from, else false.
50432c6bacSPaul Burton  */
5142b10815SPaul Burton #ifdef CONFIG_MIPS_FP_SUPPORT
52432c6bacSPaul Burton extern bool do_dsemulret(struct pt_regs *xcp);
5342b10815SPaul Burton #else
do_dsemulret(struct pt_regs * xcp)5442b10815SPaul Burton static inline bool do_dsemulret(struct pt_regs *xcp)
5542b10815SPaul Burton {
5642b10815SPaul Burton 	return false;
5742b10815SPaul Burton }
5842b10815SPaul Burton #endif
59432c6bacSPaul Burton 
60432c6bacSPaul Burton /**
61432c6bacSPaul Burton  * dsemul_thread_cleanup() - Cleanup thread 'emulation' frame
62432c6bacSPaul Burton  * @tsk: The task structure associated with the thread
63432c6bacSPaul Burton  *
64432c6bacSPaul Burton  * If the thread @tsk has a branch delay slot 'emulation' frame
65432c6bacSPaul Burton  * allocated to it then free that frame.
66432c6bacSPaul Burton  *
67432c6bacSPaul Burton  * Return: True if a frame was freed, else false.
68432c6bacSPaul Burton  */
6942b10815SPaul Burton #ifdef CONFIG_MIPS_FP_SUPPORT
70432c6bacSPaul Burton extern bool dsemul_thread_cleanup(struct task_struct *tsk);
7142b10815SPaul Burton #else
dsemul_thread_cleanup(struct task_struct * tsk)7242b10815SPaul Burton static inline bool dsemul_thread_cleanup(struct task_struct *tsk)
7342b10815SPaul Burton {
7442b10815SPaul Burton 	return false;
7542b10815SPaul Burton }
7642b10815SPaul Burton #endif
77432c6bacSPaul Burton /**
78432c6bacSPaul Burton  * dsemul_thread_rollback() - Rollback from an 'emulation' frame
79432c6bacSPaul Burton  * @regs:	User thread register context.
80432c6bacSPaul Burton  *
81432c6bacSPaul Burton  * If the current thread, whose register context is represented by @regs,
82432c6bacSPaul Burton  * is executing within a delay slot 'emulation' frame then exit that
83432c6bacSPaul Burton  * frame. The PC will be rolled back to the branch if the instruction
84432c6bacSPaul Burton  * that was being 'emulated' has not yet executed, or advanced to the
85432c6bacSPaul Burton  * continuation PC if it has.
86432c6bacSPaul Burton  *
87432c6bacSPaul Burton  * Return: True if a frame was exited, else false.
88432c6bacSPaul Burton  */
8942b10815SPaul Burton #ifdef CONFIG_MIPS_FP_SUPPORT
90432c6bacSPaul Burton extern bool dsemul_thread_rollback(struct pt_regs *regs);
9142b10815SPaul Burton #else
dsemul_thread_rollback(struct pt_regs * regs)9242b10815SPaul Burton static inline bool dsemul_thread_rollback(struct pt_regs *regs)
9342b10815SPaul Burton {
9442b10815SPaul Burton 	return false;
9542b10815SPaul Burton }
9642b10815SPaul Burton #endif
97432c6bacSPaul Burton 
98432c6bacSPaul Burton /**
99432c6bacSPaul Burton  * dsemul_mm_cleanup() - Cleanup per-mm delay slot 'emulation' state
100432c6bacSPaul Burton  * @mm:		The struct mm_struct to cleanup state for.
101432c6bacSPaul Burton  *
102432c6bacSPaul Burton  * Cleanup state for the given @mm, ensuring that any memory allocated
103432c6bacSPaul Burton  * for delay slot 'emulation' book-keeping is freed. This is to be called
104432c6bacSPaul Burton  * before @mm is freed in order to avoid memory leaks.
105432c6bacSPaul Burton  */
10642b10815SPaul Burton #ifdef CONFIG_MIPS_FP_SUPPORT
107432c6bacSPaul Burton extern void dsemul_mm_cleanup(struct mm_struct *mm);
10842b10815SPaul Burton #else
dsemul_mm_cleanup(struct mm_struct * mm)10942b10815SPaul Burton static inline void dsemul_mm_cleanup(struct mm_struct *mm)
11042b10815SPaul Burton {
11142b10815SPaul Burton 	/* no-op */
11242b10815SPaul Burton }
11342b10815SPaul Burton #endif
114432c6bacSPaul Burton 
115432c6bacSPaul Burton #endif /* __MIPS_ASM_DSEMUL_H__ */
116