xref: /reactos/ntoskrnl/ke/arm/ctxswtch.s (revision c2c66aff)
1*c2c66affSColin Finck/*
2*c2c66affSColin Finck * PROJECT:         ReactOS Kernel
3*c2c66affSColin Finck * LICENSE:         BSD - See COPYING.ARM in the top level directory
4*c2c66affSColin Finck * FILE:            ntoskrnl/ke/arm/ctxswtch.s
5*c2c66affSColin Finck * PURPOSE:         Context Switch and Idle Thread on ARM
6*c2c66affSColin Finck * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
7*c2c66affSColin Finck *                  ReactOS Portable Systems Group
8*c2c66affSColin Finck */
9*c2c66affSColin Finck
10*c2c66affSColin Finck#include <ksarm.h>
11*c2c66affSColin Finck
12*c2c66affSColin Finck    IMPORT KeLowerIrql
13*c2c66affSColin Finck
14*c2c66affSColin Finck    TEXTAREA
15*c2c66affSColin Finck
16*c2c66affSColin Finck/*!
17*c2c66affSColin Finck * \name KiSwapContextInternal
18*c2c66affSColin Finck *
19*c2c66affSColin Finck * \brief
20*c2c66affSColin Finck *     The KiSwapContextInternal routine switches context to another thread.
21*c2c66affSColin Finck *
22*c2c66affSColin Finck * \param r0
23*c2c66affSColin Finck *     Pointer to the KTHREAD to which the caller wishes to switch to.
24*c2c66affSColin Finck *
25*c2c66affSColin Finck * \param r1
26*c2c66affSColin Finck *     Pointer to the KTHREAD to which the caller wishes to switch from.
27*c2c66affSColin Finck *
28*c2c66affSColin Finck * \param r2
29*c2c66affSColin Finck *     APC bypass
30*c2c66affSColin Finck *
31*c2c66affSColin Finck * \return
32*c2c66affSColin Finck *     None.
33*c2c66affSColin Finck *
34*c2c66affSColin Finck * \remarks
35*c2c66affSColin Finck *     ...
36*c2c66affSColin Finck *
37*c2c66affSColin Finck *--*/
38*c2c66affSColin Finck    NESTED_ENTRY KiSwapContextInternal
39*c2c66affSColin Finck
40*c2c66affSColin Finck    /* Push a KSWITCH_FRAME on the stack */
41*c2c66affSColin Finck    stmdb sp!,{r2,r3,r11,lr} // FIXME: what is the 2nd field?
42*c2c66affSColin Finck    // PROLOG_PUSH {r2,r3,r11,lr}
43*c2c66affSColin Finck
44*c2c66affSColin Finck    PROLOG_END KiSwapContextInternal
45*c2c66affSColin Finck
46*c2c66affSColin Finck    /* Save kernel stack of old thread */
47*c2c66affSColin Finck    str sp, [r1, #ThKernelStack]
48*c2c66affSColin Finck
49*c2c66affSColin Finck    /* Save new thread in R11 */
50*c2c66affSColin Finck    mov r11, r0
51*c2c66affSColin Finck
52*c2c66affSColin Finck    //bl KiSwapContextSuspend
53*c2c66affSColin Finck    __debugbreak
54*c2c66affSColin Finck
55*c2c66affSColin Finck    /* Load stack of new thread */
56*c2c66affSColin Finck    ldr sp, [r11, #ThKernelStack]
57*c2c66affSColin Finck
58*c2c66affSColin Finck    /* Reload APC bypass */
59*c2c66affSColin Finck    ldr r2, [sp, #SwApcBypass]
60*c2c66affSColin Finck
61*c2c66affSColin Finck    //bl KiSwapContextResume
62*c2c66affSColin Finck    __debugbreak
63*c2c66affSColin Finck
64*c2c66affSColin Finck    /* Restore R2, R11 and return */
65*c2c66affSColin Finck    ldmia sp!,{r2,r3,r11,pc}
66*c2c66affSColin Finck
67*c2c66affSColin Finck    NESTED_END KiSwapContextInternal
68*c2c66affSColin Finck
69*c2c66affSColin Finck
70*c2c66affSColin Finck/*!
71*c2c66affSColin Finck * KiSwapContext
72*c2c66affSColin Finck *
73*c2c66affSColin Finck * \brief
74*c2c66affSColin Finck *     The KiSwapContext routine switches context to another thread.
75*c2c66affSColin Finck *
76*c2c66affSColin Finck * BOOLEAN
77*c2c66affSColin Finck * KiSwapContext(
78*c2c66affSColin Finck *     _In_ KIRQL WaitIrql,
79*c2c66affSColin Finck *     _Inout_ PKTHREAD CurrentThread);
80*c2c66affSColin Finck *
81*c2c66affSColin Finck * \param WaitIrql <r0>
82*c2c66affSColin Finck *     ...
83*c2c66affSColin Finck *
84*c2c66affSColin Finck * \param CurrentThread <r1>
85*c2c66affSColin Finck *     Pointer to the KTHREAD of the current thread.
86*c2c66affSColin Finck *
87*c2c66affSColin Finck * \return
88*c2c66affSColin Finck *     The WaitStatus of the Target Thread.
89*c2c66affSColin Finck *
90*c2c66affSColin Finck * \remarks
91*c2c66affSColin Finck *     This is a wrapper around KiSwapContextInternal which will save all the
92*c2c66affSColin Finck *     non-volatile registers so that the Internal function can use all of
93*c2c66affSColin Finck *     them. It will also save the old current thread and set the new one.
94*c2c66affSColin Finck *
95*c2c66affSColin Finck *     The calling thread does not return after KiSwapContextInternal until
96*c2c66affSColin Finck *     another thread switches to it.
97*c2c66affSColin Finck *
98*c2c66affSColin Finck *--*/
99*c2c66affSColin Finck    NESTED_ENTRY KiSwapContext
100*c2c66affSColin Finck
101*c2c66affSColin Finck    /* Push non-volatiles and return address on the stack */
102*c2c66affSColin Finck    stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,lr}
103*c2c66affSColin Finck    // PROLOG_PUSH {r4,r5,r6,r7,r8,r9,r10,r11,lr}
104*c2c66affSColin Finck
105*c2c66affSColin Finck    PROLOG_END KiSwapContext
106*c2c66affSColin Finck
107*c2c66affSColin Finck    /* Do the swap with the registers correctly setup */
108*c2c66affSColin Finck    mov32 r0, 0xFFDFF000 // FIXME: properly load the PCR into r0 (PCR should be in CP15, c3, TPIDRPRW)
109*c2c66affSColin Finck    ldr r0, [r0, #PcCurrentThread] /* Pointer to the new thread */
110*c2c66affSColin Finck    bl KiSwapContextInternal
111*c2c66affSColin Finck
112*c2c66affSColin Finck    /* Restore non-volatiles and return */
113*c2c66affSColin Finck    ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
114*c2c66affSColin Finck
115*c2c66affSColin Finck    NESTED_END KiSwapContext
116*c2c66affSColin Finck
117*c2c66affSColin Finck
118*c2c66affSColin Finck
119*c2c66affSColin Finck    NESTED_ENTRY KiThreadStartup
120*c2c66affSColin Finck    PROLOG_END KiThreadStartup
121*c2c66affSColin Finck
122*c2c66affSColin Finck    /* Lower IRQL to APC_LEVEL */
123*c2c66affSColin Finck    mov a1, #1
124*c2c66affSColin Finck    bl KeLowerIrql
125*c2c66affSColin Finck
126*c2c66affSColin Finck    /* Set the start address and startup context */
127*c2c66affSColin Finck    mov a1, r6
128*c2c66affSColin Finck    mov a2, r5
129*c2c66affSColin Finck    blx r7
130*c2c66affSColin Finck
131*c2c66affSColin Finck    /* The function must not return! */
132*c2c66affSColin Finck    __assertfail
133*c2c66affSColin Finck
134*c2c66affSColin Finck    NESTED_END KiThreadStartup
135*c2c66affSColin Finck
136*c2c66affSColin Finck
137*c2c66affSColin Finck    NESTED_ENTRY KiSwitchThreads
138*c2c66affSColin Finck    PROLOG_END KiSwitchThreads
139*c2c66affSColin Finck
140*c2c66affSColin Finck	// UNIMPLEMENTED!
141*c2c66affSColin Finck	__debugbreak
142*c2c66affSColin Finck
143*c2c66affSColin Finck    NESTED_END KiSwitchThreads
144*c2c66affSColin Finck
145*c2c66affSColin Finck    END
146*c2c66affSColin Finck/* EOF */
147