Ejemplo n.º 1
0
static void cache_manager_smp_functions( size_t set_size,
    cpu_set_t *cpu_set )
{
  rtems_cache_flush_multiple_data_lines_processor_set( &data_to_flush,
      sizeof(data_to_flush), set_size, cpu_set );
  rtems_cache_invalidate_multiple_data_lines_processor_set( &data_to_flush,
      sizeof(data_to_flush), set_size, cpu_set );
  rtems_cache_flush_entire_data_processor_set( set_size, cpu_set );
  rtems_cache_invalidate_entire_instruction();
  rtems_cache_invalidate_multiple_instruction_lines( &function_to_flush,
      4 /* arbitrary size */ );
}
Ejemplo n.º 2
0
static int call_at_level(int start, int fl, int s, bool dirty)
{
  if (fl == start) {
    /*
     * Some architectures like the SPARC have register windows.  A side-effect
     * of this context switch is that we start with a fresh window set.  On
     * architectures like ARM or PowerPC this context switch has no effect.
     */
    _Context_Switch(&ctx, &ctx);
  }

  if (fl > 0) {
    if (always_true) {
      return call_at_level(start, fl - 1, s, dirty);
    } else {
      return prevent_opt_func(fl - 1, fl - 2);
    }
  } else {
    char *volatile space;
    rtems_counter_ticks a;
    rtems_counter_ticks b;

    if (dirty) {
      dirty_data_cache(main_data, data_size, cache_line_size, fl);
      rtems_cache_invalidate_entire_instruction();
    }

    a = rtems_counter_read();

    /* Ensure that we use an untouched stack area */
    space = alloca(1024);
    (void) space;

    _Context_Switch(&ctx, &ctx);

    b = rtems_counter_read();
    t[s] = rtems_counter_difference(b, a);

    return 0;
  }
}
Ejemplo n.º 3
0
void _CPU_ISR_install_raw_handler(
  uint32_t    vector,
  proc_ptr    new_handler,
  proc_ptr   *old_handler
)
{
  uint32_t               real_vector;
  CPU_Trap_table_entry  *tbr;
  CPU_Trap_table_entry  *slot;
  uint32_t               u32_tbr;
  uint32_t               u32_handler;

  /*
   *  Get the "real" trap number for this vector ignoring the synchronous
   *  versus asynchronous indicator included with our vector numbers.
   */

  real_vector = SPARC_REAL_TRAP_NUMBER( vector );

  /*
   *  Get the current base address of the trap table and calculate a pointer
   *  to the slot we are interested in.
   */

  sparc_get_tbr( u32_tbr );

  u32_tbr &= 0xfffff000;

  tbr = (CPU_Trap_table_entry *) u32_tbr;

  slot = &tbr[ real_vector ];

  /*
   *  Get the address of the old_handler from the trap table.
   *
   *  NOTE: The old_handler returned will be bogus if it does not follow
   *        the RTEMS model.
   */

#define HIGH_BITS_MASK   0xFFFFFC00
#define HIGH_BITS_SHIFT  10
#define LOW_BITS_MASK    0x000003FF

  if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
    u32_handler =
      (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) |
      (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
    *old_handler = (proc_ptr) u32_handler;
  } else
    *old_handler = 0;

  /*
   *  Copy the template to the slot and then fix it.
   */

  *slot = _CPU_Trap_slot_template;

  u32_handler = (uint32_t) new_handler;

  slot->mov_vector_l3 |= vector;
  slot->sethi_of_handler_to_l4 |=
    (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
  slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);

  /*
   * There is no instruction cache snooping, so we need to invalidate
   * the instruction cache to make sure that the processor sees the
   * changes to the trap table. This step is required on both single-
   * and multiprocessor systems.
   *
   * In a SMP configuration a change to the trap table might be
   * missed by other cores. If the system state is up, the other
   * cores can be notified using SMP messages that they need to
   * flush their icache. If the up state has not been reached
   * there is no need to notify other cores. They will do an
   * automatic flush of the icache just after entering the up
   * state, but before enabling interrupts.
   */
  rtems_cache_invalidate_entire_instruction();
}
Ejemplo n.º 4
0
Archivo: cpu.c Proyecto: rtemss/rtems
/*  Verified this is working properly from sparc64_install_isr_entries */
void _CPU_ISR_install_raw_handler(
  uint32_t    vector,
  proc_ptr    new_handler,
  proc_ptr   *old_handler
)
{
  uint32_t               real_vector;
  CPU_Trap_table_entry  *tba;
  CPU_Trap_table_entry  *slot;
  uint64_t               u64_tba;
  uint64_t               u64_handler;

  /*
   *  Get the "real" trap number for this vector ignoring the synchronous
   *  versus asynchronous indicator included with our vector numbers.
   */

  real_vector = SPARC_REAL_TRAP_NUMBER( vector );

  /*
   *  Get the current base address of the trap table and calculate a pointer
   *  to the slot we are interested in.
   */

  sparc64_get_tba( u64_tba );

/*  u32_tbr &= 0xfffff000; */
  u64_tba &= 0xffffffffffff8000;  /* keep only trap base address */

  tba = (CPU_Trap_table_entry *) u64_tba;

  /* use array indexing to fill in lower bits -- require
   * CPU_Trap_table_entry to be full-sized. */
  slot = &tba[ real_vector ];

  /*
   *  Get the address of the old_handler from the trap table.
   *
   *  NOTE: The old_handler returned will be bogus if it does not follow
   *        the RTEMS model.
   */

  /* shift amount to shift of hi bits (31:10) */
#define HI_BITS_SHIFT  10

  /* shift amount of hm bits (41:32) */
#define HM_BITS_SHIFT  32

  /* shift amount of hh bits (63:42) */
#define HH_BITS_SHIFT  42

  /* We're only interested in bits 0-9 of the immediate field*/
#define IMM_MASK    0x000003FF

  if ( slot->rdpr_tstate_g4 == _CPU_Trap_slot_template.rdpr_tstate_g4 ) {
    u64_handler =
      (((uint64_t)((slot->sethi_of_hh_handler_to_g2 << HI_BITS_SHIFT) |
      (slot->or_g2_hm_handler_to_g2 & IMM_MASK))) << HM_BITS_SHIFT) |
      ((slot->sethi_of_handler_to_g3 << HI_BITS_SHIFT) |
      (slot->jmp_to_low_of_handler_plus_g3 & IMM_MASK));
    *old_handler = (proc_ptr) u64_handler;
  } else
    *old_handler = 0;

  /*
   *  Copy the template to the slot and then fix it.
   */

  *slot = _CPU_Trap_slot_template;

  u64_handler = (uint64_t) new_handler;

  /* mask for extracting %hh */
#define HH_BITS_MASK   0xFFFFFC0000000000

  /* mask for extracting %hm */
#define HM_BITS_MASK   0x000003FF00000000

  /* mask for extracting %hi */
#define HI_BITS_MASK   0x00000000FFFFFC00

  /* mask for extracting %lo */
#define LO_BITS_MASK   0x00000000000003FF


  slot->mov_vector_g2 |= vector;
  slot->sethi_of_hh_handler_to_g2 |=
    (u64_handler & HH_BITS_MASK) >> HH_BITS_SHIFT;
  slot->or_g2_hm_handler_to_g2 |=
    (u64_handler & HM_BITS_MASK) >> HM_BITS_SHIFT;
  slot->sethi_of_handler_to_g3 |=
    (u64_handler & HI_BITS_MASK) >> HI_BITS_SHIFT;
  slot->jmp_to_low_of_handler_plus_g3 |= (u64_handler & LO_BITS_MASK);

  /* need to flush icache after this !!! */

  /* need to flush icache in case old trap handler is in cache */
  rtems_cache_invalidate_entire_instruction();

}
Ejemplo n.º 5
0
Archivo: init.c Proyecto: ChOr82/RTEMS
static void test_timing(void)
{
  rtems_interrupt_lock lock;
  rtems_interrupt_lock_context lock_context;
  size_t data_size = sizeof(data);
  uint64_t d[3];
  uint32_t cache_level;
  size_t cache_size;

  rtems_interrupt_lock_initialize(&lock, "test");

  printf(
    "data cache line size %zi bytes\n"
    "data cache size %zi bytes\n",
    rtems_cache_get_data_line_size(),
    rtems_cache_get_data_cache_size(0)
  );

  cache_level = 1;
  cache_size = rtems_cache_get_data_cache_size(cache_level);
  while (cache_size > 0) {
    printf(
      "data cache level %" PRIu32 " size %zi bytes\n",
      cache_level,
      cache_size
    );
    ++cache_level;
    cache_size = rtems_cache_get_data_cache_size(cache_level);
  }

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = load();
  d[1] = load();
  rtems_cache_flush_entire_data();
  d[2] = load();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "load %zi bytes with flush entire data\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with flushed cache %" PRIu64 " ns\n",
    data_size,
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = load();
  d[1] = load();
  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
  d[2] = load();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "load %zi bytes with flush multiple data\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with flushed cache %" PRIu64 " ns\n",
    data_size,
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = load();
  d[1] = load();
  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
  d[2] = load();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "load %zi bytes with invalidate multiple data\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with invalidated cache %" PRIu64 " ns\n",
    data_size,
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = store();
  d[1] = store();
  rtems_cache_flush_entire_data();
  d[2] = store();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "store %zi bytes with flush entire data\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with flushed cache %" PRIu64 " ns\n",
    data_size,
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = store();
  d[1] = store();
  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
  d[2] = store();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "store %zi bytes with flush multiple data\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with flushed cache %" PRIu64 " ns\n",
    data_size,
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = store();
  d[1] = store();
  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
  d[2] = store();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "store %zi bytes with invalidate multiple data\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with invalidated cache %" PRIu64 " ns\n",
    data_size,
    d[0],
    d[1],
    d[2]
  );

  printf(
    "instruction cache line size %zi bytes\n"
    "instruction cache size %zi bytes\n",
    rtems_cache_get_instruction_line_size(),
    rtems_cache_get_instruction_cache_size(0)
  );

  cache_level = 1;
  cache_size = rtems_cache_get_instruction_cache_size(cache_level);
  while (cache_size > 0) {
    printf(
      "instruction cache level %" PRIu32 " size %zi bytes\n",
      cache_level,
      cache_size
    );
    ++cache_level;
    cache_size = rtems_cache_get_instruction_cache_size(cache_level);
  }

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = do_some_work();
  d[1] = do_some_work();
  rtems_cache_invalidate_entire_instruction();
  d[2] = do_some_work();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "invalidate entire instruction\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with invalidated cache %" PRIu64 " ns\n",
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_acquire(&lock, &lock_context);

  d[0] = do_some_work();
  d[1] = do_some_work();
  rtems_cache_invalidate_multiple_instruction_lines(do_some_work, 4096);
  d[2] = do_some_work();

  rtems_interrupt_lock_release(&lock, &lock_context);

  printf(
    "invalidate multiple instruction\n"
    "  duration with normal cache %" PRIu64 " ns\n"
    "  duration with warm cache %" PRIu64 " ns\n"
    "  duration with invalidated cache %" PRIu64 " ns\n",
    d[0],
    d[1],
    d[2]
  );

  rtems_interrupt_lock_destroy(&lock);
}
Ejemplo n.º 6
0
void _CPU_ISR_install_raw_handler(
    uint32_t    vector,
    proc_ptr    new_handler,
    proc_ptr   *old_handler
)
{
    uint32_t               real_vector;
    CPU_Trap_table_entry  *tbr;
    CPU_Trap_table_entry  *slot;
    uint32_t               u32_tbr;
    uint32_t               u32_handler;

    /*
     *  Get the "real" trap number for this vector ignoring the synchronous
     *  versus asynchronous indicator included with our vector numbers.
     */

    real_vector = SPARC_REAL_TRAP_NUMBER( vector );

    /*
     *  Get the current base address of the trap table and calculate a pointer
     *  to the slot we are interested in.
     */

    sparc_get_tbr( u32_tbr );

    u32_tbr &= 0xfffff000;

    tbr = (CPU_Trap_table_entry *) u32_tbr;

    slot = &tbr[ real_vector ];

    /*
     *  Get the address of the old_handler from the trap table.
     *
     *  NOTE: The old_handler returned will be bogus if it does not follow
     *        the RTEMS model.
     */

#define HIGH_BITS_MASK   0xFFFFFC00
#define HIGH_BITS_SHIFT  10
#define LOW_BITS_MASK    0x000003FF

    if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
        u32_handler =
            (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) |
            (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
        *old_handler = (proc_ptr) u32_handler;
    } else
        *old_handler = 0;

    /*
     *  Copy the template to the slot and then fix it.
     */

    *slot = _CPU_Trap_slot_template;

    u32_handler = (uint32_t) new_handler;

    slot->mov_vector_l3 |= vector;
    slot->sethi_of_handler_to_l4 |=
        (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
    slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);

    /* need to flush icache after this !!! */

    rtems_cache_invalidate_entire_instruction();

}