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

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

Various bugs.

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