xref: /netbsd-src/sys/arch/arm/cortex/gic_splfuncs_armv8.S (revision dbc391605c93a9219e0579efc3ac352634fe5641)
1/* $NetBSD: gic_splfuncs_armv8.S,v 1.3 2021/10/31 15:32:14 jmcneill Exp $ */
2
3/*-
4 * Copyright (c) 2021 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <machine/asm.h>
30#include "assym.h"
31
32RCSID("$NetBSD: gic_splfuncs_armv8.S,v 1.3 2021/10/31 15:32:14 jmcneill Exp $")
33
34#ifdef __HAVE_PREEMPTION
35#define	DISABLE_PREEMPTION			\
36	ldr	w1, [x3, #L_NOPREEMPT];		\
37	add	w1, w1, #1;			\
38	str	w1, [x3, #L_NOPREEMPT]
39#define	ENABLE_PREEMPTION			\
40	ldr	w1, [x3, #L_NOPREEMPT];		\
41	sub	w1, w1, #1;			\
42	str	w1, [x3, #L_NOPREEMPT]
43#else
44#define	DISABLE_PREEMPTION
45#define	ENABLE_PREEMPTION
46#endif
47
48/*
49 * int
50 * gic_splraise(int newipl)
51 *
52 *	w0 = newipl
53 */
54	.align 7        /* cacheline-aligned */
55ENTRY_NP(gic_splraise)
56	/* Save curlwp in x3, curcpu in x1 */
57	mrs	x3, tpidr_el1			/* get curlwp */
58	DISABLE_PREEMPTION
59	ldr	x1, [x3, #L_CPU]		/* get curcpu */
60
61	/* If newipl > cpl, update cpl */
62	ldr	w2, [x1, #CI_CPL]
63	cmp	w0, w2
64	b.le	.Lnoraise
65	str	w0, [x1, #CI_CPL]
66
67.Lnoraise:
68	ENABLE_PREEMPTION
69	mov	w0, w2				/* return oldipl */
70	ret
71END(gic_splraise)
72
73
74/*
75 * void
76 * gic_splx(int newipl)
77 *
78 *	w0 = newipl
79 */
80	.align 7        /* cacheline-aligned */
81ENTRY_NP(gic_splx)
82	/* Save curlwp in x3, curcpu in x1 */
83	mrs	x3, tpidr_el1			/* get curlwp */
84	DISABLE_PREEMPTION
85	ldr	x1, [x3, #L_CPU]		/* get curcpu */
86
87.Lagain:
88	/* If newipl >= cpl, just return */
89	ldr	w2, [x1, #CI_CPL]
90	cmp	w0, w2
91	b.hs	.Ldone
92
93	/* Slow path if ci_intr_depth != 0 */
94	ldr	w2, [x1, #CI_INTR_DEPTH]
95	cbnz	w2, .Lslow
96
97	/* Save newipl and restart address in cpu info */
98	str	w0, [x1, #CI_SPLX_SAVEDIPL]
99	adr	x2, .Lrestart
100	str	x2, [x1, #CI_SPLX_RESTART]
101
102	/* Slow path if hwpl > newipl */
103	ldr	w2, [x1, #CI_HWPL]
104	cmp	w2, w0
105	b.hi	.Lrestore
106
107	/* Update cpl */
108	str	w0, [x1, #CI_CPL]
109
110	/* Clear saved restart address from cpu info */
111	str	xzr, [x1, #CI_SPLX_RESTART]
112
113	/* Check for pending softints */
114	ldr	w2, [x1, #CI_SOFTINTS]
115	lsr	w2, w2, w0
116	cbnz	w2, _C_LABEL(dosoftints)
117
118.Ldone:
119	ENABLE_PREEMPTION
120	ret
121
122.Lrestart:
123	/* Reload registers */
124	mrs	x3, tpidr_el1			/* get curlwp */
125	ldr	x1, [x3, #L_CPU]		/* get curcpu */
126	ldr	w0, [x1, #CI_SPLX_SAVEDIPL]	/* get newipl */
127	b	.Lagain
128
129.Lrestore:
130	/* Clear saved restart address from cpu info */
131	str	xzr, [x1, #CI_SPLX_RESTART]
132
133.Lslow:
134	ENABLE_PREEMPTION
135	/* Jump to slow path */
136	b	_C_LABEL(Xgic_splx)
137END(gic_splx)
138