source: trunk/hal/tsar_mips32/hal_context.c @ 3

Last change on this file since 3 was 1, checked in by alain, 8 years ago

First import

File size: 13.7 KB
Line 
1/*
2 * hal_context.c - implementation of Thread Context API for TSAR-MIPS32
3 *
4 * Author  Alain Greiner    (2016)
5 *
6 * Copyright (c)  UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH.is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_types.h>
25#include <memcpy.h>
26#include <thread.h>
27#include <string.h>
28#include <process.h>
29#include <vmm.h>
30#include <core.h>
31#include <cluster.h>
32
33#include <hal_context.h>
34
35//////////////////////////////////////////////////////////
36error_t hal_cpu_context_create( struct thread_s * thread )
37{
38    kmem_req_t  req;
39
40    // allocate memory for cpu_context
41    req.type   = KMEM_GENERIC;
42    req.size   = sizeof(hal_cpu_context_t);
43    req.flags  = AF_KERNEL | AF_ZERO;
44
45    hal_cpu_context_t * context = (hal_cpu_context_t *)kmem_alloc( &req );
46    if( context == NULL ) return ENOMEM;
47
48    // set cpu context pointer in thread
49    thread->cpu_context = (void*)context;
50
51    // stack pointer, status register and mmu_mode depends on thread type
52        uint32_t sp_29;
53    uint32_t c0_sr;
54    uint32_t c2_mode;
55    if( thread->type == THREAD_USER )
56    {
57        sp_29   = ((uint32_t)thread->u_stack_base) + thread->u_stack_size;
58        c0_sr   = SR_USR_MODE;
59        c2_mode = 0xF;
60    }
61    else
62    {
63        sp_29   = ((uint32_t)thread->k_stack_base) + thread->k_stack_size;
64        c0_sr   = SR_SYS_MODE;
65        c2_mode = 0x3;
66    }
67
68    // align stack pointer on a double word boundary
69        sp_29 = (sp_29 - 8) & (~ 0x7);
70
71    // initialise context
72        context->sp_29      = sp_29; 
73        context->fp_30      = sp_29;                          // TODO check this [AG]
74    context->ra_31      = (uint32_t)thread->entry_func;
75        context->c0_sr      = c0_sr;
76        context->c0_th      = (uint32_t)thread; 
77        context->c2_ptpr    = (uint32_t)((thread->process->vmm.gpt.ppn) >> 1);
78        context->c2_mode    = c2_mode;
79
80    return 0;
81}  // end hal_cpu_context_create()
82
83/////////////////////////////////////////////
84error_t hal_cpu_context_copy( thread_t * dst,
85                              thread_t * src )
86{
87    kmem_req_t  req;
88
89    // allocate memory for dst cpu_context
90    req.type   = KMEM_GENERIC;
91    req.size   = sizeof(hal_cpu_context_t);
92    req.flags  = AF_KERNEL | AF_ZERO;
93
94    hal_cpu_context_t * dst_context = (hal_cpu_context_t *)kmem_alloc( &req );
95    if( dst_context == NULL ) return ENOMEM;
96
97    // set cpu context pointer in dst thread
98    dst->cpu_context = dst_context;
99
100    // get cpu context pointer from src thread
101    hal_cpu_context_t * src_context = src->cpu_context;
102
103    // copy CPU context from src to dst
104    memcpy( dst_context , src_context , sizeof(hal_cpu_context_t) );
105
106    return 0;
107}  // end hal_cpu_context_copy()
108
109/////////////////////////////////////////////////
110void hal_cpu_context_destroy( thread_t * thread )
111{
112    kmem_req_t  req;
113
114    req.type = KMEM_GENERIC;
115    req.ptr  = thread->cpu_context;
116    kmem_free( &req );
117
118}  // end hal_cpu_context_destroy()
119
120///////////////////////////////////////////////////
121error_t hal_fpu_context_create( thread_t * thread )
122{
123    kmem_req_t  req;
124
125    // allocate memory for uzone
126    req.type   = KMEM_GENERIC;
127    req.size   = sizeof(hal_fpu_context_t);
128    req.flags  = AF_KERNEL | AF_ZERO;
129
130    hal_fpu_context_t * context = (hal_fpu_context_t *)kmem_alloc( &req );
131    if( context == NULL ) return ENOMEM;
132
133    // set fpu context pointer in thread
134    thread->fpu_context = (void*)context;
135   
136    return 0;
137}  // hal_fpu_context_create()
138
139/////////////////////////////////////////////
140error_t hal_fpu_context_copy( thread_t * dst,
141                              thread_t * src )
142{
143    kmem_req_t  req;
144
145    // allocate memory for dst fpu_context
146    req.type   = KMEM_GENERIC;
147    req.size   = sizeof(hal_fpu_context_t);
148    req.flags  = AF_KERNEL | AF_ZERO;
149
150    hal_fpu_context_t * dst_context = (hal_fpu_context_t *)kmem_alloc( &req );
151    if( dst_context == NULL ) return ENOMEM;
152
153    // set fpu context pointer in dst thread
154    dst->fpu_context = (void*)dst_context;
155
156    // get fpu context pointer from src thread
157    hal_fpu_context_t * src_context = src->fpu_context;
158
159    // copy CPU context from src to dst
160    memcpy( dst_context , src_context , sizeof(hal_fpu_context_t) );
161
162    return 0;
163}  // end hal_fpu_context_copy()
164
165/////////////////////////////////////////////////
166void hal_fpu_context_destroy( thread_t * thread )
167{
168    kmem_req_t  req;
169
170    req.type = KMEM_GENERIC;
171    req.ptr  = thread->fpu_context;
172    kmem_free( &req );
173
174}  // end hal_fpu_context_destroy()
175
176//////////////////////////////////////////////     
177void hal_cpu_context_save( thread_t * thread )
178{
179    uint32_t ctx = (uint32_t)thread->cpu_context;
180
181    asm volatile(
182    ".set noreorder                \n" 
183    "sw      $16,   0*4(%0)        \n"   /* save s0 to slot 0                   */
184    "sw      $17,   1*4(%0)        \n"   /* save s1 to slot 1                   */
185    "sw      $18,   2*4(%0)        \n"   /* save s2 to slot 2                   */
186    "sw      $19,   3*4(%0)        \n"   /* save s3 to slot 3                   */
187    "sw      $20,   4*4(%0)        \n"   /* save s4 to slot 4                   */
188    "sw      $21,   5*4(%0)        \n"   /* save s5 to slot 5                   */
189    "sw      $22,   6*4(%0)        \n"   /* save s6 to slot 6                   */
190    "sw      $23,   7*4(%0)        \n"   /* save s7 to slot 7                   */
191    "sw      $29,   8*4(%0)        \n"   /* save sp to slot 8                   */
192    "sw      $30,   9*4(%0)        \n"   /* save fp to slot 9                   */
193    "sw      $31,   10*4(%0)       \n"   /* save ra to slot 10                  */
194    "mfc0        $26,   $4,       2        \n"   /* get c0_th from CP0                  */
195        "sw      $26,   12*4(%0)       \n"   /* save c0_th to slot 12               */
196        "mfc2    $26,   $0             \n"   /* get c2_ptpr from CP2                */
197        "sw      $26,   13*4(%0)       \n"   /* save c2_ptpr to slot 13             */
198        "mfc2    $26,   $1             \n"   /* get c2_mod from CP2                 */
199        "sw      $26,   14*4(%0)       \n"   /* save c2_mode to slot 14             */
200    "sync                          \n"
201        ".set reorder                  \n"
202    : : "r"( ctx ) : "$26" , "memory" ); 
203}
204
205/////////////////////////////////////////////////     
206void hal_cpu_context_restore( thread_t * thread )
207{
208    uint32_t ctx = (uint32_t)thread->cpu_context;
209
210    asm volatile(
211    ".set noreorder                \n"
212    "nop                           \n"
213        "lw      $16,  0*4(%0)         \n"   /* restore s0_16                       */
214        "lw      $17,  1*4(%0)         \n"   /* restore s1_17                       */
215    "lw      $18,  2*4(%0)         \n"   /* restore s2_18                       */
216    "lw      $19,  3*4(%0)         \n"   /* restore s3_19                       */
217    "lw      $20,  4*4(%0)         \n"   /* restore s4_20                       */
218    "lw      $21,  5*4(%0)         \n"   /* restore s5_21                       */
219    "lw      $22,  6*4(%0)         \n"   /* restore s6_22                       */
220    "lw      $23,  7*4(%0)         \n"   /* restore s7_23                       */
221        "lw      $29,  8*4(%0)         \n"   /* restore sp_29                       */ 
222        "lw      $30,  9*4(%0)         \n"   /* restore fp_30                       */
223        "lw      $31,  10*4(%0)        \n"   /* restore ra_31                       */
224    "lw      $26,  12*4(%0)        \n"   /* get c0_th from slot 12              */
225        "mtc0    $26,  $4,    2        \n"   /* restore c0_th                       */
226    "lw      $26,  13*4(%0)        \n"   /* get c2_ptpr from slot 13            */
227        "mtc2    $26,  $0              \n"   /* restore c2_ptpr                     */
228    "lw      $26,  14*4(%0)        \n"   /* get c2_mode from slot 14            */
229        "mtc2    $26,  $1              \n"   /* restore c2_mode                     */
230    ".set reorder                  \n"
231    : : "r"(ctx)
232      : "$16","$17","$18","$19","$20","$21","$22","$23","$26","$29","$30","$31" ); 
233}
234
235//////////////////////////////////////////////
236void hal_cpu_context_load( thread_t * thread )
237{
238    // get relevant values from thread context
239    hal_cpu_context_t * ctx     = (hal_cpu_context_t *)thread->cpu_context;     
240    uint32_t            sp_29   = ctx->sp_29;
241    uint32_t            fp_30   = ctx->fp_30;
242    uint32_t            c0_th   = ctx->c0_th;
243    uint32_t            c0_sr   = ctx->c0_sr;
244    uint32_t            c2_ptpr = ctx->c2_ptpr;
245    uint32_t            c2_mode = ctx->c2_mode;
246 
247    // get pointer on entry function & argument from thread attributes
248    uint32_t            func    = (uint32_t)thread->entry_func;
249    uint32_t            args    = (uint32_t)thread->entry_args;
250
251    // reset loadable field in thread descriptor
252    thread->flags &= ~THREAD_FLAG_LOADABLE;
253
254    // load registers
255    asm volatile(
256    ".set noreorder                \n"
257        "or       $26,    %0,    $0    \n"   /* $26 <= stack pointer                */
258        "or       $27,    %2,    $0    \n"   /* $27 <= status register              */
259        "addiu    $26,    $26,  -4     \n"   /* decrement stack pointer             */
260        "or       $4,     %7,   $0     \n"   /* load a0                             */
261        "sw       $4,     ($26)        \n"   /* set entry_args in stack             */
262        "ori      $27,    $27,  0x2    \n"   /* set EXL flag in status register     */
263        "mtc0     $27,    $12          \n"   /* load c0_sr                          */
264        "mtc0     %3,     $4,    2     \n"   /* load c0_th                          */
265        "mtc2     %4,     $0           \n"   /* load c2 ptpr                        */
266        "mtc0     %6,     $14          \n"   /* load c0_epc                         */
267        "or           $29,        $16,  $0     \n"   /* load sp_29                          */
268        "or           $30,        %1,   $0     \n"   /* load fp_30                          */
269    "mtc2     %5,     $1           \n"   /* load c2_mode                        */
270    "nop                           \n"
271    "eret                          \n"   /* jump to user code                   */
272    "nop                           \n"
273    ".set reorder                  \n"
274    : 
275    : "r"(sp_29),"r"(fp_30),"r"(c0_sr),"r"(c0_th),
276      "r"(c2_ptpr),"r"(c2_mode),"r"(func),"r"(args)
277    : "$4","$26","$27","$29","$30" );
278
279}  // end hal_cpu_context_load()
280
281
282//////////////////////////////////////////////
283void hal_fpu_context_save( thread_t * thread )
284{
285    uint32_t ctx = (uint32_t)thread->fpu_context;
286
287    asm volatile(
288    ".set noreorder           \n"
289    "swc1    $f0,    0*4(%0)  \n"   
290    "swc1    $f1,    1*4(%0)  \n"   
291    "swc1    $f2,    2*4(%0)  \n"   
292    "swc1    $f3,    3*4(%0)  \n"   
293    "swc1    $f4,    4*4(%0)  \n"   
294    "swc1    $f5,    5*4(%0)  \n"   
295    "swc1    $f6,    6*4(%0)  \n"   
296    "swc1    $f7,    7*4(%0)  \n"   
297    "swc1    $f8,    8*4(%0)  \n"   
298    "swc1    $f9,    9*4(%0)  \n"   
299    "swc1    $f10,  10*4(%0)  \n"   
300    "swc1    $f11,  11*4(%0)  \n"   
301    "swc1    $f12,  12*4(%0)  \n"   
302    "swc1    $f13,  13*4(%0)  \n"   
303    "swc1    $f14,  14*4(%0)  \n"   
304    "swc1    $f15,  15*4(%0)  \n"   
305    "swc1    $f16,  16*4(%0)  \n"   
306    "swc1    $f17,  17*4(%0)  \n"   
307    "swc1    $f18,  18*4(%0)  \n"   
308    "swc1    $f19,  19*4(%0)  \n"   
309    "swc1    $f20,  20*4(%0)  \n"   
310    "swc1    $f21,  21*4(%0)  \n"   
311    "swc1    $f22,  22*4(%0)  \n"   
312    "swc1    $f23,  23*4(%0)  \n"   
313    "swc1    $f24,  24*4(%0)  \n"   
314    "swc1    $f25,  25*4(%0)  \n"   
315    "swc1    $f26,  26*4(%0)  \n"   
316    "swc1    $f27,  27*4(%0)  \n"   
317    "swc1    $f28,  28*4(%0)  \n"   
318    "swc1    $f29,  29*4(%0)  \n"   
319    "swc1    $f30,  30*4(%0)  \n"   
320    "swc1    $f31,  31*4(%0)  \n"   
321    ".set reorder             \n"
322    : : "r"(ctx) );
323
324}  // end hal_cpu_context_save()
325
326/////////////////////////////////////////////////
327void hal_fpu_context_restore( thread_t * thread )
328{
329    uint32_t ctx = (uint32_t)thread->fpu_context;
330
331    asm volatile(
332    ".set noreorder           \n"
333    "lwc1    $f0,    0*4(%0)  \n"   
334    "lwc1    $f1,    1*4(%0)  \n"   
335    "lwc1    $f2,    2*4(%0)  \n"   
336    "lwc1    $f3,    3*4(%0)  \n"   
337    "lwc1    $f4,    4*4(%0)  \n"   
338    "lwc1    $f5,    5*4(%0)  \n"   
339    "lwc1    $f6,    6*4(%0)  \n"   
340    "lwc1    $f7,    7*4(%0)  \n"   
341    "lwc1    $f8,    8*4(%0)  \n"   
342    "lwc1    $f9,    9*4(%0)  \n"   
343    "lwc1    $f10,  10*4(%0)  \n"   
344    "lwc1    $f11,  11*4(%0)  \n"   
345    "lwc1    $f12,  12*4(%0)  \n"   
346    "lwc1    $f13,  13*4(%0)  \n"   
347    "lwc1    $f14,  14*4(%0)  \n"   
348    "lwc1    $f15,  15*4(%0)  \n"   
349    "lwc1    $f16,  16*4(%0)  \n"   
350    "lwc1    $f17,  17*4(%0)  \n"   
351    "lwc1    $f18,  18*4(%0)  \n"   
352    "lwc1    $f19,  19*4(%0)  \n"   
353    "lwc1    $f20,  20*4(%0)  \n"   
354    "lwc1    $f21,  21*4(%0)  \n"   
355    "lwc1    $f22,  22*4(%0)  \n"   
356    "lwc1    $f23,  23*4(%0)  \n"   
357    "lwc1    $f24,  24*4(%0)  \n"   
358    "lwc1    $f25,  25*4(%0)  \n"   
359    "lwc1    $f26,  26*4(%0)  \n"   
360    "lwc1    $f27,  27*4(%0)  \n"   
361    "lwc1    $f28,  28*4(%0)  \n"   
362    "lwc1    $f29,  29*4(%0)  \n"   
363    "lwc1    $f30,  30*4(%0)  \n"   
364    "lwc1    $f31,  31*4(%0)  \n"   
365    ".set reorder             \n"
366    : : "r"(ctx) );
367
368} // end hal_cpu_context_restore()
369
370/////////////////////////////////////
371void hal_fpu_context_dup( xptr_t dst,
372                          xptr_t src )
373{
374        hal_remote_memcpy( dst , src , sizeof(hal_fpu_context_t) );
375}
376
Note: See TracBrowser for help on using the repository browser.