Home | History | Annotate | Line # | Download | only in arm32
cpuswitch.S revision 1.57
      1  1.57       scw /*	$NetBSD: cpuswitch.S,v 1.57 2008/04/20 15:42:19 scw Exp $	*/
      2   1.1     chris 
      3   1.1     chris /*
      4  1.30       scw  * Copyright 2003 Wasabi Systems, Inc.
      5  1.30       scw  * All rights reserved.
      6  1.30       scw  *
      7  1.30       scw  * Written by Steve C. Woodford for Wasabi Systems, Inc.
      8  1.30       scw  *
      9  1.30       scw  * Redistribution and use in source and binary forms, with or without
     10  1.30       scw  * modification, are permitted provided that the following conditions
     11  1.30       scw  * are met:
     12  1.30       scw  * 1. Redistributions of source code must retain the above copyright
     13  1.30       scw  *    notice, this list of conditions and the following disclaimer.
     14  1.30       scw  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.30       scw  *    notice, this list of conditions and the following disclaimer in the
     16  1.30       scw  *    documentation and/or other materials provided with the distribution.
     17  1.30       scw  * 3. All advertising materials mentioning features or use of this software
     18  1.30       scw  *    must display the following acknowledgement:
     19  1.30       scw  *      This product includes software developed for the NetBSD Project by
     20  1.30       scw  *      Wasabi Systems, Inc.
     21  1.30       scw  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  1.30       scw  *    or promote products derived from this software without specific prior
     23  1.30       scw  *    written permission.
     24  1.30       scw  *
     25  1.30       scw  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  1.30       scw  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  1.30       scw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  1.30       scw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  1.30       scw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  1.30       scw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  1.30       scw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  1.30       scw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  1.30       scw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  1.30       scw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  1.30       scw  * POSSIBILITY OF SUCH DAMAGE.
     36  1.30       scw  */
     37  1.30       scw /*
     38   1.1     chris  * Copyright (c) 1994-1998 Mark Brinicombe.
     39   1.1     chris  * Copyright (c) 1994 Brini.
     40   1.1     chris  * All rights reserved.
     41   1.1     chris  *
     42   1.1     chris  * This code is derived from software written for Brini by Mark Brinicombe
     43   1.1     chris  *
     44   1.1     chris  * Redistribution and use in source and binary forms, with or without
     45   1.1     chris  * modification, are permitted provided that the following conditions
     46   1.1     chris  * are met:
     47   1.1     chris  * 1. Redistributions of source code must retain the above copyright
     48   1.1     chris  *    notice, this list of conditions and the following disclaimer.
     49   1.1     chris  * 2. Redistributions in binary form must reproduce the above copyright
     50   1.1     chris  *    notice, this list of conditions and the following disclaimer in the
     51   1.1     chris  *    documentation and/or other materials provided with the distribution.
     52   1.1     chris  * 3. All advertising materials mentioning features or use of this software
     53   1.1     chris  *    must display the following acknowledgement:
     54   1.1     chris  *	This product includes software developed by Brini.
     55   1.1     chris  * 4. The name of the company nor the name of the author may be used to
     56   1.1     chris  *    endorse or promote products derived from this software without specific
     57   1.1     chris  *    prior written permission.
     58   1.1     chris  *
     59   1.1     chris  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
     60   1.1     chris  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     61   1.1     chris  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     62   1.1     chris  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     63   1.1     chris  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     64   1.1     chris  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     65   1.1     chris  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     66   1.1     chris  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     67   1.1     chris  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     68   1.1     chris  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     69   1.1     chris  * SUCH DAMAGE.
     70   1.1     chris  *
     71   1.1     chris  * RiscBSD kernel project
     72   1.1     chris  *
     73   1.1     chris  * cpuswitch.S
     74   1.1     chris  *
     75   1.1     chris  * cpu switching functions
     76   1.1     chris  *
     77   1.1     chris  * Created      : 15/10/94
     78   1.1     chris  */
     79   1.1     chris 
     80   1.1     chris #include "opt_armfpe.h"
     81  1.30       scw #include "opt_arm32_pmap.h"
     82  1.19     bjh21 #include "opt_multiprocessor.h"
     83  1.36    martin #include "opt_lockdebug.h"
     84   1.1     chris 
     85   1.1     chris #include "assym.h"
     86  1.46    briggs #include <arm/arm32/pte.h>
     87   1.1     chris #include <machine/param.h>
     88   1.1     chris #include <machine/cpu.h>
     89   1.1     chris #include <machine/frame.h>
     90   1.1     chris #include <machine/asm.h>
     91   1.1     chris 
     92  1.34  kristerw /* LINTSTUB: include <sys/param.h> */
     93  1.34  kristerw 
     94   1.1     chris #undef IRQdisable
     95   1.1     chris #undef IRQenable
     96   1.1     chris 
     97   1.1     chris /*
     98   1.1     chris  * New experimental definitions of IRQdisable and IRQenable
     99   1.1     chris  * These keep FIQ's enabled since FIQ's are special.
    100   1.1     chris  */
    101   1.1     chris 
    102   1.1     chris #define IRQdisable \
    103  1.13   thorpej 	mrs	r14, cpsr ; \
    104   1.1     chris 	orr	r14, r14, #(I32_bit) ; \
    105  1.13   thorpej 	msr	cpsr_c, r14 ; \
    106   1.1     chris 
    107   1.1     chris #define IRQenable \
    108  1.13   thorpej 	mrs	r14, cpsr ; \
    109   1.1     chris 	bic	r14, r14, #(I32_bit) ; \
    110  1.13   thorpej 	msr	cpsr_c, r14 ; \
    111   1.1     chris 
    112   1.1     chris 	.text
    113   1.1     chris 
    114  1.19     bjh21 #ifdef MULTIPROCESSOR
    115  1.19     bjh21 .Lcpu_info_store:
    116  1.19     bjh21 	.word	_C_LABEL(cpu_info_store)
    117  1.29   thorpej .Lcurlwp:
    118  1.19     bjh21 	/* FIXME: This is bogus in the general case. */
    119  1.29   thorpej 	.word	_C_LABEL(cpu_info_store) + CI_CURLWP
    120  1.22     bjh21 
    121  1.22     bjh21 .Lcurpcb:
    122  1.22     bjh21 	.word	_C_LABEL(cpu_info_store) + CI_CURPCB
    123  1.19     bjh21 #else
    124  1.29   thorpej .Lcurlwp:
    125  1.29   thorpej 	.word	_C_LABEL(curlwp)
    126   1.1     chris 
    127  1.17   thorpej .Lcurpcb:
    128   1.1     chris 	.word	_C_LABEL(curpcb)
    129  1.22     bjh21 #endif
    130   1.1     chris 
    131  1.22     bjh21 #ifndef MULTIPROCESSOR
    132   1.1     chris 	.data
    133   1.1     chris 	.global	_C_LABEL(curpcb)
    134   1.1     chris _C_LABEL(curpcb):
    135   1.1     chris 	.word	0x00000000
    136   1.1     chris 	.text
    137  1.22     bjh21 #endif
    138   1.1     chris 
    139  1.57       scw .Lpmap_previous_active_lwp:
    140  1.57       scw 	.word	_C_LABEL(pmap_previous_active_lwp)
    141  1.30       scw 
    142   1.1     chris /*
    143  1.47      yamt  * struct lwp *
    144  1.47      yamt  * cpu_switchto(struct lwp *current, struct lwp *next)
    145  1.48     skrll  *
    146  1.47      yamt  * Switch to the specified next LWP
    147  1.47      yamt  * Arguments:
    148  1.16   thorpej  *
    149  1.29   thorpej  *	r0	'struct lwp *' of the current LWP
    150  1.47      yamt  *	r1	'struct lwp *' of the LWP to switch to
    151   1.1     chris  */
    152  1.47      yamt ENTRY(cpu_switchto)
    153  1.51     skrll 	mov	ip, sp
    154  1.51     skrll 	stmfd	sp!, {r4-r7, ip, lr}
    155   1.1     chris 
    156  1.55     chris 	/* move lwps and new pcb into caller saved registers */
    157  1.55     chris 	mov	r6, r1
    158  1.55     chris 	mov	r4, r0
    159  1.55     chris 	ldr	r7, [r6, #(L_ADDR)]
    160   1.7     chris 
    161  1.55     chris 	/* rem: r4 = old lwp */
    162  1.55     chris 	/* rem: r6 = new lwp */
    163  1.55     chris 	/* rem: r7 = new pcb */
    164  1.55     chris 
    165   1.1     chris 	IRQdisable
    166   1.7     chris 
    167  1.19     bjh21 #ifdef MULTIPROCESSOR
    168  1.19     bjh21 	/* XXX use curcpu() */
    169  1.19     bjh21 	ldr	r0, .Lcpu_info_store
    170  1.29   thorpej 	str	r0, [r6, #(L_CPU)]
    171  1.19     bjh21 #else
    172  1.29   thorpej 	/* l->l_cpu initialized in fork1() for single-processor */
    173  1.19     bjh21 #endif
    174   1.1     chris 
    175  1.55     chris 	/* We have a new curlwp and pcb so make a note of them */
    176  1.55     chris 	ldr	r0, .Lcurlwp
    177  1.55     chris 	ldr	r1, .Lcurpcb
    178  1.55     chris 
    179  1.55     chris 	str	r6, [r0]
    180  1.55     chris 	str	r7, [r1]
    181   1.1     chris 
    182   1.1     chris 	/* At this point we can allow IRQ's again. */
    183   1.1     chris 	IRQenable
    184   1.1     chris 
    185  1.47      yamt 	/* rem: r4 = old lwp */
    186  1.43     skrll 	/* rem: r6 = new lwp */
    187  1.55     chris 	/* rem: r7 = new pcb */
    188   1.4     chris 	/* rem: interrupts are enabled */
    189   1.1     chris 
    190   1.1     chris 	/*
    191  1.47      yamt 	 * If the old lwp on entry to cpu_switchto was zero then the
    192   1.1     chris 	 * process that called it was exiting. This means that we do
    193   1.1     chris 	 * not need to save the current context. Instead we can jump
    194   1.1     chris 	 * straight to restoring the context for the new process.
    195   1.1     chris 	 */
    196  1.47      yamt 	teq	r4, #0x00000000
    197  1.49       scw 	beq	.Ldo_switch
    198   1.1     chris 
    199  1.47      yamt 	/* rem: r4 = old lwp */
    200  1.43     skrll 	/* rem: r6 = new lwp */
    201  1.55     chris 	/* rem: r7 = new pcb */
    202   1.4     chris 	/* rem: interrupts are enabled */
    203   1.1     chris 
    204  1.48     skrll 	/* Save old context */
    205   1.1     chris 
    206  1.29   thorpej 	/* Get the user structure for the old lwp. */
    207  1.55     chris 	ldr	r5, [r4, #(L_ADDR)]
    208   1.1     chris 
    209  1.29   thorpej 	/* Save all the registers in the old lwp's pcb */
    210  1.37       scw #ifndef __XSCALE__
    211  1.55     chris 	add	r0, r5, #(PCB_R8)
    212  1.55     chris 	stmia	r0, {r8-r13}
    213  1.37       scw #else
    214  1.55     chris 	strd	r8, [r5, #(PCB_R8)]
    215  1.55     chris 	strd	r10, [r5, #(PCB_R10)]
    216  1.55     chris 	strd	r12, [r5, #(PCB_R12)]
    217  1.37       scw #endif
    218   1.1     chris 
    219   1.1     chris 	/*
    220  1.29   thorpej 	 * NOTE: We can now use r8-r13 until it is time to restore
    221  1.29   thorpej 	 * them for the new process.
    222  1.29   thorpej 	 */
    223  1.29   thorpej 
    224  1.47      yamt 	/* rem: r4 = old lwp */
    225  1.55     chris 	/* rem: r5 = old pcb */
    226  1.47      yamt 	/* rem: r6 = new lwp */
    227  1.55     chris 	/* rem: r7 = new pcb */
    228  1.47      yamt 	/* rem: interrupts are enabled */
    229  1.47      yamt 
    230  1.48     skrll 	/* What else needs to be saved? Only FPA stuff when that is supported */
    231  1.56  rearnsha #ifdef FPU_VFP
    232  1.56  rearnsha 	/*
    233  1.56  rearnsha 	 * Now's a good time to 'save' the VFP context.  Note that we
    234  1.56  rearnsha 	 * don't really force a save here, which can save time if we
    235  1.56  rearnsha 	 * end up restarting the same context.
    236  1.56  rearnsha 	 */
    237  1.56  rearnsha 	bl	_C_LABEL(vfp_savecontext)
    238  1.56  rearnsha #endif
    239   1.1     chris 
    240  1.48     skrll 	/* Restore saved context */
    241   1.1     chris 
    242  1.49       scw .Ldo_switch:
    243  1.47      yamt 	/* rem: r4 = old lwp */
    244  1.29   thorpej 	/* rem: r6 = new lwp */
    245  1.55     chris 	/* rem: r7 = new pcb */
    246  1.53     chris 	/* rem: interrupts are enabled */
    247  1.29   thorpej 
    248  1.57       scw 	ldr	r1, .Lpmap_previous_active_lwp
    249  1.55     chris 	ldr	r5, [r6, #(L_PROC)]	/* fetch the proc for below */
    250  1.55     chris 
    251  1.52     skrll 	/* Restore all the saved registers */
    252  1.37       scw #ifndef __XSCALE__
    253  1.55     chris 	add	r0, r7, #PCB_R8
    254  1.55     chris 	ldmia	r0, {r8-r13}
    255  1.37       scw #else
    256  1.37       scw 	ldr	r8, [r7, #(PCB_R8)]
    257  1.37       scw 	ldr	r9, [r7, #(PCB_R9)]
    258  1.37       scw 	ldr	r10, [r7, #(PCB_R10)]
    259  1.37       scw 	ldr	r11, [r7, #(PCB_R11)]
    260  1.37       scw 	ldr	r12, [r7, #(PCB_R12)]
    261  1.37       scw 	ldr	r13, [r7, #(PCB_SP)]
    262  1.37       scw #endif
    263  1.29   thorpej 
    264  1.57       scw 	/* Record the old lwp for pmap_activate()'s benefit */
    265  1.57       scw 	str	r4, [r1]
    266  1.57       scw 
    267  1.47      yamt 	/* rem: r4 = old lwp */
    268  1.29   thorpej 	/* rem: r5 = new lwp's proc */
    269  1.29   thorpej 	/* rem: r6 = new lwp */
    270  1.29   thorpej 	/* rem: r7 = new pcb */
    271  1.18   thorpej 
    272  1.56  rearnsha #ifdef FPU_VFP
    273  1.56  rearnsha 	mov	r0, r6
    274  1.56  rearnsha 	bl	_C_LABEL(vfp_loadcontext)
    275  1.56  rearnsha #endif
    276   1.1     chris #ifdef ARMFPE
    277  1.29   thorpej 	add	r0, r7, #(USER_SIZE) & 0x00ff
    278   1.1     chris 	add	r0, r0, #(USER_SIZE) & 0xff00
    279   1.1     chris 	bl	_C_LABEL(arm_fpe_core_changecontext)
    280   1.1     chris #endif
    281   1.1     chris 
    282  1.47      yamt 	/* rem: r4 = old lwp */
    283  1.29   thorpej 	/* rem: r5 = new lwp's proc */
    284  1.29   thorpej 	/* rem: r6 = new lwp */
    285  1.18   thorpej 	/* rem: r7 = new PCB */
    286  1.18   thorpej 
    287  1.18   thorpej 	/*
    288  1.18   thorpej 	 * Check for restartable atomic sequences (RAS).
    289  1.18   thorpej 	 */
    290  1.18   thorpej 
    291  1.39       dsl 	ldr	r2, [r5, #(P_RASLIST)]
    292  1.38       scw 	ldr	r1, [r7, #(PCB_TF)]	/* r1 = trapframe (used below) */
    293  1.18   thorpej 	teq	r2, #0			/* p->p_nras == 0? */
    294  1.18   thorpej 	bne	.Lswitch_do_ras		/* no, check for one */
    295  1.18   thorpej 
    296  1.14    briggs .Lswitch_return:
    297  1.47      yamt 	/* cpu_switchto returns the old lwp */
    298  1.29   thorpej 	mov	r0, r4
    299  1.47      yamt 	/* lwp_trampoline expects new lwp as it's second argument */
    300  1.47      yamt 	mov	r1, r6
    301   1.1     chris 
    302   1.1     chris 	/*
    303  1.51     skrll 	 * Pull the registers that got pushed when cpu_switchto() was called,
    304  1.51     skrll 	 * and return.
    305   1.1     chris 	 */
    306  1.51     skrll 	ldmfd	sp, {r4-r7, sp, pc}
    307  1.18   thorpej 
    308  1.18   thorpej .Lswitch_do_ras:
    309  1.38       scw 	ldr	r1, [r1, #(TF_PC)]	/* second ras_lookup() arg */
    310  1.29   thorpej 	mov	r0, r5			/* first ras_lookup() arg */
    311  1.18   thorpej 	bl	_C_LABEL(ras_lookup)
    312  1.18   thorpej 	cmn	r0, #1			/* -1 means "not in a RAS" */
    313  1.38       scw 	ldrne	r1, [r7, #(PCB_TF)]
    314  1.38       scw 	strne	r0, [r1, #(TF_PC)]
    315  1.18   thorpej 	b	.Lswitch_return
    316   1.1     chris 
    317  1.47      yamt ENTRY(lwp_trampoline)
    318  1.52     skrll 	/*
    319  1.52     skrll 	 * cpu_switchto gives us:
    320  1.52     skrll 	 *
    321  1.52     skrll 	 * arg0(r0) = old lwp
    322  1.52     skrll 	 * arg1(r1) = new lwp
    323  1.52     skrll 	 */
    324  1.47      yamt 	bl	_C_LABEL(lwp_startup)
    325  1.38       scw 
    326   1.1     chris 	mov	r0, r5
    327   1.1     chris 	mov	r1, sp
    328  1.24     bjh21 	mov	lr, pc
    329   1.1     chris 	mov	pc, r4
    330   1.1     chris 
    331   1.1     chris 	/* Kill irq's */
    332  1.13   thorpej         mrs     r0, cpsr
    333   1.1     chris         orr     r0, r0, #(I32_bit)
    334  1.13   thorpej         msr     cpsr_c, r0
    335   1.1     chris 
    336   1.1     chris 	PULLFRAME
    337   1.1     chris 
    338   1.1     chris 	movs	pc, lr			/* Exit */
    339