source: trunk/hal/tsar_mips32/core/hal_context.c @ 349

Last change on this file since 349 was 317, checked in by alain, 7 years ago

1) Introduce the TSAR hal_cpu_context_switch() function.
2) Introduce the generic vfs_kernel_move() function.

File size: 19.4 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 <hal_switch.h>
26#include <memcpy.h>
27#include <thread.h>
28#include <string.h>
29#include <process.h>
30#include <printk.h>
31#include <vmm.h>
32#include <core.h>
33#include <cluster.h>
34#include <hal_context.h>
35
36/////////////////////////////////////////////////////////////////////////////////////////
37//       Define various SR values for TSAR-MIPS32
38/////////////////////////////////////////////////////////////////////////////////////////
39
40#define SR_USR_MODE       0xFC11
41#define SR_USR_MODE_FPU   0x2000FC11
42#define SR_SYS_MODE       0xFC00
43
44/////////////////////////////////////////////////////////////////////////////////////////
45// These structuree defines the cpu_context anf fpu_context for TSAR MIPS32.
46// These registers are saved/restored at each context switch.
47// WARNING : update the hal_***_context_save() and hal_***_context_restore()
48//           functions when modifying this structure, and check the two
49//           CONFIG_CPU_CTX_SIZE & CONFIGFPU_CTX_SIZE configuration parameterss.
50/////////////////////////////////////////////////////////////////////////////////////////
51
52typedef struct hal_cpu_context_s
53{
54    uint32_t c0_epc;     // slot 0
55    uint32_t at_01;      // slot 1
56    uint32_t v0_02;      // slot 2
57    uint32_t v1_03;      // slot 3
58    uint32_t a0_04;      // slot 4
59    uint32_t a1_05;      // slot 5
60    uint32_t a2_06;      // slot 6
61    uint32_t a3_07;      // slot 7
62
63    uint32_t t0_08;      // slot 8
64    uint32_t t1_09;      // slot 9
65    uint32_t t2_10;      // slot 10
66    uint32_t t3_11;      // slot 11
67    uint32_t t4_12;      // slot 12
68    uint32_t t5_13;      // slot 13
69    uint32_t t6_14;      // slot 14
70    uint32_t t7_15;      // slot 15
71
72        uint32_t s0_16;      // slot 16
73        uint32_t s1_17;      // slot 17
74        uint32_t s2_18;      // slot 18
75        uint32_t s3_19;      // slot 19
76        uint32_t s4_20;      // slot 20
77        uint32_t s5_21;      // slot 21
78        uint32_t s6_22;      // slot 22
79        uint32_t s7_23;      // slot 23
80
81    uint32_t t8_24;      // slot 24
82    uint32_t t8_25;      // slot 25
83    uint32_t hi_26;      // slot 26
84    uint32_t lo_27;      // slot 27
85    uint32_t gp_28;      // slot 28
86        uint32_t sp_29;      // slot 29
87        uint32_t fp_30;      // slot 30
88        uint32_t ra_31;      // slot 31
89
90        uint32_t c2_ptpr;    // slot 32
91        uint32_t c2_mode;    // slot 33
92
93        uint32_t c0_sr;      // slot 34
94        uint32_t c0_th;      // slot 35
95} 
96hal_cpu_context_t;
97
98/////////////////////////////////////////////////////////////////////////////////////////
99// This structure defines the fpu_context for TSAR MIPS32.
100/////////////////////////////////////////////////////////////////////////////////////////
101
102typedef struct hal_fpu_context_s
103{
104        uint32_t   fpu_regs[32];     
105}
106hal_fpu_context_t;
107
108
109
110/////////////////////////////////////////////////////////////////////////////////////////
111//        CPU context access functions
112/////////////////////////////////////////////////////////////////////////////////////////
113
114
115/////////////////////////////////////////////////////////////////////////////////////////
116// Seven registers are initialised by this function:
117// GPR : sp_29 / fp_30 / ra_31
118// CP0 : c0_sr / c0_th
119// CP2 : c2_ptpr / c2_mode
120/////////////////////////////////////////////////////////////////////////////////////////
121error_t hal_cpu_context_create( thread_t * thread )
122{
123    kmem_req_t  req;
124
125    context_dmsg("\n[INFO] %s : enters for thread %x in process %x\n",
126                 __FUNCTION__ , thread->trdid , thread->process->pid );
127
128    // allocate memory for cpu_context
129    req.type   = KMEM_CPU_CTX;
130    req.size   = sizeof(hal_cpu_context_t);
131    req.flags  = AF_KERNEL | AF_ZERO;
132
133    hal_cpu_context_t * context = (hal_cpu_context_t *)kmem_alloc( &req );
134    if( context == NULL ) return ENOMEM;
135
136    // set cpu context pointer in thread
137    thread->cpu_context = (void*)context;
138
139    // stack pointer, status register and mmu_mode depends on thread type
140        uint32_t sp_29;
141    uint32_t c0_sr;
142    uint32_t c2_mode;
143    if( thread->type == THREAD_USER )
144    {
145        sp_29   = ((uint32_t)thread->u_stack_base) + thread->u_stack_size;
146        c0_sr   = SR_USR_MODE;
147        c2_mode = 0xF;
148    }
149    else
150    {
151        sp_29   = ((uint32_t)thread->k_stack_base) + thread->k_stack_size;
152        c0_sr   = SR_SYS_MODE;
153        c2_mode = 0x3;
154    }
155
156    // align stack pointer on a double word boundary
157        sp_29 = (sp_29 - 8) & (~ 0x7);
158
159    // initialise context
160        context->sp_29      = sp_29; 
161        context->fp_30      = sp_29;                          // TODO check this [AG]
162    context->ra_31      = (uint32_t)thread->entry_func;
163        context->c0_sr      = c0_sr;
164        context->c0_th      = (uint32_t)thread; 
165        context->c2_ptpr    = (uint32_t)((thread->process->vmm.gpt.ppn) >> 1);
166        context->c2_mode    = c2_mode;
167
168    context_dmsg("\n[INFO] %s : exit for thread %x in process %x / ra = %x\n",
169                 __FUNCTION__ , thread->trdid , thread->process->pid , context->ra_31 );
170
171    return 0;
172}  // end hal_cpu_context_create()
173
174/////////////////////////////////////////////////
175void hal_cpu_context_display( thread_t * thread )
176{
177    hal_cpu_context_t * ctx = (hal_cpu_context_t *)thread->cpu_context;
178
179    printk("\n***** cpu_context for thread %x in cluster %x / ctx = %x\n" 
180           " gp_28   = %X    sp_29   = %X    ra_31   = %X\n" 
181           " c0_sr   = %X    c0_epc  = %X    c0_th = %X\n"
182           " c2_ptpr = %X    c2_mode = %X\n",
183           thread->trdid, local_cxy, ctx,
184           ctx->gp_28   , ctx->sp_29   , ctx->ra_31,
185           ctx->c0_sr   , ctx->c0_epc  , ctx->c0_th,
186           ctx->c2_ptpr , ctx->c2_mode );
187
188}  // end hal_context_display()
189
190/*
191////////////////////////////////////////////////////////////////////////////////////////
192// This static function makes the actual context switch.   
193////////////////////////////////////////////////////////////////////////////////////////
194static void hal_do_switch( hal_cpu_context_t * ctx_old,
195                           hal_cpu_context_t * ctx_new )
196{
197    asm volatile(
198    ".set noat                       \n"
199    ".set noreorder                  \n"
200    "move    $26,   %0               \n"
201
202    "mfc0    $27,   $14              \n"
203    "sw      $27,   0*4($26)         \n"
204 
205    "sw      $1,    1*4($26)         \n"
206    "sw      $2,    2*4($26)         \n"
207    "sw      $3,    3*4($26)         \n"
208    "sw      $4,    4*4($26)         \n"
209    "sw      $5,    5*4($26)         \n"
210    "sw      $6,    6*4($26)         \n"
211    "sw      $7,    7*4($26)         \n"
212
213    "sw      $8,    8*4($26)         \n"
214    "sw      $9,    9*4($26)         \n"
215    "sw      $10,  10*4($26)         \n"
216    "sw      $11,  11*4($26)         \n"
217    "sw      $12,  12*4($26)         \n"
218    "sw      $13,  13*4($26)         \n"
219    "sw      $14,  14*4($26)         \n"
220    "sw      $15,  15*4($26)         \n"
221
222    "sw      $16,  16*4($26)         \n"
223    "sw      $17,  17*4($26)         \n"
224    "sw      $18,  18*4($26)         \n"
225    "sw      $19,  19*4($26)         \n"
226    "sw      $20,  20*4($26)         \n"
227    "sw      $21,  21*4($26)         \n"
228    "sw      $22,  22*4($26)         \n"
229    "sw      $23,  23*4($26)         \n"
230
231    "sw      $24,  24*4($26)         \n"
232    "sw      $25,  25*4($26)         \n"
233
234    "mfhi    $27                     \n"
235    "sw      $27,  26*4($26)         \n"
236    "mflo    $27                     \n"
237    "sw      $27,  27*4($26)         \n"
238
239    "sw      $28,  28*4($26)         \n"
240    "sw      $29,  29*4($26)         \n"
241    "sw      $30,  30*4($26)         \n"
242    "sw      $31,  31*4($26)         \n"
243
244        "mfc2    $27,  $0                \n"
245        "sw      $27,  32*4($26)         \n"
246        "mfc2    $27,  $1                \n"
247        "sw      $27,  33*4($26)         \n"
248
249    "mfc0        $27,  $12               \n"
250        "sw      $27,  34*4($26)         \n"
251    "mfc0        $27,  $4, 2             \n"
252        "sw      $27,  35*4($26)         \n"
253
254    "sync                            \n"
255
256    "move    $26,   %1               \n"
257
258    "lw      $27,   0*4($26)         \n"
259    "mtc0    $27,   $14              \n"
260
261    "lw      $1,    1*4($26)         \n"
262    "lw      $2,    2*4($26)         \n"
263    "lw      $3,    3*4($26)         \n"
264    "lw      $4,    4*4($26)         \n"
265    "lw      $5,    5*4($26)         \n"
266    "lw      $6,    6*4($26)         \n"
267    "lw      $7,    7*4($26)         \n"
268
269    "lw      $8,    8*4($26)         \n"
270    "lw      $9,    9*4($26)         \n"
271    "lw      $10,  10*4($26)         \n"
272    "lw      $11,  11*4($26)         \n"
273    "lw      $12,  12*4($26)         \n"
274    "lw      $13,  13*4($26)         \n"
275    "lw      $14,  14*4($26)         \n"
276    "lw      $15,  15*4($26)         \n"
277
278        "lw      $16,  16*4($26)         \n"
279        "lw      $17,  17*4($26)         \n"
280    "lw      $18,  18*4($26)         \n"
281    "lw      $19,  19*4($26)         \n"
282    "lw      $20,  20*4($26)         \n"
283    "lw      $21,  21*4($26)         \n"
284    "lw      $22,  22*4($26)         \n"
285    "lw      $23,  23*4($26)         \n"
286
287    "lw      $24,  24*4($26)         \n"
288    "lw      $25,  25*4($26)         \n"
289
290    "lw      $27,  26*4($26)         \n"
291    "mthi    $27                     \n"
292    "lw      $27,  27*4($26)         \n"
293    "mtlo    $27                     \n"
294
295        "lw      $28,  28*4($26)         \n"
296        "lw      $29,  29*4($26)         \n"
297        "lw      $30,  30*4($26)         \n"
298        "lw      $31,  31*4($26)         \n"
299
300        "lw      $27,  32*4($26)         \n"
301        "mtc2    $27,  $0                \n"
302        "lw      $27,  33*4($26)         \n"
303        "mtc2    $27,  $1                \n"
304
305        "lw      $27,  34*4($26)         \n"
306    "mtc0        $27,  $12               \n"
307        "lw      $27,  35*4($26)         \n"
308    "mtc0        $27,  $4, 2             \n"
309
310    "jr      $31                     \n"
311
312        ".set reorder                    \n"
313    ".set at                         \n"
314    : : "r"(ctx_old) , "r"(ctx_new) : "$26" , "$27" , "memory" );
315
316}  // hal_context_switch()
317
318*/
319
320/////////////////////////////////////////////////////////////////////////////////////////
321// These registers are saved/restored to/from CPU context defined by <ctx> argument.
322// - GPR : all, but (zero, k0, k1), plus (hi, lo)
323// - CP0 : c0_th , c0_sr
324// - CP2 : c2_ptpr , C2_mode, C2_epc
325/////////////////////////////////////////////////////////////////////////////////////////
326void hal_cpu_context_switch( thread_t * old,
327                             thread_t * new )
328{
329    hal_cpu_context_t * ctx_old = old->cpu_context;
330    hal_cpu_context_t * ctx_new = new->cpu_context;
331
332    #if CONFIG_CONTEXT_DEBUG
333    hal_cpu_context_display( old );
334    hal_cpu_context_display( new );
335    #endif
336
337    hal_do_switch( ctx_old , ctx_new );
338}
339
340/////////////////////////////////////////////
341error_t hal_cpu_context_copy( thread_t * dst,
342                              thread_t * src )
343{
344    kmem_req_t  req;
345
346    // allocate memory for dst cpu_context
347    req.type   = KMEM_CPU_CTX;
348    req.size   = sizeof(hal_cpu_context_t);
349    req.flags  = AF_KERNEL | AF_ZERO;
350
351    hal_cpu_context_t * dst_context = (hal_cpu_context_t *)kmem_alloc( &req );
352    if( dst_context == NULL ) return ENOMEM;
353
354    // set cpu context pointer in dst thread
355    dst->cpu_context = dst_context;
356
357    // get cpu context pointer from src thread
358    hal_cpu_context_t * src_context = src->cpu_context;
359
360    // copy CPU context from src to dst
361    memcpy( dst_context , src_context , sizeof(hal_cpu_context_t) );
362
363    return 0;
364
365}  // end hal_cpu_context_copy()
366
367/////////////////////////////////////////////////
368void hal_cpu_context_destroy( thread_t * thread )
369{
370    kmem_req_t  req;
371
372    req.type = KMEM_CPU_CTX;
373    req.ptr  = thread->cpu_context;
374    kmem_free( &req );
375
376}  // end hal_cpu_context_destroy()
377
378
379
380
381
382///////////////////////////////////////////////////
383error_t hal_fpu_context_create( thread_t * thread )
384{
385    kmem_req_t  req;
386
387    // allocate memory for uzone
388    req.type   = KMEM_FPU_CTX;
389    req.size   = sizeof(hal_fpu_context_t);
390    req.flags  = AF_KERNEL | AF_ZERO;
391
392    hal_fpu_context_t * context = (hal_fpu_context_t *)kmem_alloc( &req );
393    if( context == NULL ) return ENOMEM;
394
395    // set fpu context pointer in thread
396    thread->fpu_context = (void*)context;
397   
398    return 0;
399}  // hal_fpu_context_create()
400
401/////////////////////////////////////////////
402error_t hal_fpu_context_copy( thread_t * dst,
403                              thread_t * src )
404{
405    kmem_req_t  req;
406
407    // allocate memory for dst fpu_context
408    req.type   = KMEM_FPU_CTX;
409    req.size   = sizeof(hal_fpu_context_t);
410    req.flags  = AF_KERNEL | AF_ZERO;
411
412    hal_fpu_context_t * dst_context = (hal_fpu_context_t *)kmem_alloc( &req );
413    if( dst_context == NULL ) return ENOMEM;
414
415    // set fpu context pointer in dst thread
416    dst->fpu_context = (void*)dst_context;
417
418    // get fpu context pointer from src thread
419    hal_fpu_context_t * src_context = src->fpu_context;
420
421    // copy CPU context from src to dst
422    memcpy( dst_context , src_context , sizeof(hal_fpu_context_t) );
423
424    return 0;
425}  // end hal_fpu_context_copy()
426
427/////////////////////////////////////////////////
428void hal_fpu_context_destroy( thread_t * thread )
429{
430    kmem_req_t  req;
431
432    req.type = KMEM_FPU_CTX;
433    req.ptr  = thread->fpu_context;
434    kmem_free( &req );
435
436}  // end hal_fpu_context_destroy()
437
438/////////////////////////////////////////////////////////////////////////////////////////
439// These registers are initialised:
440// - GPR : sp_29 , fp_30 , a0
441// - CP0 : c0_sr , c0_epc , c0_th
442// - CP2 : C2_ptpr , c2_mode
443// TODO Quand cette fonction est-elle appelée? [AG]
444/////////////////////////////////////////////////////////////////////////////////////////
445void hal_cpu_context_load( thread_t * thread )
446{
447    // get relevant values from thread context
448    hal_cpu_context_t * ctx     = (hal_cpu_context_t *)thread->cpu_context;     
449    uint32_t            sp_29   = ctx->sp_29;
450    uint32_t            fp_30   = ctx->fp_30;
451    uint32_t            c0_th   = ctx->c0_th;
452    uint32_t            c0_sr   = ctx->c0_sr;
453    uint32_t            c2_ptpr = ctx->c2_ptpr;
454    uint32_t            c2_mode = ctx->c2_mode;
455 
456    // get pointer on entry function & argument from thread attributes
457    uint32_t            func    = (uint32_t)thread->entry_func;
458    uint32_t            args    = (uint32_t)thread->entry_args;
459
460    // reset loadable field in thread descriptor
461    thread->flags &= ~THREAD_FLAG_LOADABLE;
462
463    // load registers
464    asm volatile(
465    ".set noreorder                \n"
466        "or       $26,    %0,    $0    \n"   /* $26 <= stack pointer                */
467        "or       $27,    %2,    $0    \n"   /* $27 <= status register              */
468        "addiu    $26,    $26,  -4     \n"   /* decrement stack pointer             */
469        "or       $4,     %7,   $0     \n"   /* load a0                             */
470        "sw       $4,     ($26)        \n"   /* set entry_args in stack             */
471        "ori      $27,    $27,  0x2    \n"   /* set EXL flag in status register     */
472        "mtc0     $27,    $12          \n"   /* load c0_sr                          */
473        "mtc0     %3,     $4,    2     \n"   /* load c0_th                          */
474        "mtc2     %4,     $0           \n"   /* load c2 ptpr                        */
475        "mtc0     %6,     $14          \n"   /* load c0_epc                         */
476        "or           $29,        $16,  $0     \n"   /* load sp_29                          */
477        "or           $30,        %1,   $0     \n"   /* load fp_30                          */
478    "mtc2     %5,     $1           \n"   /* load c2_mode                        */
479    "nop                           \n"
480    "eret                          \n"   /* jump to user code                   */
481    "nop                           \n"
482    ".set reorder                  \n"
483    : 
484    : "r"(sp_29),"r"(fp_30),"r"(c0_sr),"r"(c0_th),
485      "r"(c2_ptpr),"r"(c2_mode),"r"(func),"r"(args)
486    : "$4","$26","$27","$29","$30" );
487
488}  // end hal_cpu_context_load()
489
490
491//////////////////////////////////////////////
492void hal_fpu_context_save( thread_t * thread )
493{
494    uint32_t ctx = (uint32_t)thread->fpu_context;
495
496    asm volatile(
497    ".set noreorder           \n"
498    "swc1    $f0,    0*4(%0)  \n"   
499    "swc1    $f1,    1*4(%0)  \n"   
500    "swc1    $f2,    2*4(%0)  \n"   
501    "swc1    $f3,    3*4(%0)  \n"   
502    "swc1    $f4,    4*4(%0)  \n"   
503    "swc1    $f5,    5*4(%0)  \n"   
504    "swc1    $f6,    6*4(%0)  \n"   
505    "swc1    $f7,    7*4(%0)  \n"   
506    "swc1    $f8,    8*4(%0)  \n"   
507    "swc1    $f9,    9*4(%0)  \n"   
508    "swc1    $f10,  10*4(%0)  \n"   
509    "swc1    $f11,  11*4(%0)  \n"   
510    "swc1    $f12,  12*4(%0)  \n"   
511    "swc1    $f13,  13*4(%0)  \n"   
512    "swc1    $f14,  14*4(%0)  \n"   
513    "swc1    $f15,  15*4(%0)  \n"   
514    "swc1    $f16,  16*4(%0)  \n"   
515    "swc1    $f17,  17*4(%0)  \n"   
516    "swc1    $f18,  18*4(%0)  \n"   
517    "swc1    $f19,  19*4(%0)  \n"   
518    "swc1    $f20,  20*4(%0)  \n"   
519    "swc1    $f21,  21*4(%0)  \n"   
520    "swc1    $f22,  22*4(%0)  \n"   
521    "swc1    $f23,  23*4(%0)  \n"   
522    "swc1    $f24,  24*4(%0)  \n"   
523    "swc1    $f25,  25*4(%0)  \n"   
524    "swc1    $f26,  26*4(%0)  \n"   
525    "swc1    $f27,  27*4(%0)  \n"   
526    "swc1    $f28,  28*4(%0)  \n"   
527    "swc1    $f29,  29*4(%0)  \n"   
528    "swc1    $f30,  30*4(%0)  \n"   
529    "swc1    $f31,  31*4(%0)  \n"   
530    ".set reorder             \n"
531    : : "r"(ctx) );
532
533}  // end hal_cpu_context_save()
534
535/////////////////////////////////////////////////
536void hal_fpu_context_restore( thread_t * thread )
537{
538    uint32_t ctx = (uint32_t)thread->fpu_context;
539
540    asm volatile(
541    ".set noreorder           \n"
542    "lwc1    $f0,    0*4(%0)  \n"   
543    "lwc1    $f1,    1*4(%0)  \n"   
544    "lwc1    $f2,    2*4(%0)  \n"   
545    "lwc1    $f3,    3*4(%0)  \n"   
546    "lwc1    $f4,    4*4(%0)  \n"   
547    "lwc1    $f5,    5*4(%0)  \n"   
548    "lwc1    $f6,    6*4(%0)  \n"   
549    "lwc1    $f7,    7*4(%0)  \n"   
550    "lwc1    $f8,    8*4(%0)  \n"   
551    "lwc1    $f9,    9*4(%0)  \n"   
552    "lwc1    $f10,  10*4(%0)  \n"   
553    "lwc1    $f11,  11*4(%0)  \n"   
554    "lwc1    $f12,  12*4(%0)  \n"   
555    "lwc1    $f13,  13*4(%0)  \n"   
556    "lwc1    $f14,  14*4(%0)  \n"   
557    "lwc1    $f15,  15*4(%0)  \n"   
558    "lwc1    $f16,  16*4(%0)  \n"   
559    "lwc1    $f17,  17*4(%0)  \n"   
560    "lwc1    $f18,  18*4(%0)  \n"   
561    "lwc1    $f19,  19*4(%0)  \n"   
562    "lwc1    $f20,  20*4(%0)  \n"   
563    "lwc1    $f21,  21*4(%0)  \n"   
564    "lwc1    $f22,  22*4(%0)  \n"   
565    "lwc1    $f23,  23*4(%0)  \n"   
566    "lwc1    $f24,  24*4(%0)  \n"   
567    "lwc1    $f25,  25*4(%0)  \n"   
568    "lwc1    $f26,  26*4(%0)  \n"   
569    "lwc1    $f27,  27*4(%0)  \n"   
570    "lwc1    $f28,  28*4(%0)  \n"   
571    "lwc1    $f29,  29*4(%0)  \n"   
572    "lwc1    $f30,  30*4(%0)  \n"   
573    "lwc1    $f31,  31*4(%0)  \n"   
574    ".set reorder             \n"
575    : : "r"(ctx) );
576
577} // end hal_cpu_context_restore()
578
579/////////////////////////////////////
580void hal_fpu_context_dup( xptr_t dst,
581                          xptr_t src )
582{
583        hal_remote_memcpy( dst , src , sizeof(hal_fpu_context_t) );
584}
585
Note: See TracBrowser for help on using the repository browser.