11.3Sjmcneill/* $NetBSD: gic_splfuncs_armv8.S,v 1.3 2021/10/31 15:32:14 jmcneill Exp $ */ 21.1Sjmcneill 31.1Sjmcneill/*- 41.1Sjmcneill * Copyright (c) 2021 Jared McNeill <jmcneill@invisible.ca> 51.1Sjmcneill * All rights reserved. 61.1Sjmcneill * 71.1Sjmcneill * Redistribution and use in source and binary forms, with or without 81.1Sjmcneill * modification, are permitted provided that the following conditions 91.1Sjmcneill * are met: 101.1Sjmcneill * 1. Redistributions of source code must retain the above copyright 111.1Sjmcneill * notice, this list of conditions and the following disclaimer. 121.1Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 131.1Sjmcneill * notice, this list of conditions and the following disclaimer in the 141.1Sjmcneill * documentation and/or other materials provided with the distribution. 151.1Sjmcneill * 161.1Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 171.1Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 181.1Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 191.1Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 201.1Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211.1Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 221.1Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231.1Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241.1Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251.1Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261.1Sjmcneill * SUCH DAMAGE. 271.1Sjmcneill */ 281.1Sjmcneill 291.1Sjmcneill#include <machine/asm.h> 301.1Sjmcneill#include "assym.h" 311.1Sjmcneill 321.3SjmcneillRCSID("$NetBSD: gic_splfuncs_armv8.S,v 1.3 2021/10/31 15:32:14 jmcneill Exp $") 331.2Sjmcneill 341.2Sjmcneill#ifdef __HAVE_PREEMPTION 351.2Sjmcneill#define DISABLE_PREEMPTION \ 361.2Sjmcneill ldr w1, [x3, #L_NOPREEMPT]; \ 371.2Sjmcneill add w1, w1, #1; \ 381.2Sjmcneill str w1, [x3, #L_NOPREEMPT] 391.2Sjmcneill#define ENABLE_PREEMPTION \ 401.2Sjmcneill ldr w1, [x3, #L_NOPREEMPT]; \ 411.2Sjmcneill sub w1, w1, #1; \ 421.2Sjmcneill str w1, [x3, #L_NOPREEMPT] 431.2Sjmcneill#else 441.2Sjmcneill#define DISABLE_PREEMPTION 451.2Sjmcneill#define ENABLE_PREEMPTION 461.2Sjmcneill#endif 471.1Sjmcneill 481.1Sjmcneill/* 491.1Sjmcneill * int 501.1Sjmcneill * gic_splraise(int newipl) 511.1Sjmcneill * 521.1Sjmcneill * w0 = newipl 531.1Sjmcneill */ 541.1Sjmcneill .align 7 /* cacheline-aligned */ 551.1SjmcneillENTRY_NP(gic_splraise) 561.2Sjmcneill /* Save curlwp in x3, curcpu in x1 */ 571.2Sjmcneill mrs x3, tpidr_el1 /* get curlwp */ 581.2Sjmcneill DISABLE_PREEMPTION 591.2Sjmcneill ldr x1, [x3, #L_CPU] /* get curcpu */ 601.1Sjmcneill 611.1Sjmcneill /* If newipl > cpl, update cpl */ 621.1Sjmcneill ldr w2, [x1, #CI_CPL] 631.1Sjmcneill cmp w0, w2 641.1Sjmcneill b.le .Lnoraise 651.1Sjmcneill str w0, [x1, #CI_CPL] 661.1Sjmcneill 671.1Sjmcneill.Lnoraise: 681.2Sjmcneill ENABLE_PREEMPTION 691.1Sjmcneill mov w0, w2 /* return oldipl */ 701.1Sjmcneill ret 711.1SjmcneillEND(gic_splraise) 721.1Sjmcneill 731.1Sjmcneill 741.1Sjmcneill/* 751.1Sjmcneill * void 761.1Sjmcneill * gic_splx(int newipl) 771.1Sjmcneill * 781.1Sjmcneill * w0 = newipl 791.1Sjmcneill */ 801.1Sjmcneill .align 7 /* cacheline-aligned */ 811.1SjmcneillENTRY_NP(gic_splx) 821.2Sjmcneill /* Save curlwp in x3, curcpu in x1 */ 831.2Sjmcneill mrs x3, tpidr_el1 /* get curlwp */ 841.2Sjmcneill DISABLE_PREEMPTION 851.2Sjmcneill ldr x1, [x3, #L_CPU] /* get curcpu */ 861.1Sjmcneill 871.3Sjmcneill.Lagain: 881.1Sjmcneill /* If newipl >= cpl, just return */ 891.1Sjmcneill ldr w2, [x1, #CI_CPL] 901.1Sjmcneill cmp w0, w2 911.1Sjmcneill b.hs .Ldone 921.1Sjmcneill 931.1Sjmcneill /* Slow path if ci_intr_depth != 0 */ 941.1Sjmcneill ldr w2, [x1, #CI_INTR_DEPTH] 951.1Sjmcneill cbnz w2, .Lslow 961.1Sjmcneill 971.1Sjmcneill /* Save newipl and restart address in cpu info */ 981.1Sjmcneill str w0, [x1, #CI_SPLX_SAVEDIPL] 991.1Sjmcneill adr x2, .Lrestart 1001.1Sjmcneill str x2, [x1, #CI_SPLX_RESTART] 1011.1Sjmcneill 1021.1Sjmcneill /* Slow path if hwpl > newipl */ 1031.1Sjmcneill ldr w2, [x1, #CI_HWPL] 1041.1Sjmcneill cmp w2, w0 1051.1Sjmcneill b.hi .Lrestore 1061.1Sjmcneill 1071.1Sjmcneill /* Update cpl */ 1081.1Sjmcneill str w0, [x1, #CI_CPL] 1091.1Sjmcneill 1101.1Sjmcneill /* Clear saved restart address from cpu info */ 1111.1Sjmcneill str xzr, [x1, #CI_SPLX_RESTART] 1121.1Sjmcneill 1131.1Sjmcneill /* Check for pending softints */ 1141.1Sjmcneill ldr w2, [x1, #CI_SOFTINTS] 1151.1Sjmcneill lsr w2, w2, w0 1161.1Sjmcneill cbnz w2, _C_LABEL(dosoftints) 1171.1Sjmcneill 1181.1Sjmcneill.Ldone: 1191.2Sjmcneill ENABLE_PREEMPTION 1201.1Sjmcneill ret 1211.1Sjmcneill 1221.1Sjmcneill.Lrestart: 1231.3Sjmcneill /* Reload registers */ 1241.3Sjmcneill mrs x3, tpidr_el1 /* get curlwp */ 1251.3Sjmcneill ldr x1, [x3, #L_CPU] /* get curcpu */ 1261.1Sjmcneill ldr w0, [x1, #CI_SPLX_SAVEDIPL] /* get newipl */ 1271.1Sjmcneill b .Lagain 1281.1Sjmcneill 1291.1Sjmcneill.Lrestore: 1301.1Sjmcneill /* Clear saved restart address from cpu info */ 1311.1Sjmcneill str xzr, [x1, #CI_SPLX_RESTART] 1321.1Sjmcneill 1331.1Sjmcneill.Lslow: 1341.2Sjmcneill ENABLE_PREEMPTION 1351.1Sjmcneill /* Jump to slow path */ 1361.1Sjmcneill b _C_LABEL(Xgic_splx) 1371.1SjmcneillEND(gic_splx) 138