source: rtems/cpukit/score/cpu/unix/cpu.c @ 3652ad35

4.104.114.84.95
Last change on this file since 3652ad35 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
RevLine 
[ac7d5ef0]1/*
[3652ad35]2 *  UNIX Simulator Dependent Source
[ac7d5ef0]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>
[3a4ae6c]20#include <rtems/core/isr.h>
[3652ad35]21#include <rtems/core/interr.h>
[ac7d5ef0]22
23#include <stdio.h>
24#include <stdlib.h>
25#include <signal.h>
26#include <time.h>
[10aed1e3]27#include <sys/time.h>
[ac7d5ef0]28
[637df35]29#ifndef SA_RESTART
30#define SA_RESTART 0
31#endif
[ac7d5ef0]32
[637df35]33void  _CPU_Signal_initialize(void);
34void  _CPU_Stray_signal(int);
35void  _CPU_ISR_Handler(int);
[ac7d5ef0]36
[637df35]37sigset_t         _CPU_Signal_mask;
38Context_Control  _CPU_Context_Default_with_ISRs_enabled;
39Context_Control  _CPU_Context_Default_with_ISRs_disabled;
[ac7d5ef0]40
41/*
42 * Which cpu are we? Used by libcpu and libbsp.
43 */
44
45int cpu_number;
46
[637df35]47/*PAGE
48 *
49 *  _CPU_ISR_From_CPU_Init
50 */
51
[e7e016f]52sigset_t  posix_empty_mask;
53
[637df35]54void _CPU_ISR_From_CPU_Init()
55{
56  unsigned32        i;
57  proc_ptr          old_handler;
58
[e7e016f]59  /*
60   * Generate an empty mask to be used by disable_support
61   */
[637df35]62
[e7e016f]63  sigemptyset(&posix_empty_mask);
64 
[637df35]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
[e7e016f]76  _CPU_ISR_Enable(1);
[637df35]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);
[10aed1e3]113#ifdef SIGEMT
[637df35]114  sigaction(SIGEMT, &act, 0);
[10aed1e3]115#endif
[637df35]116  sigaction(SIGFPE, &act, 0);
117  sigaction(SIGKILL, &act, 0);
118  sigaction(SIGBUS, &act, 0);
119  sigaction(SIGSEGV, &act, 0);
[10aed1e3]120#ifdef SIGSYS
[637df35]121  sigaction(SIGSYS, &act, 0);
[10aed1e3]122#endif
[637df35]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);
[e7e016f]139#ifdef SIGLOST
[637df35]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 );
[3652ad35]173  _CPU_Context_switch(
174    &_CPU_Context_Default_with_ISRs_enabled,
175    &_CPU_Context_Default_with_ISRs_enabled
[637df35]176  );
177
178  _CPU_ISR_Set_level( 1 );
[3652ad35]179  _CPU_Context_switch(
180    &_CPU_Context_Default_with_ISRs_disabled,
181    &_CPU_Context_Default_with_ISRs_disabled
[637df35]182  );
183}
184
[3a4ae6c]185/*PAGE
186 *
187 *  _CPU_ISR_Get_level
188 */
189
[3652ad35]190sigset_t GET_old_mask;
191
[3a4ae6c]192unsigned32 _CPU_ISR_Get_level( void )
193{
[3652ad35]194/*  sigset_t  old_mask; */
195   unsigned32 old_level;
[3a4ae6c]196 
[3652ad35]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;
[3a4ae6c]203
[3652ad35]204  return old_level;
[3a4ae6c]205}
206
[ac7d5ef0]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,
[3a4ae6c]219  void            (*thread_dispatch)      /* ignored on this CPU */
[ac7d5ef0]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
[637df35]246  _CPU_ISR_From_CPU_Init();
[ac7d5ef0]247
[637df35]248  _CPU_Context_From_CPU_Init();
[ac7d5ef0]249
[637df35]250}
[ac7d5ef0]251
[637df35]252/*PAGE
253 *
254 *  _CPU_ISR_install_raw_handler
255 */
[ac7d5ef0]256
[637df35]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 );
[ac7d5ef0]264}
265
[637df35]266/*PAGE
267 *
268 *  _CPU_ISR_install_vector
[ac7d5ef0]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
[637df35]299    *  be used by the _CPU_ISR_Handler so the user gets control.
[ac7d5ef0]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{
[637df35]333  while (1)
334    pause();
[ac7d5ef0]335}
336
[637df35]337/*PAGE
338 *
339 *  _CPU_Context_Initialize
340 */
341
[ac7d5ef0]342void _CPU_Context_Initialize(
343  Context_Control  *_the_context,
344  unsigned32       *_stack_base,
345  unsigned32        _size,
346  unsigned32        _new_level,
[88d594a]347  void             *_entry_point
[ac7d5ef0]348)
349{
[637df35]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;
[ac7d5ef0]356
[637df35]357  jmp_addr = (unsigned32) _entry_point;
[ac7d5ef0]358
[637df35]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   */
[88d594a]364
[637df35]365  _stack_low = ((unsigned32)(_stack_base) + CPU_STACK_ALIGNMENT);
366  _stack_low &= ~(CPU_STACK_ALIGNMENT - 1);
[88d594a]367
[637df35]368  _stack_high = ((unsigned32)(_stack_base) + _size);
369  _stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
[ac7d5ef0]370
[637df35]371  _the_size = _size & ~(CPU_STACK_ALIGNMENT - 1);
[ac7d5ef0]372
[637df35]373  /*
374   * Slam our jmp_buf template into the context we are creating
375   */
[ac7d5ef0]376
[637df35]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     
[3652ad35]382  memcpy(_the_context, source, sizeof(Context_Control) ); /* sizeof(jmp_buf)); */
[ac7d5ef0]383
[637df35]384  addr = (unsigned32 *)_the_context;
[ac7d5ef0]385
386#if defined(hppa1_1)
[637df35]387  *(addr + RP_OFF) = jmp_addr;
388  *(addr + SP_OFF) = (unsigned32)(_stack_low + CPU_FRAME_SIZE);
[ac7d5ef0]389
[637df35]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   */
[ac7d5ef0]397
[637df35]398  if (jmp_addr & 0x40000000) {
399    jmp_addr &= 0xfffffffc;
400     *(addr + RP_OFF) = (unsigned32)*(unsigned32 *)jmp_addr;
401  }
[ac7d5ef0]402#elif defined(sparc)
403
[637df35]404  /*
405   *  See /usr/include/sys/stack.h in Solaris 2.3 for a nice
406   *  diagram of the stack.
407   */
[ac7d5ef0]408
[637df35]409  asm ("ta  0x03");            /* flush registers */
[ac7d5ef0]410
[637df35]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);
[8044533]414
415#elif defined(i386)
416 
417    /*
418     *  This information was gathered by disassembling setjmp().
419     */
[10aed1e3]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;
[8044533]432 
[10aed1e3]433      addr = (unsigned32 *) stack_ptr;
[8044533]434 
[10aed1e3]435      addr[ 0 ] = jmp_addr;
436      addr[ 1 ] = (unsigned32) stack_ptr;
437      addr[ 2 ] = (unsigned32) stack_ptr;
438    }
[8044533]439
[ac7d5ef0]440#else
441#error "UNKNOWN CPU!!!"
442#endif
443
444}
445
[637df35]446/*PAGE
447 *
448 *  _CPU_Context_restore
449 */
450
[ac7d5ef0]451void _CPU_Context_restore(
452  Context_Control  *next
453)
454{
[637df35]455  sigprocmask( SIG_SETMASK, &next->isr_level, 0 );
456  longjmp( next->regs, 0 );
[ac7d5ef0]457}
458
[637df35]459/*PAGE
460 *
461 *  _CPU_Context_switch
462 */
463
[ac7d5ef0]464void _CPU_Context_switch(
465  Context_Control  *current,
466  Context_Control  *next
467)
468{
[3652ad35]469  int status;
470
[637df35]471  /*
472   *  Switch levels in one operation
473   */
[ac7d5ef0]474
[3652ad35]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    );
[ac7d5ef0]482
[637df35]483  if (setjmp(current->regs) == 0) {    /* Save the current context */
484     longjmp(next->regs, 0);           /* Switch to the new context */
[3652ad35]485     if ( status )
486       _Internal_error_Occurred(
487         INTERNAL_ERROR_CORE,
488         TRUE,
489         status
490       );
[637df35]491  }
[3652ad35]492
[ac7d5ef0]493}
[637df35]494 
495/*PAGE
496 *
497 *  _CPU_Save_float_context
498 */
[ac7d5ef0]499
500void _CPU_Save_float_context(
501  Context_Control_fp *fp_context
502)
503{
504}
505
[637df35]506/*PAGE
507 *
508 *  _CPU_Restore_float_context
509 */
510
[ac7d5ef0]511void _CPU_Restore_float_context(
512  Context_Control_fp *fp_context
513)
514{
515}
516
[637df35]517/*PAGE
518 *
519 *  _CPU_ISR_Disable_support
520 */
[ac7d5ef0]521
[637df35]522unsigned32 _CPU_ISR_Disable_support(void)
[ac7d5ef0]523{
[3652ad35]524  int status;
[637df35]525  sigset_t  old_mask;
[ac7d5ef0]526
[3652ad35]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    );
[ac7d5ef0]534
[3652ad35]535  if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))
[637df35]536    return 1;
[ac7d5ef0]537
[637df35]538  return 0;
[ac7d5ef0]539}
540
[637df35]541/*PAGE
542 *
543 *  _CPU_ISR_Enable
544 */
[ac7d5ef0]545
[637df35]546void _CPU_ISR_Enable(
547  unsigned32 level
548)
[ac7d5ef0]549{
[3652ad35]550  int status;
551
[637df35]552  if (level == 0)
[3652ad35]553    status = sigprocmask(SIG_UNBLOCK, &_CPU_Signal_mask, 0);
[637df35]554  else
[3652ad35]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    );
[ac7d5ef0]563}
564
[637df35]565/*PAGE
[ac7d5ef0]566 *
[637df35]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.
[ac7d5ef0]572 */
573
[637df35]574void _CPU_ISR_Handler(int vector)
[ac7d5ef0]575{
[637df35]576  extern void        _Thread_Dispatch(void);
577  extern unsigned32  _Thread_Dispatch_disable_level;
578  extern boolean     _Context_Switch_necessary;
[ac7d5ef0]579
580
[637df35]581  if (_ISR_Nest_level++ == 0) {
582      /* switch to interrupt stack */
583  }
[ac7d5ef0]584
[637df35]585  _Thread_Dispatch_disable_level++;
[ac7d5ef0]586
[637df35]587  if (_ISR_Vector_table[vector]) {
588     _ISR_Vector_table[vector](vector);
589  } else {
590     _CPU_Stray_signal(vector);
591  }
[ac7d5ef0]592
[637df35]593  if (_ISR_Nest_level-- == 0) {
594      /* switch back to original stack */
595  }
[ac7d5ef0]596
[637df35]597  _Thread_Dispatch_disable_level--;
[ac7d5ef0]598
[637df35]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  }
[ac7d5ef0]604}
605
[637df35]606/*PAGE
607 *
608 *  _CPU_Stray_signal
609 */
[ac7d5ef0]610
[637df35]611void _CPU_Stray_signal(int sig_num)
[ac7d5ef0]612{
[637df35]613  char buffer[ 80 ];   
[ac7d5ef0]614
[637df35]615  /*
616   *  We avoid using the stdio section of the library.
617   *  The following is generally safe.
618   */
[ac7d5ef0]619
[637df35]620  write(
621    2,
622    buffer,
623    sprintf( buffer, "Stray signal %d\n", sig_num )
624  );
[ac7d5ef0]625 
[637df35]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   */
[ac7d5ef0]631 
[637df35]632  switch (sig_num) {
633      case SIGINT:
634      case SIGHUP:
635      case SIGQUIT:
636      case SIGILL:
[10aed1e3]637#ifdef SIGEMT
[637df35]638      case SIGEMT:
[10aed1e3]639#endif
[637df35]640      case SIGKILL:
641      case SIGBUS:
642      case SIGSEGV:
643      case SIGTERM:
644          _CPU_Fatal_error(0x100 + sig_num);
645  }
[ac7d5ef0]646}
647
[637df35]648/*PAGE
649 *
650 *  _CPU_Fatal_error
651 */
[ac7d5ef0]652
[637df35]653void _CPU_Fatal_error(unsigned32 error)
[ac7d5ef0]654{
[637df35]655  setitimer(ITIMER_REAL, 0, 0);
[ac7d5ef0]656
[e7e016f]657  if ( error ) {
658#ifdef RTEMS_DEBUG
659    abort();
660#endif
661    if (getenv("RTEMS_DEBUG"))
662      abort();
663  }
664
[637df35]665  _exit(error);
[ac7d5ef0]666}
667
[637df35]668/*PAGE
669 *
670 *  _CPU_ffs
671 */
672
673int _CPU_ffs(unsigned32 value)
[ac7d5ef0]674{
[637df35]675  int output;
676  extern int ffs( int );
[ac7d5ef0]677
[637df35]678  output = ffs(value);
679  output = output - 1;
[ac7d5ef0]680
[637df35]681  return output;
[ac7d5ef0]682}
Note: See TracBrowser for help on using the repository browser.