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

Last change on this file since 159 was 151, checked in by alain, 7 years ago

Move the core specific hal_cpu_context_t & hafpu_context_t structures
from the igeneric hal_context.h file to the specific hal_context.c file.

File size: 15.6 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 <printk.h>
30#include <vmm.h>
31#include <core.h>
32#include <cluster.h>
33
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// This structure defines the cpu_context for TSAR MIPS32.
46// These registers are saved/restored at each context switch.
47// WARNING : update the hal_cpu_context_save() and hal_cpu_context_restore()
48//           functions when modifying this structure.
49/////////////////////////////////////////////////////////////////////////////////////////
50
51typedef struct hal_cpu_context_s
52{
53        uint32_t s0_16;      // slot 0
54        uint32_t s1_17;      // slot 1
55        uint32_t s2_18;      // slot 2
56        uint32_t s3_19;      // slot 3
57        uint32_t s4_20;      // slot 4
58        uint32_t s5_21;      // slot 5
59        uint32_t s6_22;      // slot 6
60        uint32_t s7_23;      // slot 7
61        uint32_t sp_29;      // slot 8
62        uint32_t fp_30;      // slot 9
63        uint32_t ra_31;      // slot 10
64        uint32_t c0_sr;      // slot 11
65        uint32_t c0_th;      // slot 12
66        uint32_t c2_ptpr;    // slot 13
67        uint32_t c2_mode;    // slot 14
68} 
69hal_cpu_context_t;
70
71/////////////////////////////////////////////////////////////////////////////////////////
72// This structure defines the fpu_context for TSAR MIPS32.
73/////////////////////////////////////////////////////////////////////////////////////////
74
75typedef struct hal_fpu_context_s
76{
77        uint32_t   fpu_regs[32];     
78}
79hal_fpu_context_t;
80
81//////////////////////////////////////////////////////////
82error_t hal_cpu_context_create( struct thread_s * thread )
83{
84    kmem_req_t  req;
85
86    context_dmsg("\n[INFO] %s : enters for thread %x in process %x\n",
87                 __FUNCTION__ , thread->trdid , thread->process->pid );
88
89    // allocate memory for cpu_context
90    req.type   = KMEM_CPU_CTX;
91    req.size   = sizeof(hal_cpu_context_t);
92    req.flags  = AF_KERNEL | AF_ZERO;
93
94    hal_cpu_context_t * context = (hal_cpu_context_t *)kmem_alloc( &req );
95    if( context == NULL ) return ENOMEM;
96
97    // set cpu context pointer in thread
98    thread->cpu_context = (void*)context;
99
100    // stack pointer, status register and mmu_mode depends on thread type
101        uint32_t sp_29;
102    uint32_t c0_sr;
103    uint32_t c2_mode;
104    if( thread->type == THREAD_USER )
105    {
106        sp_29   = ((uint32_t)thread->u_stack_base) + thread->u_stack_size;
107        c0_sr   = SR_USR_MODE;
108        c2_mode = 0xF;
109    }
110    else
111    {
112        sp_29   = ((uint32_t)thread->k_stack_base) + thread->k_stack_size;
113        c0_sr   = SR_SYS_MODE;
114        c2_mode = 0x3;
115    }
116
117    // align stack pointer on a double word boundary
118        sp_29 = (sp_29 - 8) & (~ 0x7);
119
120    // initialise context
121        context->sp_29      = sp_29; 
122        context->fp_30      = sp_29;                          // TODO check this [AG]
123    context->ra_31      = (uint32_t)thread->entry_func;
124        context->c0_sr      = c0_sr;
125        context->c0_th      = (uint32_t)thread; 
126        context->c2_ptpr    = (uint32_t)((thread->process->vmm.gpt.ppn) >> 1);
127        context->c2_mode    = c2_mode;
128
129    context_dmsg("\n[INFO] %s : exit for thread %x in process %x\n",
130                 __FUNCTION__ , thread->trdid , thread->process->pid );
131
132    return 0;
133}  // end hal_cpu_context_create()
134
135/////////////////////////////////////////////
136error_t hal_cpu_context_copy( thread_t * dst,
137                              thread_t * src )
138{
139    kmem_req_t  req;
140
141    // allocate memory for dst cpu_context
142    req.type   = KMEM_CPU_CTX;
143    req.size   = sizeof(hal_cpu_context_t);
144    req.flags  = AF_KERNEL | AF_ZERO;
145
146    hal_cpu_context_t * dst_context = (hal_cpu_context_t *)kmem_alloc( &req );
147    if( dst_context == NULL ) return ENOMEM;
148
149    // set cpu context pointer in dst thread
150    dst->cpu_context = dst_context;
151
152    // get cpu context pointer from src thread
153    hal_cpu_context_t * src_context = src->cpu_context;
154
155    // copy CPU context from src to dst
156    memcpy( dst_context , src_context , sizeof(hal_cpu_context_t) );
157
158    return 0;
159}  // end hal_cpu_context_copy()
160
161/////////////////////////////////////////////////
162void hal_cpu_context_destroy( thread_t * thread )
163{
164    kmem_req_t  req;
165
166    req.type = KMEM_CPU_CTX;
167    req.ptr  = thread->cpu_context;
168    kmem_free( &req );
169
170}  // end hal_cpu_context_destroy()
171
172///////////////////////////////////////////////////
173error_t hal_fpu_context_create( thread_t * thread )
174{
175    kmem_req_t  req;
176
177    // allocate memory for uzone
178    req.type   = KMEM_FPU_CTX;
179    req.size   = sizeof(hal_fpu_context_t);
180    req.flags  = AF_KERNEL | AF_ZERO;
181
182    hal_fpu_context_t * context = (hal_fpu_context_t *)kmem_alloc( &req );
183    if( context == NULL ) return ENOMEM;
184
185    // set fpu context pointer in thread
186    thread->fpu_context = (void*)context;
187   
188    return 0;
189}  // hal_fpu_context_create()
190
191/////////////////////////////////////////////
192error_t hal_fpu_context_copy( thread_t * dst,
193                              thread_t * src )
194{
195    kmem_req_t  req;
196
197    // allocate memory for dst fpu_context
198    req.type   = KMEM_FPU_CTX;
199    req.size   = sizeof(hal_fpu_context_t);
200    req.flags  = AF_KERNEL | AF_ZERO;
201
202    hal_fpu_context_t * dst_context = (hal_fpu_context_t *)kmem_alloc( &req );
203    if( dst_context == NULL ) return ENOMEM;
204
205    // set fpu context pointer in dst thread
206    dst->fpu_context = (void*)dst_context;
207
208    // get fpu context pointer from src thread
209    hal_fpu_context_t * src_context = src->fpu_context;
210
211    // copy CPU context from src to dst
212    memcpy( dst_context , src_context , sizeof(hal_fpu_context_t) );
213
214    return 0;
215}  // end hal_fpu_context_copy()
216
217/////////////////////////////////////////////////
218void hal_fpu_context_destroy( thread_t * thread )
219{
220    kmem_req_t  req;
221
222    req.type = KMEM_FPU_CTX;
223    req.ptr  = thread->fpu_context;
224    kmem_free( &req );
225
226}  // end hal_fpu_context_destroy()
227
228//////////////////////////////////////////////     
229void hal_cpu_context_save( thread_t * thread )
230{
231    uint32_t ctx = (uint32_t)thread->cpu_context;
232
233    asm volatile(
234    ".set noreorder                \n" 
235    "sw      $16,   0*4(%0)        \n"   /* save s0 to slot 0                   */
236    "sw      $17,   1*4(%0)        \n"   /* save s1 to slot 1                   */
237    "sw      $18,   2*4(%0)        \n"   /* save s2 to slot 2                   */
238    "sw      $19,   3*4(%0)        \n"   /* save s3 to slot 3                   */
239    "sw      $20,   4*4(%0)        \n"   /* save s4 to slot 4                   */
240    "sw      $21,   5*4(%0)        \n"   /* save s5 to slot 5                   */
241    "sw      $22,   6*4(%0)        \n"   /* save s6 to slot 6                   */
242    "sw      $23,   7*4(%0)        \n"   /* save s7 to slot 7                   */
243    "sw      $29,   8*4(%0)        \n"   /* save sp to slot 8                   */
244    "sw      $30,   9*4(%0)        \n"   /* save fp to slot 9                   */
245    "sw      $31,   10*4(%0)       \n"   /* save ra to slot 10                  */
246    "mfc0        $26,   $4,       2        \n"   /* get c0_th from CP0                  */
247        "sw      $26,   12*4(%0)       \n"   /* save c0_th to slot 12               */
248        "mfc2    $26,   $0             \n"   /* get c2_ptpr from CP2                */
249        "sw      $26,   13*4(%0)       \n"   /* save c2_ptpr to slot 13             */
250        "mfc2    $26,   $1             \n"   /* get c2_mod from CP2                 */
251        "sw      $26,   14*4(%0)       \n"   /* save c2_mode to slot 14             */
252    "sync                          \n"
253        ".set reorder                  \n"
254    : : "r"( ctx ) : "$26" , "memory" ); 
255}
256
257/////////////////////////////////////////////////     
258void hal_cpu_context_restore( thread_t * thread )
259{
260    uint32_t ctx = (uint32_t)thread->cpu_context;
261
262    asm volatile(
263    ".set noreorder                \n"
264    "nop                           \n"
265        "lw      $16,  0*4(%0)         \n"   /* restore s0_16                       */
266        "lw      $17,  1*4(%0)         \n"   /* restore s1_17                       */
267    "lw      $18,  2*4(%0)         \n"   /* restore s2_18                       */
268    "lw      $19,  3*4(%0)         \n"   /* restore s3_19                       */
269    "lw      $20,  4*4(%0)         \n"   /* restore s4_20                       */
270    "lw      $21,  5*4(%0)         \n"   /* restore s5_21                       */
271    "lw      $22,  6*4(%0)         \n"   /* restore s6_22                       */
272    "lw      $23,  7*4(%0)         \n"   /* restore s7_23                       */
273        "lw      $29,  8*4(%0)         \n"   /* restore sp_29                       */ 
274        "lw      $30,  9*4(%0)         \n"   /* restore fp_30                       */
275        "lw      $31,  10*4(%0)        \n"   /* restore ra_31                       */
276    "lw      $26,  12*4(%0)        \n"   /* get c0_th from slot 12              */
277        "mtc0    $26,  $4,    2        \n"   /* restore c0_th                       */
278    "lw      $26,  13*4(%0)        \n"   /* get c2_ptpr from slot 13            */
279        "mtc2    $26,  $0              \n"   /* restore c2_ptpr                     */
280    "lw      $26,  14*4(%0)        \n"   /* get c2_mode from slot 14            */
281        "mtc2    $26,  $1              \n"   /* restore c2_mode                     */
282    ".set reorder                  \n"
283    : : "r"(ctx)
284      : "$16","$17","$18","$19","$20","$21","$22","$23","$26","$29","$30","$31" ); 
285}
286
287//////////////////////////////////////////////
288void hal_cpu_context_load( thread_t * thread )
289{
290    // get relevant values from thread context
291    hal_cpu_context_t * ctx     = (hal_cpu_context_t *)thread->cpu_context;     
292    uint32_t            sp_29   = ctx->sp_29;
293    uint32_t            fp_30   = ctx->fp_30;
294    uint32_t            c0_th   = ctx->c0_th;
295    uint32_t            c0_sr   = ctx->c0_sr;
296    uint32_t            c2_ptpr = ctx->c2_ptpr;
297    uint32_t            c2_mode = ctx->c2_mode;
298 
299    // get pointer on entry function & argument from thread attributes
300    uint32_t            func    = (uint32_t)thread->entry_func;
301    uint32_t            args    = (uint32_t)thread->entry_args;
302
303    // reset loadable field in thread descriptor
304    thread->flags &= ~THREAD_FLAG_LOADABLE;
305
306    // load registers
307    asm volatile(
308    ".set noreorder                \n"
309        "or       $26,    %0,    $0    \n"   /* $26 <= stack pointer                */
310        "or       $27,    %2,    $0    \n"   /* $27 <= status register              */
311        "addiu    $26,    $26,  -4     \n"   /* decrement stack pointer             */
312        "or       $4,     %7,   $0     \n"   /* load a0                             */
313        "sw       $4,     ($26)        \n"   /* set entry_args in stack             */
314        "ori      $27,    $27,  0x2    \n"   /* set EXL flag in status register     */
315        "mtc0     $27,    $12          \n"   /* load c0_sr                          */
316        "mtc0     %3,     $4,    2     \n"   /* load c0_th                          */
317        "mtc2     %4,     $0           \n"   /* load c2 ptpr                        */
318        "mtc0     %6,     $14          \n"   /* load c0_epc                         */
319        "or           $29,        $16,  $0     \n"   /* load sp_29                          */
320        "or           $30,        %1,   $0     \n"   /* load fp_30                          */
321    "mtc2     %5,     $1           \n"   /* load c2_mode                        */
322    "nop                           \n"
323    "eret                          \n"   /* jump to user code                   */
324    "nop                           \n"
325    ".set reorder                  \n"
326    : 
327    : "r"(sp_29),"r"(fp_30),"r"(c0_sr),"r"(c0_th),
328      "r"(c2_ptpr),"r"(c2_mode),"r"(func),"r"(args)
329    : "$4","$26","$27","$29","$30" );
330
331}  // end hal_cpu_context_load()
332
333
334//////////////////////////////////////////////
335void hal_fpu_context_save( thread_t * thread )
336{
337    uint32_t ctx = (uint32_t)thread->fpu_context;
338
339    asm volatile(
340    ".set noreorder           \n"
341    "swc1    $f0,    0*4(%0)  \n"   
342    "swc1    $f1,    1*4(%0)  \n"   
343    "swc1    $f2,    2*4(%0)  \n"   
344    "swc1    $f3,    3*4(%0)  \n"   
345    "swc1    $f4,    4*4(%0)  \n"   
346    "swc1    $f5,    5*4(%0)  \n"   
347    "swc1    $f6,    6*4(%0)  \n"   
348    "swc1    $f7,    7*4(%0)  \n"   
349    "swc1    $f8,    8*4(%0)  \n"   
350    "swc1    $f9,    9*4(%0)  \n"   
351    "swc1    $f10,  10*4(%0)  \n"   
352    "swc1    $f11,  11*4(%0)  \n"   
353    "swc1    $f12,  12*4(%0)  \n"   
354    "swc1    $f13,  13*4(%0)  \n"   
355    "swc1    $f14,  14*4(%0)  \n"   
356    "swc1    $f15,  15*4(%0)  \n"   
357    "swc1    $f16,  16*4(%0)  \n"   
358    "swc1    $f17,  17*4(%0)  \n"   
359    "swc1    $f18,  18*4(%0)  \n"   
360    "swc1    $f19,  19*4(%0)  \n"   
361    "swc1    $f20,  20*4(%0)  \n"   
362    "swc1    $f21,  21*4(%0)  \n"   
363    "swc1    $f22,  22*4(%0)  \n"   
364    "swc1    $f23,  23*4(%0)  \n"   
365    "swc1    $f24,  24*4(%0)  \n"   
366    "swc1    $f25,  25*4(%0)  \n"   
367    "swc1    $f26,  26*4(%0)  \n"   
368    "swc1    $f27,  27*4(%0)  \n"   
369    "swc1    $f28,  28*4(%0)  \n"   
370    "swc1    $f29,  29*4(%0)  \n"   
371    "swc1    $f30,  30*4(%0)  \n"   
372    "swc1    $f31,  31*4(%0)  \n"   
373    ".set reorder             \n"
374    : : "r"(ctx) );
375
376}  // end hal_cpu_context_save()
377
378/////////////////////////////////////////////////
379void hal_fpu_context_restore( thread_t * thread )
380{
381    uint32_t ctx = (uint32_t)thread->fpu_context;
382
383    asm volatile(
384    ".set noreorder           \n"
385    "lwc1    $f0,    0*4(%0)  \n"   
386    "lwc1    $f1,    1*4(%0)  \n"   
387    "lwc1    $f2,    2*4(%0)  \n"   
388    "lwc1    $f3,    3*4(%0)  \n"   
389    "lwc1    $f4,    4*4(%0)  \n"   
390    "lwc1    $f5,    5*4(%0)  \n"   
391    "lwc1    $f6,    6*4(%0)  \n"   
392    "lwc1    $f7,    7*4(%0)  \n"   
393    "lwc1    $f8,    8*4(%0)  \n"   
394    "lwc1    $f9,    9*4(%0)  \n"   
395    "lwc1    $f10,  10*4(%0)  \n"   
396    "lwc1    $f11,  11*4(%0)  \n"   
397    "lwc1    $f12,  12*4(%0)  \n"   
398    "lwc1    $f13,  13*4(%0)  \n"   
399    "lwc1    $f14,  14*4(%0)  \n"   
400    "lwc1    $f15,  15*4(%0)  \n"   
401    "lwc1    $f16,  16*4(%0)  \n"   
402    "lwc1    $f17,  17*4(%0)  \n"   
403    "lwc1    $f18,  18*4(%0)  \n"   
404    "lwc1    $f19,  19*4(%0)  \n"   
405    "lwc1    $f20,  20*4(%0)  \n"   
406    "lwc1    $f21,  21*4(%0)  \n"   
407    "lwc1    $f22,  22*4(%0)  \n"   
408    "lwc1    $f23,  23*4(%0)  \n"   
409    "lwc1    $f24,  24*4(%0)  \n"   
410    "lwc1    $f25,  25*4(%0)  \n"   
411    "lwc1    $f26,  26*4(%0)  \n"   
412    "lwc1    $f27,  27*4(%0)  \n"   
413    "lwc1    $f28,  28*4(%0)  \n"   
414    "lwc1    $f29,  29*4(%0)  \n"   
415    "lwc1    $f30,  30*4(%0)  \n"   
416    "lwc1    $f31,  31*4(%0)  \n"   
417    ".set reorder             \n"
418    : : "r"(ctx) );
419
420} // end hal_cpu_context_restore()
421
422/////////////////////////////////////
423void hal_fpu_context_dup( xptr_t dst,
424                          xptr_t src )
425{
426        hal_remote_memcpy( dst , src , sizeof(hal_fpu_context_t) );
427}
428
Note: See TracBrowser for help on using the repository browser.