summaryrefslogtreecommitdiffstats
path: root/arch/loongarch/kernel/lbt.S
blob: 9c75120a26d836d75d3bb08c2b5a0022a8c5d58d (plain)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Author: Qi Hu <huqi@loongson.cn>
 *         Huacai Chen <chenhuacai@loongson.cn>
 *
 * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
 */
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/asm-extable.h>
#include <asm/asm-offsets.h>
#include <asm/errno.h>
#include <asm/regdef.h>

#define SCR_REG_WIDTH 8

	.macro	EX insn, reg, src, offs
.ex\@:	\insn	\reg, \src, \offs
	_asm_extable .ex\@, .L_lbt_fault
	.endm

/*
 * Save a thread's lbt context.
 */
SYM_FUNC_START(_save_lbt)
	movscr2gr	t1, $scr0		# save scr
	stptr.d		t1, a0, THREAD_SCR0
	movscr2gr	t1, $scr1
	stptr.d		t1, a0, THREAD_SCR1
	movscr2gr	t1, $scr2
	stptr.d		t1, a0, THREAD_SCR2
	movscr2gr	t1, $scr3
	stptr.d		t1, a0, THREAD_SCR3

	x86mfflag	t1, 0x3f		# save eflags
	stptr.d		t1, a0, THREAD_EFLAGS
	jr		ra
SYM_FUNC_END(_save_lbt)
EXPORT_SYMBOL(_save_lbt)

/*
 * Restore a thread's lbt context.
 */
SYM_FUNC_START(_restore_lbt)
	ldptr.d		t1, a0, THREAD_SCR0	# restore scr
	movgr2scr	$scr0, t1
	ldptr.d		t1, a0, THREAD_SCR1
	movgr2scr	$scr1, t1
	ldptr.d		t1, a0, THREAD_SCR2
	movgr2scr	$scr2, t1
	ldptr.d		t1, a0, THREAD_SCR3
	movgr2scr	$scr3, t1

	ldptr.d		t1, a0, THREAD_EFLAGS	# restore eflags
	x86mtflag	t1, 0x3f
	jr		ra
SYM_FUNC_END(_restore_lbt)
EXPORT_SYMBOL(_restore_lbt)

/*
 * Load scr/eflag with zero.
 */
SYM_FUNC_START(_init_lbt)
	movgr2scr	$scr0, zero
	movgr2scr	$scr1, zero
	movgr2scr	$scr2, zero
	movgr2scr	$scr3, zero

	x86mtflag	zero, 0x3f
	jr		ra
SYM_FUNC_END(_init_lbt)

/*
 * a0: scr
 * a1: eflag
 */
SYM_FUNC_START(_save_lbt_context)
	movscr2gr	t1, $scr0		# save scr
	EX	st.d	t1, a0, (0 * SCR_REG_WIDTH)
	movscr2gr	t1, $scr1
	EX	st.d	t1, a0, (1 * SCR_REG_WIDTH)
	movscr2gr	t1, $scr2
	EX	st.d	t1, a0, (2 * SCR_REG_WIDTH)
	movscr2gr	t1, $scr3
	EX	st.d	t1, a0, (3 * SCR_REG_WIDTH)

	x86mfflag	t1, 0x3f		# save eflags
	EX 	st.w	t1, a1, 0
	li.w		a0, 0			# success
	jr		ra
SYM_FUNC_END(_save_lbt_context)

/*
 * a0: scr
 * a1: eflag
 */
SYM_FUNC_START(_restore_lbt_context)
	EX	ld.d	t1, a0, (0 * SCR_REG_WIDTH)	# restore scr
	movgr2scr	$scr0, t1
	EX	ld.d	t1, a0, (1 * SCR_REG_WIDTH)
	movgr2scr	$scr1, t1
	EX	ld.d	t1, a0, (2 * SCR_REG_WIDTH)
	movgr2scr	$scr2, t1
	EX	ld.d	t1, a0, (3 * SCR_REG_WIDTH)
	movgr2scr	$scr3, t1

	EX 	ld.w	t1, a1, 0			# restore eflags
	x86mtflag	t1, 0x3f
	li.w		a0, 0			# success
	jr		ra
SYM_FUNC_END(_restore_lbt_context)

/*
 * a0: ftop
 */
SYM_FUNC_START(_save_ftop_context)
	x86mftop	t1
	st.w		t1, a0, 0
	li.w		a0, 0			# success
	jr		ra
SYM_FUNC_END(_save_ftop_context)

/*
 * a0: ftop
 */
SYM_FUNC_START(_restore_ftop_context)
	ld.w		t1, a0, 0
	andi		t1, t1, 0x7
	la.pcrel	a0, 1f
	alsl.d		a0, t1, a0, 3
	jr		a0
1:
	x86mttop	0
	b	2f
	x86mttop	1
	b	2f
	x86mttop	2
	b	2f
	x86mttop	3
	b	2f
	x86mttop	4
	b	2f
	x86mttop	5
	b	2f
	x86mttop	6
	b	2f
	x86mttop	7
2:
	li.w		a0, 0			# success
	jr		ra
SYM_FUNC_END(_restore_ftop_context)

.L_lbt_fault:
	li.w		a0, -EFAULT		# failure
	jr		ra