source: rtems/cpukit/score/cpu/unix/cpu.c @ 879a047

4.104.114.84.95
Last change on this file since 879a047 was 3652ad35, checked in by Joel Sherrill <joel.sherrill@…>, on 09/19/95 at 14:53:29

Minor bug fixes to get all targets compilable and running. The
single biggest changes were the expansion of the workspace size
macro to include other types of objects and the increase in the
minimum stack size for most CPUs.

  • Property mode set to 100644
File size: 14.0 KB
Line 
1/*
2 *  UNIX Simulator Dependent Source
3 *
4 *
5 *  To anyone who acknowledges that this file is provided "AS IS"
6 *  without any express or implied warranty:
7 *      permission to use, copy, modify, and distribute this file
8 *      for any purpose is hereby granted without fee, provided that
9 *      the above copyright notice and this notice appears in all
10 *      copies, and that the name of Division Incorporated not be
11 *      used in advertising or publicity pertaining to distribution
12 *      of the software without specific, written prior permission.
13 *      Division Incorporated makes no representations about the
14 *      suitability of this software for any purpose.
15 *
16 *  $Id$
17 */
18
19#include <rtems/system.h>
20#include <rtems/core/isr.h>
21#include <rtems/core/interr.h>
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <signal.h>
26#include <time.h>
27#include <sys/time.h>
28
29#ifndef SA_RESTART
30#define SA_RESTART 0
31#endif
32
33void  _CPU_Signal_initialize(void);
34void  _CPU_Stray_signal(int);
35void  _CPU_ISR_Handler(int);
36
37sigset_t         _CPU_Signal_mask;
38Context_Control  _CPU_Context_Default_with_ISRs_enabled;
39Context_Control  _CPU_Context_Default_with_ISRs_disabled;
40
41/*
42 * Which cpu are we? Used by libcpu and libbsp.
43 */
44
45int cpu_number;
46
47/*PAGE
48 *
49 *  _CPU_ISR_From_CPU_Init
50 */
51
52sigset_t  posix_empty_mask;
53
54void _CPU_ISR_From_CPU_Init()
55{
56  unsigned32        i;
57  proc_ptr          old_handler;
58
59  /*
60   * Generate an empty mask to be used by disable_support
61   */
62
63  sigemptyset(&posix_empty_mask);
64 
65  /*
66   * Block all the signals except SIGTRAP for the debugger
67   * and SIGABRT for fatal errors.
68   */
69
70  (void) sigfillset(&_CPU_Signal_mask);
71  (void) sigdelset(&_CPU_Signal_mask, SIGTRAP);
72  (void) sigdelset(&_CPU_Signal_mask, SIGABRT);
73  (void) sigdelset(&_CPU_Signal_mask, SIGIOT);
74  (void) sigdelset(&_CPU_Signal_mask, SIGCONT);
75
76  _CPU_ISR_Enable(1);
77
78  /*
79   * Set the handler for all signals to be signal_handler
80   * which will then vector out to the correct handler
81   * for whichever signal actually happened. Initially
82   * set the vectors to the stray signal handler.
83   */
84
85  for (i = 0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
86      (void)_CPU_ISR_install_vector(i, _CPU_Stray_signal, &old_handler);
87
88  _CPU_Signal_initialize();
89}
90
91void _CPU_Signal_initialize( void )
92{
93  struct sigaction  act;
94  sigset_t          mask;
95
96  /* mark them all active except for TraceTrap  and Abort */
97
98  sigfillset(&mask);
99  sigdelset(&mask, SIGTRAP);
100  sigdelset(&mask, SIGABRT);
101  sigdelset(&mask, SIGIOT);
102  sigdelset(&mask, SIGCONT);
103  sigprocmask(SIG_UNBLOCK, &mask, 0);
104
105  act.sa_handler = _CPU_ISR_Handler;
106  act.sa_mask = mask;
107  act.sa_flags = SA_RESTART;
108
109  sigaction(SIGHUP, &act, 0);
110  sigaction(SIGINT, &act, 0);
111  sigaction(SIGQUIT, &act, 0);
112  sigaction(SIGILL, &act, 0);
113#ifdef SIGEMT
114  sigaction(SIGEMT, &act, 0);
115#endif
116  sigaction(SIGFPE, &act, 0);
117  sigaction(SIGKILL, &act, 0);
118  sigaction(SIGBUS, &act, 0);
119  sigaction(SIGSEGV, &act, 0);
120#ifdef SIGSYS
121  sigaction(SIGSYS, &act, 0);
122#endif
123  sigaction(SIGPIPE, &act, 0);
124  sigaction(SIGALRM, &act, 0);
125  sigaction(SIGTERM, &act, 0);
126  sigaction(SIGUSR1, &act, 0);
127  sigaction(SIGUSR2, &act, 0);
128  sigaction(SIGCHLD, &act, 0);
129  sigaction(SIGCLD, &act, 0);
130  sigaction(SIGPWR, &act, 0);
131  sigaction(SIGVTALRM, &act, 0);
132  sigaction(SIGPROF, &act, 0);
133  sigaction(SIGIO, &act, 0);
134  sigaction(SIGWINCH, &act, 0);
135  sigaction(SIGSTOP, &act, 0);
136  sigaction(SIGTTIN, &act, 0);
137  sigaction(SIGTTOU, &act, 0);
138  sigaction(SIGURG, &act, 0);
139#ifdef SIGLOST
140    sigaction(SIGLOST, &act, 0);
141#endif
142
143}
144
145/*PAGE
146 *
147 *  _CPU_Context_From_CPU_Init
148 */
149
150void _CPU_Context_From_CPU_Init()
151{
152
153#if defined(hppa1_1) && defined(RTEMS_UNIXLIB)
154    /*
155     * HACK - set the _SYSTEM_ID to 0x20c so that setjmp/longjmp
156     * will handle the full 32 floating point registers.
157     *
158     *  NOTE:  Is this a bug in HPUX9?
159     */
160
161    {
162      extern unsigned32 _SYSTEM_ID;
163
164      _SYSTEM_ID = 0x20c;
165    }
166#endif
167
168  /*
169   *  get default values to use in _CPU_Context_Initialize()
170   */
171
172  _CPU_ISR_Set_level( 0 );
173  _CPU_Context_switch(
174    &_CPU_Context_Default_with_ISRs_enabled,
175    &_CPU_Context_Default_with_ISRs_enabled
176  );
177
178  _CPU_ISR_Set_level( 1 );
179  _CPU_Context_switch(
180    &_CPU_Context_Default_with_ISRs_disabled,
181    &_CPU_Context_Default_with_ISRs_disabled
182  );
183}
184
185/*PAGE
186 *
187 *  _CPU_ISR_Get_level
188 */
189
190sigset_t GET_old_mask;
191
192unsigned32 _CPU_ISR_Get_level( void )
193{
194/*  sigset_t  old_mask; */
195   unsigned32 old_level;
196 
197  sigprocmask(0, 0, &GET_old_mask);
198 
199  if (memcmp((void *)&posix_empty_mask, (void *)&GET_old_mask, sizeof(sigset_t)))
200    old_level = 1;
201  else
202    old_level = 0;
203
204  return old_level;
205}
206
207/*  _CPU_Initialize
208 *
209 *  This routine performs processor dependent initialization.
210 *
211 *  INPUT PARAMETERS:
212 *    cpu_table       - CPU table to initialize
213 *    thread_dispatch - address of disptaching routine
214 */
215
216
217void _CPU_Initialize(
218  rtems_cpu_table  *cpu_table,
219  void            (*thread_dispatch)      /* ignored on this CPU */
220)
221{
222  /*
223   *  The thread_dispatch argument is the address of the entry point
224   *  for the routine called at the end of an ISR once it has been
225   *  decided a context switch is necessary.  On some compilation
226   *  systems it is difficult to call a high-level language routine
227   *  from assembly.  This allows us to trick these systems.
228   *
229   *  If you encounter this problem save the entry point in a CPU
230   *  dependent variable.
231   */
232
233  _CPU_Thread_dispatch_pointer = thread_dispatch;
234
235  /*
236   * XXX; If there is not an easy way to initialize the FP context
237   *      during Context_Initialize, then it is usually easier to
238   *      save an "uninitialized" FP context here and copy it to
239   *      the task's during Context_Initialize.
240   */
241
242  /* XXX: FP context initialization support */
243
244  _CPU_Table = *cpu_table;
245
246  _CPU_ISR_From_CPU_Init();
247
248  _CPU_Context_From_CPU_Init();
249
250}
251
252/*PAGE
253 *
254 *  _CPU_ISR_install_raw_handler
255 */
256
257void _CPU_ISR_install_raw_handler(
258  unsigned32  vector,
259  proc_ptr    new_handler,
260  proc_ptr   *old_handler
261)
262{
263  _CPU_Fatal_halt( 0xdeaddead );
264}
265
266/*PAGE
267 *
268 *  _CPU_ISR_install_vector
269 *
270 *  This kernel routine installs the RTEMS handler for the
271 *  specified vector.
272 *
273 *  Input parameters:
274 *    vector      - interrupt vector number
275 *    old_handler - former ISR for this vector number
276 *    new_handler - replacement ISR for this vector number
277 *
278 *  Output parameters:  NONE
279 *
280 */
281
282
283void _CPU_ISR_install_vector(
284  unsigned32  vector,
285  proc_ptr    new_handler,
286  proc_ptr   *old_handler
287)
288{
289   *old_handler = _ISR_Vector_table[ vector ];
290
291   /*
292    *  If the interrupt vector table is a table of pointer to isr entry
293    *  points, then we need to install the appropriate RTEMS interrupt
294    *  handler for this vector number.
295    */
296
297   /*
298    *  We put the actual user ISR address in '_ISR_vector_table'.  This will
299    *  be used by the _CPU_ISR_Handler so the user gets control.
300    */
301
302    _ISR_Vector_table[ vector ] = new_handler;
303}
304
305/*PAGE
306 *
307 *  _CPU_Install_interrupt_stack
308 */
309
310void _CPU_Install_interrupt_stack( void )
311{
312}
313
314/*PAGE
315 *
316 *  _CPU_Internal_threads_Idle_thread_body
317 *
318 *  NOTES:
319 *
320 *  1. This is the same as the regular CPU independent algorithm.
321 *
322 *  2. If you implement this using a "halt", "idle", or "shutdown"
323 *     instruction, then don't forget to put it in an infinite loop.
324 *
325 *  3. Be warned. Some processors with onboard DMA have been known
326 *     to stop the DMA if the CPU were put in IDLE mode.  This might
327 *     also be a problem with other on-chip peripherals.  So use this
328 *     hook with caution.
329 */
330
331void _CPU_Internal_threads_Idle_thread_body( void )
332{
333  while (1)
334    pause();
335}
336
337/*PAGE
338 *
339 *  _CPU_Context_Initialize
340 */
341
342void _CPU_Context_Initialize(
343  Context_Control  *_the_context,
344  unsigned32       *_stack_base,
345  unsigned32        _size,
346  unsigned32        _new_level,
347  void             *_entry_point
348)
349{
350  void        *source;
351  unsigned32  *addr;
352  unsigned32   jmp_addr;
353  unsigned32   _stack_low;   /* lowest "stack aligned" address */
354  unsigned32   _stack_high;  /* highest "stack aligned" address */
355  unsigned32   _the_size;
356
357  jmp_addr = (unsigned32) _entry_point;
358
359  /*
360   *  On CPUs with stacks which grow down, we build the stack
361   *  based on the _stack_high address.  On CPUs with stacks which
362   *  grow up, we build the stack based on the _stack_low address. 
363   */
364
365  _stack_low = ((unsigned32)(_stack_base) + CPU_STACK_ALIGNMENT);
366  _stack_low &= ~(CPU_STACK_ALIGNMENT - 1);
367
368  _stack_high = ((unsigned32)(_stack_base) + _size);
369  _stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
370
371  _the_size = _size & ~(CPU_STACK_ALIGNMENT - 1);
372
373  /*
374   * Slam our jmp_buf template into the context we are creating
375   */
376
377  if ( _new_level == 0 )
378    source = _CPU_Context_Default_with_ISRs_enabled.regs;
379  else
380    source = _CPU_Context_Default_with_ISRs_disabled.regs;
381     
382  memcpy(_the_context, source, sizeof(Context_Control) ); /* sizeof(jmp_buf)); */
383
384  addr = (unsigned32 *)_the_context;
385
386#if defined(hppa1_1)
387  *(addr + RP_OFF) = jmp_addr;
388  *(addr + SP_OFF) = (unsigned32)(_stack_low + CPU_FRAME_SIZE);
389
390  /*
391   * See if we are using shared libraries by checking
392   * bit 30 in 24 off of newp. If bit 30 is set then
393   * we are using shared libraries and the jump address
394   * is at what 24 off of newp points to so shove that
395   * into 24 off of newp instead.
396   */
397
398  if (jmp_addr & 0x40000000) {
399    jmp_addr &= 0xfffffffc;
400     *(addr + RP_OFF) = (unsigned32)*(unsigned32 *)jmp_addr;
401  }
402#elif defined(sparc)
403
404  /*
405   *  See /usr/include/sys/stack.h in Solaris 2.3 for a nice
406   *  diagram of the stack.
407   */
408
409  asm ("ta  0x03");            /* flush registers */
410
411  *(addr + RP_OFF) = jmp_addr + ADDR_ADJ_OFFSET;
412  *(addr + SP_OFF) = (unsigned32)(_stack_high - CPU_FRAME_SIZE);
413  *(addr + FP_OFF) = (unsigned32)(_stack_high);
414
415#elif defined(i386)
416 
417    /*
418     *  This information was gathered by disassembling setjmp().
419     */
420
421    {
422      unsigned32 stack_ptr;
423
424      stack_ptr = _stack_high - CPU_FRAME_SIZE;
425
426      *(addr + EBX_OFF) = 0xFEEDFEED;
427      *(addr + ESI_OFF) = 0xDEADDEAD;
428      *(addr + EDI_OFF) = 0xDEAFDEAF;
429      *(addr + EBP_OFF) = stack_ptr;
430      *(addr + ESP_OFF) = stack_ptr;
431      *(addr + RET_OFF) = jmp_addr;
432 
433      addr = (unsigned32 *) stack_ptr;
434 
435      addr[ 0 ] = jmp_addr;
436      addr[ 1 ] = (unsigned32) stack_ptr;
437      addr[ 2 ] = (unsigned32) stack_ptr;
438    }
439
440#else
441#error "UNKNOWN CPU!!!"
442#endif
443
444}
445
446/*PAGE
447 *
448 *  _CPU_Context_restore
449 */
450
451void _CPU_Context_restore(
452  Context_Control  *next
453)
454{
455  sigprocmask( SIG_SETMASK, &next->isr_level, 0 );
456  longjmp( next->regs, 0 );
457}
458
459/*PAGE
460 *
461 *  _CPU_Context_switch
462 */
463
464void _CPU_Context_switch(
465  Context_Control  *current,
466  Context_Control  *next
467)
468{
469  int status;
470
471  /*
472   *  Switch levels in one operation
473   */
474
475  status = sigprocmask( SIG_SETMASK, &next->isr_level, &current->isr_level );
476  if ( status )
477    _Internal_error_Occurred(
478      INTERNAL_ERROR_CORE,
479      TRUE,
480      status
481    );
482
483  if (setjmp(current->regs) == 0) {    /* Save the current context */
484     longjmp(next->regs, 0);           /* Switch to the new context */
485     if ( status )
486       _Internal_error_Occurred(
487         INTERNAL_ERROR_CORE,
488         TRUE,
489         status
490       );
491  }
492
493}
494 
495/*PAGE
496 *
497 *  _CPU_Save_float_context
498 */
499
500void _CPU_Save_float_context(
501  Context_Control_fp *fp_context
502)
503{
504}
505
506/*PAGE
507 *
508 *  _CPU_Restore_float_context
509 */
510
511void _CPU_Restore_float_context(
512  Context_Control_fp *fp_context
513)
514{
515}
516
517/*PAGE
518 *
519 *  _CPU_ISR_Disable_support
520 */
521
522unsigned32 _CPU_ISR_Disable_support(void)
523{
524  int status;
525  sigset_t  old_mask;
526
527  status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, &old_mask);
528  if ( status )
529    _Internal_error_Occurred(
530      INTERNAL_ERROR_CORE,
531      TRUE,
532      status
533    );
534
535  if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))
536    return 1;
537
538  return 0;
539}
540
541/*PAGE
542 *
543 *  _CPU_ISR_Enable
544 */
545
546void _CPU_ISR_Enable(
547  unsigned32 level
548)
549{
550  int status;
551
552  if (level == 0)
553    status = sigprocmask(SIG_UNBLOCK, &_CPU_Signal_mask, 0);
554  else
555    status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, 0);
556
557  if ( status )
558    _Internal_error_Occurred(
559      INTERNAL_ERROR_CORE,
560      TRUE,
561      status
562    );
563}
564
565/*PAGE
566 *
567 *  _CPU_ISR_Handler
568 *
569 *  External interrupt handler.
570 *  This is installed as a UNIX signal handler.
571 *  It vectors out to specific user interrupt handlers.
572 */
573
574void _CPU_ISR_Handler(int vector)
575{
576  extern void        _Thread_Dispatch(void);
577  extern unsigned32  _Thread_Dispatch_disable_level;
578  extern boolean     _Context_Switch_necessary;
579
580
581  if (_ISR_Nest_level++ == 0) {
582      /* switch to interrupt stack */
583  }
584
585  _Thread_Dispatch_disable_level++;
586
587  if (_ISR_Vector_table[vector]) {
588     _ISR_Vector_table[vector](vector);
589  } else {
590     _CPU_Stray_signal(vector);
591  }
592
593  if (_ISR_Nest_level-- == 0) {
594      /* switch back to original stack */
595  }
596
597  _Thread_Dispatch_disable_level--;
598
599  if (_Thread_Dispatch_disable_level == 0 &&
600      (_Context_Switch_necessary || _ISR_Signals_to_thread_executing)) {
601      _CPU_ISR_Enable(0);
602      _Thread_Dispatch();
603  }
604}
605
606/*PAGE
607 *
608 *  _CPU_Stray_signal
609 */
610
611void _CPU_Stray_signal(int sig_num)
612{
613  char buffer[ 80 ];   
614
615  /*
616   *  We avoid using the stdio section of the library.
617   *  The following is generally safe.
618   */
619
620  write(
621    2,
622    buffer,
623    sprintf( buffer, "Stray signal %d\n", sig_num )
624  );
625 
626  /*
627   * If it was a "fatal" signal, then exit here
628   * If app code has installed a hander for one of these, then
629   * we won't call _CPU_Stray_signal, so this is ok.
630   */
631 
632  switch (sig_num) {
633      case SIGINT:
634      case SIGHUP:
635      case SIGQUIT:
636      case SIGILL:
637#ifdef SIGEMT
638      case SIGEMT:
639#endif
640      case SIGKILL:
641      case SIGBUS:
642      case SIGSEGV:
643      case SIGTERM:
644          _CPU_Fatal_error(0x100 + sig_num);
645  }
646}
647
648/*PAGE
649 *
650 *  _CPU_Fatal_error
651 */
652
653void _CPU_Fatal_error(unsigned32 error)
654{
655  setitimer(ITIMER_REAL, 0, 0);
656
657  if ( error ) {
658#ifdef RTEMS_DEBUG
659    abort();
660#endif
661    if (getenv("RTEMS_DEBUG"))
662      abort();
663  }
664
665  _exit(error);
666}
667
668/*PAGE
669 *
670 *  _CPU_ffs
671 */
672
673int _CPU_ffs(unsigned32 value)
674{
675  int output;
676  extern int ffs( int );
677
678  output = ffs(value);
679  output = output - 1;
680
681  return output;
682}
Note: See TracBrowser for help on using the repository browser.