freebsd-skq/sys/sun4v/sun4v/swtch.S
marius 6cc2be150f Convert the remainder of the low hanging fruits regarding including
headers in .S directly rather than getting to their macros through
genassym.c/assym.s so there are less headers genassym.c has to be
kept in sync with.
While at it fix some stytle(9) bugs (indentation, prototype format,
sort headers, etc) and remove trailing whitespace.
2007-01-19 11:15:34 +00:00

258 lines
6.0 KiB
ArmAsm

/*-
* Copyright (c) 2001 Jake Burkholder.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <machine/asi.h>
#include <machine/asmacros.h>
#include <machine/fsr.h>
#include <machine/hypervisorvar.h>
#include <machine/ktr.h>
#include <machine/pcb.h>
#include <machine/tstate.h>
#include "assym.s"
.register %g2, #ignore
.register %g3, #ignore
#define PCB_REG %g6
#define MEMBAR_PRE membar #LoadStore|#StoreStore
#define MEMBAR_POST membar #LoadLoad
#define ATOMIC_CLEAR_INT_BIT(addr, old, bit, new, label) \
MEMBAR_PRE ; \
ld [addr], old ; \
label: andn old, bit, new ; \
cas [addr], old, new ; \
cmp old, new ; \
bne,a,pn %icc, label ## b ; \
ld [addr], old ; \
MEMBAR_POST
#define ATOMIC_SET_INT_BIT(addr, old, bit, new, label) \
MEMBAR_PRE ; \
ld [addr], old ; \
label: or old, bit, new ; \
cas [addr], old, new ; \
cmp old, new ; \
bne,a,pn %icc, label ## b ; \
ld [addr], old ; \
MEMBAR_POST
/*
* void cpu_throw(struct thread *old, struct thread *new)
*/
ENTRY(cpu_throw)
save %sp, -CCFSZ, %sp
flushw
ba %xcc, .Lsw1
mov %i1, %i0
END(cpu_throw)
/*
* void cpu_switch(struct thread *old, struct thread *new)
*/
ENTRY(cpu_switch)
save %sp, -CCFSZ, %sp
ldx [PCPU(CURPCB)], PCB_REG
mov %i1, %i0
/*
* If the current thread was using floating point in the kernel, save
* its context. The userland floating point context has already been
* saved in that case.
*/
rd %fprs, %l2
andcc %l2, FPRS_FEF, %g0
bz,a,pt %xcc, 1f
nop
call savefpctx
add PCB_REG, PCB_KFP, %o0
ba,a %xcc, 2f
nop
/*
* If the current thread was using floating point in userland, save
* its context.
*/
1: sub PCB_REG, TF_SIZEOF, %l2
ldx [%l2 + TF_FPRS], %l3
andcc %l3, FPRS_FEF, %g0
bz,a,pt %xcc, 2f
nop
call savefpctx
add PCB_REG, PCB_UFP, %o0
andn %l3, FPRS_FEF, %l3
stx %l3, [%l2 + TF_FPRS]
ldx [PCB_REG + PCB_FLAGS], %l3
or %l3, PCB_FEF, %l3
stx %l3, [PCB_REG + PCB_FLAGS]
/*
* Flush the windows out to the stack and save the current frame
* pointer and program counter.
*/
2: flushw
stx %fp, [PCB_REG + PCB_SP]
stx %i7, [PCB_REG + PCB_PC]
/*
* Load the new thread's frame pointer and program counter, and set
* the current thread and pcb.
*/
.Lsw1:
#if KTR_COMPILE & KTR_PROC & 0
CATR(KTR_PROC, "cpu_switch: new td=%p pc=%#lx fp=%#lx"
, %g1, %g2, %g3, 7, 8, 9)
stx %i0, [%g1 + KTR_PARM1]
ldx [%i0 + TD_PCB], %g2
ldx [%g2 + PCB_PC], %g3
stx %g3, [%g1 + KTR_PARM2]
ldx [%g2 + PCB_SP], %g3
stx %g3, [%g1 + KTR_PARM3]
9:
#endif
ldx [%i0 + TD_PCB], %i1
stx %i0, [PCPU(CURTHREAD)]
stx %i1, [PCPU(CURPCB)]
mov %i1, PCB_REG ! load in new PCB
ldx [PCB_REG + PCB_SP], %fp
ldx [PCB_REG + PCB_PC], %i7
sub %fp, CCFSZ, %sp
/*
* Point to the pmaps of the new process, and of the last non-kernel
* process to run.
*/
ldx [%i0 + TD_PROC], %i2
ldx [PCPU(PMAP)], %l2
ldx [%i2 + P_VMSPACE], %i5
add %i5, VM_PMAP, %i2
#if KTR_COMPILE & KTR_PROC & 0
CATR(KTR_PROC, "cpu_switch: new pmap=%p old pmap=%p"
, %g1, %g2, %g3, 7, 8, 9)
stx %i2, [%g1 + KTR_PARM1]
stx %l2, [%g1 + KTR_PARM2]
9:
#endif
/*
* If they are the same we are done.
*/
cmp %l2, %i2 ! current pmap == new pmap?
be,a,pn %xcc, 5f
nop
ldx [%i2 + PM_CONTEXT], %l5 ! new context
ldx [%l2 + PM_CONTEXT], %l3 ! old context
cmp %g0, %l5
be,pn %xcc, 5f ! new context == kernel?
ld [PCPU(CPUMASK)], %l4
brz %l3, 10f ! old context == kernel?
nop
/*
* Mark the old pmap as no longer active on this CPU
*/
add %l2, PM_ACTIVE, %l2
ATOMIC_CLEAR_INT_BIT(%l2, %l3, %l4, %l6, 8)
10:
add %i2, PM_ACTIVE, %i3
ATOMIC_SET_INT_BIT(%i3, %l3, %l4, %l6, 11)
add %i2, PM_TLBACTIVE, %i3
ATOMIC_SET_INT_BIT(%i3, %l3, %l4, %l6, 12)
mov SCRATCH_REG_HASH_USER, %l6
mov SCRATCH_REG_TSB_USER, %l7
ldx [%i2 + PM_HASHSCRATCH], %l3
ldx [%i2 + PM_TSBSCRATCH], %l4
stx %i2, [PCPU(PMAP)]
SET_SCRATCH(%l6,%l3) ! XXX we're assuming the
SET_SCRATCH(%l7,%l4) ! scratch values <= 32 bits
ldx [%i2 + PM_TSB_RA], %l3
mov MMU_CID_S, %l6
mov 1, %o0
mov %l3, %o1
mov MMU_TSB_CTXNON0, %o5
ta FAST_TRAP
cmp %g0, %o0
be %xcc, 4f
nop
MAGIC_TRAP_ON
MAGIC_EXIT
4: /*
* install the new secondary context number in the cpu.
*/
SET_MMU_CONTEXT(%l6, %l5)
membar #Sync
/*
* Done. Return and load the new process's window from the stack.
*/
5: ret
restore
END(cpu_switch)
ENTRY(savectx)
save %sp, -CCFSZ, %sp
flushw
call savefpctx
add %i0, PCB_UFP, %o0
stx %fp, [%i0 + PCB_SP]
stx %i7, [%i0 + PCB_PC]
ret
restore %g0, 0, %o0
END(savectx)
/*
* void savefpctx(uint32_t *);
*/
ENTRY(savefpctx)
wr %g0, FPRS_FEF, %fprs
std %f0, [%o0 + (0 * 64)]
std %f16, [%o0 + (1 * 64)]
std %f32, [%o0 + (2 * 64)]
std %f48, [%o0 + (3 * 64)]
retl
wr %g0, 0, %fprs
END(savefpctx)