source: trunk/hal/tsar_mips32/core/hal_special.c @ 624

Last change on this file since 624 was 624, checked in by alain, 5 years ago

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 7.7 KB
Line 
1/*
2 * hal_special.c - implementation of Generic Special Register Access API for TSAR-MIPS32
3 *
4 * Author    Alain Greiner (2016,2017)
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
25#include <hal_kernel_types.h>
26#include <hal_special.h>
27#include <hal_exception.h>
28#include <core.h>
29#include <thread.h>
30
31/****  Forward declarations ****/
32
33struct thread_s;
34
35
36//////////////////////////////////////////////////////////////////////////////////
37//   Extern global variables
38//////////////////////////////////////////////////////////////////////////////////
39
40extern cxy_t local_cxy;
41extern void  hal_kentry_enter( void );
42
43/////////////////////////////////////////////////////////////////////////////////
44// For the TSAR architecture, this function register the physical address of
45// the first level page table (PT1) in the PTPR register.
46// It activates the intructions MMU, and de-activates the data MMU.
47/////////////////////////////////////////////////////////////////////////////////
48void hal_mmu_init( gpt_t * gpt )
49{
50
51    // set PT1 base address in mmu_ptpr register
52    uint32_t ptpr = (((uint32_t)gpt->ptr) >> 13) | (local_cxy << 19);
53    asm volatile ( "mtc2   %0,   $0         \n" : : "r" (ptpr) );
54
55    // set ITLB | ICACHE | DCACHE bits in mmu_mode register
56    asm volatile ( "ori    $26,  $0,  0xB   \n" 
57                   "mtc2   $26,  $1         \n" );
58}
59
60////////////////////////////////////////////////////////////////////////////////
61// For the TSAR architecture, this function registers the address of the
62// hal_kentry_enter() function in the MIPS32 cp0_ebase register.
63////////////////////////////////////////////////////////////////////////////////
64void hal_set_kentry( void )
65{
66    uint32_t kentry = (uint32_t)(&hal_kentry_enter);
67
68    asm volatile("mtc0   %0,  $15,  1" : : "r" (kentry) );
69}
70
71////////////////////////////////
72inline gid_t hal_get_gid( void )
73{
74        uint32_t proc_id;
75
76        asm volatile ("mfc0    %0,  $15, 1" : "=&r" (proc_id));
77
78        return (proc_id & 0x3FF);  // 4/4/2 format for TSAR
79}
80
81///////////////////////////////////
82inline reg_t hal_time_stamp( void )
83{
84    reg_t count;
85
86        asm volatile ("mfc0   %0,  $9" : "=&r" (count));
87
88    return count;
89}
90
91///////////////////////////////
92inline reg_t hal_get_sr( void )
93{
94    reg_t sr;
95
96        asm volatile ("mfc0    %0,    $12" : "=&r" (sr));
97
98        return sr;
99}
100
101///////////////////////////////
102uint64_t hal_get_cycles( void )
103{
104        uint64_t cycles;                // absolute time to be returned
105    uint32_t last_count;            // last registered cycles count
106    uint32_t current_count;         // current cycles count
107        uint32_t elapsed;
108
109    core_t * core = CURRENT_THREAD->core;
110
111    // get last registered time stamp
112        last_count = core->time_stamp;
113
114    // get current time stamp from hardware register
115        current_count = hal_time_stamp();
116
117        // compute number of elapsed cycles, taking into account 32 bits register wrap
118        if(current_count < last_count) elapsed = (0xFFFFFFFF - last_count) + current_count;
119        else                           elapsed = current_count - last_count;
120
121    // compute absolute time
122        cycles = core->cycles + elapsed;
123
124        // update core time
125        core->time_stamp = current_count;
126        core->cycles     = cycles;
127
128        hal_fence();
129
130        return cycles;
131}
132
133///////////////////////////////////////////////////////
134inline struct thread_s * hal_get_current_thread( void )
135{
136        void * thread_ptr;
137 
138        asm volatile ("mfc0    %0,  $4,  2" : "=&r" (thread_ptr));
139
140        return thread_ptr;
141}
142
143///////////////////////////////////////////////////////
144void hal_set_current_thread( struct thread_s * thread )
145{ 
146        asm volatile ("mtc0    %0,  $4,  2" : : "r" (thread));
147}
148
149///////////////////////////
150void hal_fpu_enable( void )
151{
152    // set CU1 bit (FPU enable) in c0_sr
153        asm volatile 
154        ( ".set noat                         \n"
155      "lui    $27,    0x2000             \n"
156      "mfc0   $1,     $12                \n"
157      "or     $27,    $1,    $27         \n"
158      "mtc0   $27,    $12                \n"
159      ".set at                           \n" );
160
161    // set CU1 bit in calling thread UZONE
162    uint32_t * uzone = CURRENT_THREAD->uzone_current;
163    uzone[34] |= 0x20000000;
164}
165
166////////////////////////////
167void hal_fpu_disable( void )
168{
169    // reset CU1 bit (FPU enable) in c0_sr
170        asm volatile 
171        ( ".set noat                         \n"
172      "lui    $27,    0xDFFF             \n"
173          "ori    $27,    $27,   0xFFFF      \n"
174      "mfc0   $1,     $12                \n"
175      "and    $27,    $1,    $27         \n"
176      "mtc0   $27,    $12                \n"
177          ".set at                           \n");
178
179    // reset CU1 bit in calling thread UZONE
180    uint32_t * uzone = CURRENT_THREAD->uzone_current;
181    uzone[34] &= 0xDFFFFFFF;
182}
183
184///////////////////////////
185uint32_t hal_get_sp( void )
186{
187        register uint32_t sp;
188 
189        asm volatile ("or    %0,   $0,   $29" : "=&r" (sp));
190 
191        return sp;
192}
193
194/////////////////////////////////////
195uint32_t hal_set_sp( void * new_val )
196{
197        register uint32_t sp;
198 
199        asm volatile
200        ( "or    %0,   $0,      $29   \n"
201          "or    $29,  $0,      %1    \n"
202          : "=&r" (sp) : "r" (new_val)  );
203 
204        return sp;
205}
206
207///////////////////////////
208uint32_t hal_get_ra( void )
209{
210        register uint32_t ra;
211 
212        asm volatile ("or    %0,   $0,   $31" : "=&r" (ra));
213 
214        return ra;
215}
216
217//////////////////////////////////
218uint32_t hal_get_bad_vaddr( void )
219{
220        register uint32_t bad_va;
221
222        asm volatile
223    ( "mfc0    %0,  $8  \n"
224      : "=&r" (bad_va) );
225
226        return bad_va;
227}
228
229////////////////////////////////////////////
230uint32_t hal_uncached_read( uint32_t * ptr )
231{
232        register uint32_t val;
233
234        asm volatile
235        ( "ll    %0,     (%1)  \n"
236      : "=&r"(val) : "r" (ptr) );
237
238        return val;
239}
240
241//////////////////////////////////////////
242void hal_invalid_dcache_line( void * ptr )
243{
244        asm volatile
245        ( "cache    %0,     (%1)              \n"
246          "sync                               \n"
247          : : "i" (0x11) , "r" (ptr) );
248}
249
250/////////////////////////////
251inline void hal_fence( void )
252{
253        asm volatile ("sync");
254}
255
256/////////////////////////////
257inline void hal_rdbar( void )
258{
259        asm volatile( "" ::: "memory" );
260}
261
262///////////////////////////
263void hal_core_sleep( void )
264{
265        while( 1 ) asm volatile ("wait");
266}
267
268//////////////////////////////////////
269void hal_fixed_delay( uint32_t delay )
270{ 
271    asm volatile
272    ( ".set noreorder        \n"
273      "or    $27,  %0,  $0   \n"
274      "1:                    \n"
275      "addi  $27, $27,  -1   \n"
276      "nop                   \n"
277      "bne   $27,  $0,  1b   \n"
278      "nop                   \n"
279      ".set reorder          \n"
280      : : "r" (delay>>2) : "$27" );
281}
282
283//////////////////////////////////////////////////
284void hal_get_mmu_excp( intptr_t * mmu_ins_excp_code,
285                       intptr_t * mmu_ins_bad_vaddr,
286                       intptr_t * mmu_dat_excp_code,
287                       intptr_t * mmu_dat_bad_vaddr )
288{
289    asm volatile
290    ( "mfc2   %0,    $11        \n"
291      "mfc2   %1,    $13        \n"
292      "mfc2   %2,    $12        \n"
293      "mfc2   %3,    $14        \n"
294      : "=&r"(*mmu_ins_excp_code),
295        "=&r"(*mmu_ins_bad_vaddr),
296        "=&r"(*mmu_dat_excp_code),
297        "=&r"(*mmu_dat_bad_vaddr) );
298}
299
Note: See TracBrowser for help on using the repository browser.