1 | /* |
---|
2 | * boot_utils.c - TSAR bootloader utilities implementation. |
---|
3 | * |
---|
4 | * Authors : Alain Greiner / Vu Son (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 <stdarg.h> |
---|
25 | |
---|
26 | #include <boot_tty_driver.h> |
---|
27 | #include <hal_kernel_types.h> |
---|
28 | #include <boot_utils.h> |
---|
29 | |
---|
30 | |
---|
31 | /**************************************************************************** |
---|
32 | * Global variables * |
---|
33 | ****************************************************************************/ |
---|
34 | |
---|
35 | extern boot_remote_spinlock_t tty0_lock; // allocated in boot.c |
---|
36 | |
---|
37 | /**************************************************************************** |
---|
38 | * Remote accesses. * |
---|
39 | ****************************************************************************/ |
---|
40 | |
---|
41 | ////////////////////////////////// |
---|
42 | uint32_t boot_remote_lw(xptr_t xp) |
---|
43 | { |
---|
44 | uint32_t res; |
---|
45 | uint32_t ptr; |
---|
46 | uint32_t cxy; |
---|
47 | |
---|
48 | // Extracting information from the extended pointer |
---|
49 | ptr = (uint32_t)GET_PTR(xp); |
---|
50 | cxy = (uint32_t)GET_CXY(xp); |
---|
51 | |
---|
52 | // Assembly instructions to get the work done. |
---|
53 | asm volatile("mfc2 $15, $24\n" /* $15 <= CP2_DATA_PADDR_EXT */ |
---|
54 | "mtc2 %2, $24\n" /* CP2_DATA_PADDR_EXT <= cxy */ |
---|
55 | "lw %0, 0(%1)\n" /* *ptr <= data */ |
---|
56 | "mtc2 $15, $24\n" /* CP2_DATA_PADDR_EXT <= $15 */ |
---|
57 | "sync \n" |
---|
58 | : "=&r"(res) /* Temporary register so that it |
---|
59 | doesn't overlap the other inputs |
---|
60 | or outputs. */ |
---|
61 | : "r"(ptr), "r"(cxy) |
---|
62 | : "$15" |
---|
63 | ); |
---|
64 | |
---|
65 | return res; |
---|
66 | |
---|
67 | } // boot_remote_lw() |
---|
68 | |
---|
69 | ///////////////////////////////////////////// |
---|
70 | void boot_remote_sw(xptr_t xp, uint32_t data) |
---|
71 | { |
---|
72 | uint32_t ptr; /* Classic pointer to the distant memory location. */ |
---|
73 | uint32_t cxy; /* Identifier of the cluster containing the distant |
---|
74 | memory location. */ |
---|
75 | |
---|
76 | /* Extracting information from the extended pointers. */ |
---|
77 | ptr = (uint32_t)GET_PTR(xp); |
---|
78 | cxy = (uint32_t)GET_CXY(xp); |
---|
79 | |
---|
80 | /* Assembly instructions to get the work done. */ |
---|
81 | asm volatile("mfc2 $15, $24\n" /* $15 <= CP2_DATA_PADDR_EXT */ |
---|
82 | "mtc2 %2, $24\n" /* CP2_DATA_PADDR_EXT <= cxy */ |
---|
83 | "sw %0, 0(%1)\n" /* *ptr <= data */ |
---|
84 | "mtc2 $15, $24\n" /* CP2_DATA_PADDR_EXT <= $15 */ |
---|
85 | "sync \n" |
---|
86 | : |
---|
87 | : "r"(data), "r"(ptr), "r"(cxy) |
---|
88 | : "$15", "memory" |
---|
89 | ); |
---|
90 | |
---|
91 | } // boot_remote_sw() |
---|
92 | |
---|
93 | ////////////////////////////////////////////////////// |
---|
94 | int32_t boot_remote_atomic_add(xptr_t xp, int32_t val) |
---|
95 | { |
---|
96 | int32_t res; /* Value stored at the distant memory location before |
---|
97 | the atomic operation. */ |
---|
98 | uint32_t ptr; /* Classic pointer to the distant memory location. */ |
---|
99 | uint32_t cxy; /* Identifier of the cluster containing the distant |
---|
100 | memory location. */ |
---|
101 | |
---|
102 | /* Extracting information from the extended pointers. */ |
---|
103 | ptr = (uint32_t)GET_PTR(xp); |
---|
104 | cxy = (uint32_t)GET_CXY(xp); |
---|
105 | |
---|
106 | /* Assembly instructions to get the work done. */ |
---|
107 | asm volatile("mfc2 $15, $24 \n" /* $15 <= CP2_DATA_PADDR_EXT */ |
---|
108 | "mtc2 %3, $24 \n" /* CP2_DATA_PADDR_EXT <= cxy */ |
---|
109 | "1: \n" |
---|
110 | "ll %0, 0(%1) \n" /* res <= *ptr */ |
---|
111 | "addu $3, %0, %2\n" /* $3 <= res + val */ |
---|
112 | "sc $3, 0(%1) \n" /* *ptr <= $3 */ |
---|
113 | "beq $3, $0, 1b\n" /* Retry until success. */ |
---|
114 | "nop \n" /* Delayed slot. */ |
---|
115 | "mtc2 $15, $24 \n" /* CP2_DATA_PADDR_EXT <= $15 */ |
---|
116 | "sync \n" |
---|
117 | : "=&r"(res) /* Temporary register so that |
---|
118 | it doesn't overlap the other |
---|
119 | inputs or outputs. */ |
---|
120 | : "r"(ptr), "r"(val), "r"(cxy) |
---|
121 | : "$3", "$15", "memory" |
---|
122 | ); |
---|
123 | |
---|
124 | return res; |
---|
125 | |
---|
126 | } // boot_remote_atomic_add() |
---|
127 | |
---|
128 | /////////////////////////////////////////////////////////////// |
---|
129 | void boot_remote_memcpy(xptr_t dest, xptr_t src, uint32_t size) |
---|
130 | { |
---|
131 | uint32_t words_nr; /* Number of 32-bit words to be copied. */ |
---|
132 | uint32_t dptr; /* Classic pointer to the destination buffer. */ |
---|
133 | uint32_t dcxy; /* Identifier of the cluster containing the |
---|
134 | destination buffer. */ |
---|
135 | uint32_t sptr; /* Classic pointer to the source buffer. */ |
---|
136 | uint32_t scxy; /* Identifier of the cluster containing the |
---|
137 | source buffer. */ |
---|
138 | uint32_t i; /* Iterator for memory copying loop. */ |
---|
139 | |
---|
140 | /* Extracting information from the extended pointers. */ |
---|
141 | dptr = (uint32_t)GET_PTR(dest); |
---|
142 | dcxy = (uint32_t)GET_CXY(dest); |
---|
143 | sptr = (uint32_t)GET_PTR(src); |
---|
144 | scxy = (uint32_t)GET_CXY(src); |
---|
145 | |
---|
146 | /* |
---|
147 | * Testing if we could perform word-by-word copy (if both addresses are |
---|
148 | * word-aligned). |
---|
149 | */ |
---|
150 | if ((dptr & 0x3) || (sptr & 0x3)) |
---|
151 | words_nr = 0; |
---|
152 | else |
---|
153 | words_nr = size >> 2; |
---|
154 | |
---|
155 | /* Copying word-by-word. */ |
---|
156 | for (i = 0; i < words_nr; i++) |
---|
157 | { |
---|
158 | asm volatile("mfc2 $15, $24\n" /* $15 <= CP2_DATA_PADDR_EXT */ |
---|
159 | "mtc2 %0, $24\n" /* CP2_DATA_PADDR_EXT <= scxy */ |
---|
160 | "lw $3, 0(%1)\n" /* $3 <= *(sptr + 4*i) */ |
---|
161 | "mtc2 %2, $24\n" /* CP2_DATA_PADDR_EXT <= dcxy */ |
---|
162 | "sw $3, 0(%3)\n" /* *(dptr + 4*i) <= $3 */ |
---|
163 | "mtc2 $15, $24\n" /* CP2_DATA_PADDR_EXT <= $15 */ |
---|
164 | "sync \n" |
---|
165 | : |
---|
166 | : "r"(scxy), "r"(sptr + (i << 2)), |
---|
167 | "r"(dcxy), "r"(dptr + (i << 2)) |
---|
168 | : "$3", "$15", "memory" |
---|
169 | ); |
---|
170 | } |
---|
171 | |
---|
172 | /* Copying byte-by-byte if there is any left. */ |
---|
173 | for (i = words_nr << 2; i < size; i++) |
---|
174 | { |
---|
175 | asm volatile("mfc2 $15, $24\n" /* $15 <= CP2_DATA_PADDR_EXT */ |
---|
176 | "mtc2 %0, $24\n" /* CP2_DATA_PADDR_EXT <= scxy */ |
---|
177 | "lb $3, 0(%1)\n" /* $3 <= *(sptr + i) */ |
---|
178 | "mtc2 %2, $24\n" /* CP2_DATA_PADDR_EXT <= dcxy */ |
---|
179 | "sb $3, 0(%3)\n" /* *(dptr + i) <= $3 */ |
---|
180 | "mtc2 $15, $24\n" /* CP2_DATA_PADDR_EXT <= $15 */ |
---|
181 | "sync \n" |
---|
182 | : |
---|
183 | : "r"(scxy), "r"(sptr + i), |
---|
184 | "r"(dcxy), "r"(dptr + i) |
---|
185 | : "$3", "$15", "memory" |
---|
186 | ); |
---|
187 | } |
---|
188 | |
---|
189 | } // boot_remote_memcpy() |
---|
190 | |
---|
191 | /**************************************************************************** |
---|
192 | * Atomic operations. * |
---|
193 | ****************************************************************************/ |
---|
194 | |
---|
195 | int32_t boot_atomic_add(int32_t* ptr, int32_t val) |
---|
196 | { |
---|
197 | int32_t res; /* Value of the variable before the atomic operation. */ |
---|
198 | |
---|
199 | asm volatile(".set noreorder \n" |
---|
200 | "1: \n" |
---|
201 | "ll %0, 0(%1) \n" /* res <= *ptr */ |
---|
202 | "addu $3, %0, %2\n" /* $3 <= res + val */ |
---|
203 | "sc $3, 0(%1) \n" /* $ptr <= $3 */ |
---|
204 | "beq $3, $0, 1b\n" /* Retry until success. */ |
---|
205 | "nop \n" |
---|
206 | "sync \n" |
---|
207 | ".set reorder \n" |
---|
208 | : "=&r"(res) /* Temporary register so that it |
---|
209 | doesn't overlap the other |
---|
210 | inputs or outputs. */ |
---|
211 | : "r"(ptr), "r"(val) |
---|
212 | : "$3", "memory" |
---|
213 | ); |
---|
214 | |
---|
215 | return res; |
---|
216 | |
---|
217 | } // boot_atomic_add() |
---|
218 | |
---|
219 | /**************************************************************************** |
---|
220 | * Memory functions. * |
---|
221 | ****************************************************************************/ |
---|
222 | |
---|
223 | /////////////////////////////////////////////////////// |
---|
224 | void boot_memcpy(void * dst, void * src, uint32_t size) |
---|
225 | { |
---|
226 | uint32_t * wdst = dst; |
---|
227 | uint32_t * wsrc = src; |
---|
228 | |
---|
229 | // word-by-word copy if both addresses are word-aligned |
---|
230 | if ( (((uint32_t)dst & 0x3) == 0) && (((uint32_t)src & 0x3) == 0) ) |
---|
231 | { |
---|
232 | while (size > 3) |
---|
233 | { |
---|
234 | *wdst++ = *wsrc++; |
---|
235 | size -= 4; |
---|
236 | } |
---|
237 | } |
---|
238 | |
---|
239 | unsigned char * cdst = (unsigned char *)wdst; |
---|
240 | unsigned char * csrc = (unsigned char *)wsrc; |
---|
241 | |
---|
242 | // byte-by-byte copy if: |
---|
243 | // - At least 1 of the 2 addresses is not word-aligned, |
---|
244 | // - 'size' value is not a multiple of 4 bytes. |
---|
245 | while (size) |
---|
246 | { |
---|
247 | *cdst++ = *csrc++; |
---|
248 | } |
---|
249 | } // boot_memcpy() |
---|
250 | |
---|
251 | //////////////////////////////////////////////////// |
---|
252 | void boot_memset(void * dst, int val, uint32_t size) |
---|
253 | { |
---|
254 | val &= 0xFF; |
---|
255 | |
---|
256 | // build a word-sized value |
---|
257 | uint32_t wval = (val << 24) | (val << 16) | (val << 8) | val; |
---|
258 | uint32_t * wdst = (uint32_t *)dst; |
---|
259 | |
---|
260 | // word per word if address aligned |
---|
261 | if (((uint32_t)dst & 0x3) == 0) |
---|
262 | { |
---|
263 | while (size > 3) |
---|
264 | { |
---|
265 | *wdst++ = wval; |
---|
266 | size -= 4; |
---|
267 | } |
---|
268 | } |
---|
269 | |
---|
270 | char * cdst = (char *)wdst; |
---|
271 | |
---|
272 | // byte per byte |
---|
273 | while (size--) |
---|
274 | { |
---|
275 | *cdst++ = (char)val; |
---|
276 | } |
---|
277 | } // boot_memset() |
---|
278 | |
---|
279 | /**************************************************************************** |
---|
280 | * String functions. * |
---|
281 | ****************************************************************************/ |
---|
282 | |
---|
283 | /////////////////////////////////////// |
---|
284 | void boot_strcpy(char* dest, char* src) |
---|
285 | { |
---|
286 | /* Checking if the arguments are correct. */ |
---|
287 | if ((dest == NULL) || (src == NULL)) |
---|
288 | return; |
---|
289 | |
---|
290 | /* Copying the string. */ |
---|
291 | while ((*dest++ = *src++) != '\0'); |
---|
292 | |
---|
293 | } // boot_strcpy() |
---|
294 | |
---|
295 | ///////////////////////////// |
---|
296 | uint32_t boot_strlen(char* s) |
---|
297 | { |
---|
298 | uint32_t res = 0; /* Length of the string (in bytes). */ |
---|
299 | |
---|
300 | if (s != NULL) |
---|
301 | { |
---|
302 | while (*s++ != '\0') |
---|
303 | res++; |
---|
304 | } |
---|
305 | |
---|
306 | return res; |
---|
307 | |
---|
308 | } // boot_strlen() |
---|
309 | |
---|
310 | /////////////////////////////////// |
---|
311 | int boot_strcmp(char* s1, char* s2) |
---|
312 | { |
---|
313 | if ((s1 == NULL) || (s2 == NULL)) |
---|
314 | return 0; |
---|
315 | |
---|
316 | while (1) |
---|
317 | { |
---|
318 | if (*s1 != *s2) |
---|
319 | return 1; |
---|
320 | if (*s1 == '\0') |
---|
321 | break; |
---|
322 | s1++; |
---|
323 | s2++; |
---|
324 | } |
---|
325 | |
---|
326 | return 0; |
---|
327 | |
---|
328 | } // boot_strcmp() |
---|
329 | |
---|
330 | /**************************************************************************** |
---|
331 | * Display functions. * |
---|
332 | ****************************************************************************/ |
---|
333 | |
---|
334 | ///////////////////////// |
---|
335 | void boot_puts(char* str) |
---|
336 | { |
---|
337 | boot_tty_write(str, boot_strlen(str)); |
---|
338 | |
---|
339 | } // boot_puts() |
---|
340 | |
---|
341 | /////////////////////////////////////// |
---|
342 | void boot_printf( char * format , ... ) |
---|
343 | { |
---|
344 | va_list args; |
---|
345 | va_start( args , format ); |
---|
346 | |
---|
347 | // take the lock protecting TTY0 |
---|
348 | boot_remote_lock( XPTR( 0 , &tty0_lock ) ); |
---|
349 | |
---|
350 | printf_text: |
---|
351 | |
---|
352 | while ( *format ) |
---|
353 | { |
---|
354 | uint32_t i; |
---|
355 | for (i = 0 ; format[i] && (format[i] != '%') ; i++); |
---|
356 | if (i) |
---|
357 | { |
---|
358 | boot_tty_write( format , i ); |
---|
359 | format += i; |
---|
360 | } |
---|
361 | if (*format == '%') |
---|
362 | { |
---|
363 | format++; |
---|
364 | goto printf_arguments; |
---|
365 | } |
---|
366 | } |
---|
367 | |
---|
368 | // release the lock |
---|
369 | boot_remote_unlock( XPTR( 0 , &tty0_lock ) ); |
---|
370 | |
---|
371 | va_end( args ); |
---|
372 | return; |
---|
373 | |
---|
374 | printf_arguments: |
---|
375 | |
---|
376 | { |
---|
377 | char buf[20]; |
---|
378 | char * pbuf = NULL; |
---|
379 | uint32_t len = 0; |
---|
380 | static const char HexaTab[] = "0123456789ABCDEF"; |
---|
381 | uint32_t i; |
---|
382 | |
---|
383 | switch (*format++) |
---|
384 | { |
---|
385 | case ('c'): /* char conversion */ |
---|
386 | { |
---|
387 | int val = va_arg( args , int ); |
---|
388 | len = 1; |
---|
389 | buf[0] = val; |
---|
390 | pbuf = &buf[0]; |
---|
391 | break; |
---|
392 | } |
---|
393 | case ('d'): /* 32 bits decimal signed */ |
---|
394 | { |
---|
395 | int val = va_arg( args , int ); |
---|
396 | if (val < 0) |
---|
397 | { |
---|
398 | val = -val; |
---|
399 | boot_tty_write( "-" , 1 ); |
---|
400 | } |
---|
401 | for(i = 0; i < 10; i++) |
---|
402 | { |
---|
403 | buf[9 - i] = HexaTab[val % 10]; |
---|
404 | if (!(val /= 10)) break; |
---|
405 | } |
---|
406 | len = i + 1; |
---|
407 | pbuf = &buf[9 - i]; |
---|
408 | break; |
---|
409 | } |
---|
410 | case ('u'): /* 32 bits decimal unsigned */ |
---|
411 | { |
---|
412 | uint32_t val = va_arg( args , uint32_t ); |
---|
413 | for(i = 0; i < 10; i++) |
---|
414 | { |
---|
415 | buf[9 - i] = HexaTab[val % 10]; |
---|
416 | if (!(val /= 10)) break; |
---|
417 | } |
---|
418 | len = i + 1; |
---|
419 | pbuf = &buf[9 - i]; |
---|
420 | break; |
---|
421 | } |
---|
422 | case ('x'): /* 32 bits hexadecimal unsigned */ |
---|
423 | { |
---|
424 | uint32_t val = va_arg( args , uint32_t ); |
---|
425 | boot_tty_write( "0x" , 2 ); |
---|
426 | for(i = 0; i < 8; i++) |
---|
427 | { |
---|
428 | buf[7 - i] = HexaTab[val & 0xF]; |
---|
429 | if (!(val = (val>>4))) break; |
---|
430 | } |
---|
431 | len = i + 1; |
---|
432 | pbuf = &buf[7 - i]; |
---|
433 | break; |
---|
434 | } |
---|
435 | case ('X'): /* 32 bits hexadecimal unsigned on 10 char */ |
---|
436 | { |
---|
437 | uint32_t val = va_arg( args , uint32_t ); |
---|
438 | boot_tty_write( "0x" , 2 ); |
---|
439 | for(i = 0; i < 8; i++) |
---|
440 | { |
---|
441 | buf[7 - i] = HexaTab[val & 0xF]; |
---|
442 | val = (val>>4); |
---|
443 | } |
---|
444 | len = 8; |
---|
445 | pbuf = buf; |
---|
446 | break; |
---|
447 | } |
---|
448 | case ('l'): /* 64 bits hexadecimal unsigned */ |
---|
449 | { |
---|
450 | uint64_t val = va_arg( args , uint64_t ); |
---|
451 | boot_tty_write( "0x" , 2 ); |
---|
452 | for(i = 0; i < 16; i++) |
---|
453 | { |
---|
454 | buf[15 - i] = HexaTab[val & 0xF]; |
---|
455 | if (!(val = (val>>4))) break; |
---|
456 | } |
---|
457 | len = i + 1; |
---|
458 | pbuf = &buf[15 - i]; |
---|
459 | break; |
---|
460 | } |
---|
461 | case ('L'): /* 64 bits hexadecimal unsigned on 18 char */ |
---|
462 | { |
---|
463 | uint64_t val = va_arg( args , uint64_t ); |
---|
464 | boot_tty_write( "0x" , 2 ); |
---|
465 | for(i = 0; i < 16; i++) |
---|
466 | { |
---|
467 | buf[15 - i] = HexaTab[val & 0xF]; |
---|
468 | val = (val>>4); |
---|
469 | } |
---|
470 | len = 16; |
---|
471 | pbuf = buf; |
---|
472 | break; |
---|
473 | } |
---|
474 | case ('s'): /* string */ |
---|
475 | { |
---|
476 | char* str = va_arg( args , char* ); |
---|
477 | while (str[len]) |
---|
478 | { |
---|
479 | len++; |
---|
480 | } |
---|
481 | pbuf = str; |
---|
482 | break; |
---|
483 | } |
---|
484 | default: |
---|
485 | { |
---|
486 | boot_tty_write( "\n[PANIC] in boot_printf() : illegal format\n", 43 ); |
---|
487 | } |
---|
488 | } |
---|
489 | |
---|
490 | if( pbuf != NULL ) boot_tty_write( pbuf, len ); |
---|
491 | |
---|
492 | goto printf_text; |
---|
493 | } |
---|
494 | } // boot_printf() |
---|
495 | |
---|
496 | |
---|
497 | |
---|
498 | |
---|
499 | |
---|
500 | |
---|
501 | /**************************************************************************** |
---|
502 | * Misc. functions. * |
---|
503 | ****************************************************************************/ |
---|
504 | |
---|
505 | //////////////// |
---|
506 | void boot_exit() |
---|
507 | { |
---|
508 | boot_printf("\n[BOOT PANIC] core %x suicide at cycle %d...\n", |
---|
509 | boot_get_procid() , boot_get_proctime() ); |
---|
510 | |
---|
511 | while (1) asm volatile ("nop"); |
---|
512 | |
---|
513 | } // boot_exit() |
---|
514 | |
---|
515 | //////////////////////////// |
---|
516 | uint32_t boot_get_proctime() |
---|
517 | { |
---|
518 | uint32_t res; /* Value stored in the CP0_COUNT register. */ |
---|
519 | |
---|
520 | asm volatile("mfc0 %0, $9" : "=r"(res)); |
---|
521 | |
---|
522 | return res; |
---|
523 | |
---|
524 | } // boot_get_proctime() |
---|
525 | |
---|
526 | |
---|
527 | ////////////////////////// |
---|
528 | uint32_t boot_get_procid() |
---|
529 | { |
---|
530 | uint32_t res; /* Value stored in the CP0_PROCID register. */ |
---|
531 | |
---|
532 | asm volatile("mfc0 %0, $15, 1" : "=r"(res)); |
---|
533 | |
---|
534 | return (res & 0xFFF); |
---|
535 | |
---|
536 | } // boot_get_procid() |
---|
537 | |
---|
538 | |
---|
539 | //////////////////////////////////////////////// |
---|
540 | void boot_remote_barrier( xptr_t xp_barrier, |
---|
541 | uint32_t count) |
---|
542 | { |
---|
543 | boot_remote_barrier_t * ptr; |
---|
544 | uint32_t cxy; |
---|
545 | uint32_t expected; |
---|
546 | uint32_t current; |
---|
547 | |
---|
548 | // Extract information from the extended pointer |
---|
549 | ptr = (boot_remote_barrier_t*)GET_PTR(xp_barrier); |
---|
550 | cxy = (uint32_t) GET_CXY(xp_barrier); |
---|
551 | |
---|
552 | // Explicitly test the barrier sense value because no initialization |
---|
553 | if (boot_remote_lw(XPTR(cxy, &ptr->sense)) == 0) expected = 1; |
---|
554 | else expected = 0; |
---|
555 | |
---|
556 | // Atomically increment counter |
---|
557 | current = boot_remote_atomic_add(XPTR(cxy, &ptr->current), 1); |
---|
558 | |
---|
559 | // The processor arrived last resets the barrier and toggles its sense |
---|
560 | if (current == (count - 1)) |
---|
561 | { |
---|
562 | boot_remote_sw(XPTR(cxy, &ptr->current), 0); |
---|
563 | boot_remote_sw(XPTR(cxy, &ptr->sense), expected); |
---|
564 | } |
---|
565 | // Other processors poll the sense |
---|
566 | else |
---|
567 | { |
---|
568 | while (boot_remote_lw(XPTR(cxy, &ptr->sense)) != expected); |
---|
569 | } |
---|
570 | |
---|
571 | } // boot_barrier() |
---|
572 | |
---|
573 | //////////////////////////////////////// |
---|
574 | void boot_remote_lock( xptr_t lock_xp ) |
---|
575 | |
---|
576 | { |
---|
577 | // Extract information from the extended pointer |
---|
578 | boot_remote_spinlock_t * ptr = (boot_remote_spinlock_t *)GET_PTR( lock_xp ); |
---|
579 | uint32_t cxy = GET_CXY( lock_xp ); |
---|
580 | |
---|
581 | // get next free ticket |
---|
582 | uint32_t ticket = boot_remote_atomic_add( XPTR( cxy , &ptr->ticket ) , 1 ); |
---|
583 | |
---|
584 | // poll the current slot index |
---|
585 | while ( boot_remote_lw( XPTR( cxy , &ptr->current ) ) != ticket ) |
---|
586 | { |
---|
587 | asm volatile ("nop"); |
---|
588 | } |
---|
589 | |
---|
590 | } // boot_remote_lock() |
---|
591 | |
---|
592 | ///////////////////////////////////////// |
---|
593 | void boot_remote_unlock( xptr_t lock_xp ) |
---|
594 | { |
---|
595 | asm volatile ( "sync" ); // for consistency |
---|
596 | |
---|
597 | // Extract information from the extended pointer |
---|
598 | boot_remote_spinlock_t * ptr = (boot_remote_spinlock_t *)GET_PTR( lock_xp ); |
---|
599 | uint32_t cxy = GET_CXY( lock_xp ); |
---|
600 | xptr_t current_xp = XPTR( cxy , &ptr->current ); |
---|
601 | |
---|
602 | // get current index value |
---|
603 | uint32_t current = boot_remote_lw( current_xp ); |
---|
604 | |
---|
605 | // increment current index |
---|
606 | boot_remote_sw( current_xp , current + 1 ); |
---|
607 | |
---|
608 | } // boot_remote_unlock() |
---|
609 | |
---|
610 | |
---|