/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include /* To get SYSBASE and PAGESIZE */ #include #if !defined(lint) .seg ".text" .align 4 #define PSR_PIL_BIT 0x8 /* * Macro to raise processor priority level. * Avoid dropping processor priority if already at high level. * Also avoid going below CPU->cpu_base_spl, which could've just been set by * a higher-level interrupt thread that just blocked. * XXX4U: bring splr inline */ #define RAISE(level) \ b splr; \ mov ((level) << PSR_PIL_BIT), %o0 /* * Macro to set the priority to a specified level. * Avoid dropping the priority below CPU->cpu_base_spl. * XXX4U: bring splx inline */ #define SETPRI(level) \ b splx; \ mov ((level) << PSR_PIL_BIT), %o0 #endif /* lint */ /* * Berkley 4.3 introduced symbolically named interrupt levels * as a way deal with priority in a machine independent fashion. * Numbered priorities are machine specific, and should be * discouraged where possible. * * Note, for the machine specific priorities there are * examples listed for devices that use a particular priority. * It should not be construed that all devices of that * type should be at that priority. It is currently were * the current devices fit into the priority scheme based * upon time criticalness. * * The underlying assumption of these assignments is that * SPARC9 IPL 10 is the highest level from which a device * routine can call wakeup. Devices that interrupt from higher * levels are restricted in what they can do. If they need * kernels services they should schedule a routine at a lower * level (via software interrupt) to do the required * processing. * * Examples of this higher usage: * Level Usage * 15 Asynchronous memory exceptions * 14 Profiling clock (and PROM uart polling clock) * 13 Audio device * 12 Serial ports * 11 Floppy controller * * The serial ports request lower level processing on level 6. * Audio and floppy request lower level processing on level 4. * * Also, almost all splN routines (where N is a number or a * mnemonic) will do a RAISE(), on the assumption that they are * never used to lower our priority. * The exceptions are: * spl8() Because you can't be above 15 to begin with! * splzs() Because this is used at boot time to lower our * priority, to allow the PROM to poll the uart. * spl0() Used to lower priority to 0. * splsoftclock() Used by hardclock to lower priority. */ #if defined(lint) int splimp(void) { return (0); } int splnet(void) { return (0); } #ifdef notdef int spl6(void) { return (0); } int spl5(void) { return (0); } #endif notdef #else /* lint */ /* locks out all interrupts, including memory errors */ ENTRY(spl8) SETPRI(15) SET_SIZE(spl8) /* just below the level that profiling runs */ ALTENTRY(splaudio) ENTRY(spl7) RAISE(13) SET_SIZE(spl7) SET_SIZE(splaudio) /* sun specific - highest priority onboard serial i/o zs ports */ ALTENTRY(splzs) SETPRI(12) /* Can't be a RAISE, as it's used to lower us */ SET_SIZE(splzs) /* * should lock out clocks and all interrupts, * as you can see, there are exceptions */ ALTENTRY(splhigh) ALTENTRY(splhi) /* the standard clock interrupt priority */ ALTENTRY(splclock) /* highest priority for any tty handling */ ALTENTRY(spltty) /* highest priority required for protection of buffered io system */ ALTENTRY(splbio) /* machine specific */ ENTRY2(spl6,spl5) RAISE(10) SET_SIZE(splhigh) SET_SIZE(splhi) SET_SIZE(splclock) SET_SIZE(spltty) SET_SIZE(splbio) SET_SIZE(spl5) SET_SIZE(spl6) /* * machine specific * for sun, some frame buffers must be at this priority */ ENTRY(spl4) RAISE(8) SET_SIZE(spl4) /* highest level that any network device will use */ ALTENTRY(splimp) /* * machine specific * for sun, devices with limited buffering: tapes, ethernet */ ENTRY(spl3) RAISE(6) SET_SIZE(splimp) SET_SIZE(spl3) /* * machine specific - not as time critical as above * for sun, disks */ ENTRY(spl2) RAISE(4) SET_SIZE(spl2) ENTRY(spl1) RAISE(2) SET_SIZE(spl1) /* highest level that any protocol handler will run */ ENTRY(splnet) RAISE(1) SET_SIZE(splnet) /* softcall priority */ /* used by hardclock to LOWER priority */ ENTRY(splsoftclock) SETPRI(1) SET_SIZE(splsoftclock) /* allow all interrupts */ ENTRY(spl0) SETPRI(0) SET_SIZE(spl0) #endif /* lint */ /* * splx - set PIL back to that indicated by the old %PSR passed as an argument, * or to the CPU's base priority, whichever is higher. * sys_rtt (in locore.s) relies on this not to use %g1 or %g2. */ #if defined(lint) /* ARGSUSED */ void splx(int level) { } #else /* lint */ ENTRY(splx) rdpr %pil, %o1 ! get current pil wrpr %o0, %pil retl mov %o1, %o0 SET_SIZE(splx) #endif /* level */ /* * splr() * * splr is like splx but will only raise the priority and never drop it * Be careful not to set priority lower than CPU->cpu_base_pri, * even though it seems we're raising the priority, it could be set higher * at any time by an interrupt routine, so we must block interrupts and * look at CPU->cpu_base_pri. * */ #if defined(lint) #ifdef notdef /* ARGSUSED */ int splr(int level) { return (0); } #endif notdef #else /* lint */ /* * splr(psr_pri_field) * splr is like splx but will only raise the priority and never drop it */ ENTRY(splr) rdpr %pil, %o1 ! get current pil cmp %o0, %o1 ble 1f nop wrpr %o0, %pil 1: retl mov %o1, %o0 ! return the old pil SET_SIZE(splr) #endif /* lint */ /* * get_ticks() */ #if defined(lint) /* ARGSUSED */ uint64_t get_ticks(void) { return (0); } #else /* lint */ ENTRY(get_ticks) rdpr %tick, %o0 sllx %o0, 1, %o0 retl srlx %o0, 1, %o0 ! shake off npt bit SET_SIZE(get_ticks) #endif /* lint */