Пример #1
0
static void null_pointer_protection(void)
{
#if defined(MPC55XX_BOARD_MPC5674FEVB) || defined(MPC55XX_BOARD_MPC5566EVB)
	struct MMU_tag mmu = { .MAS0 = { .B = { .TLBSEL = 1, .ESEL = 1 } } };

	PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mmu.MAS0.R);
	__asm__ volatile ("tlbre");
	mmu.MAS1.R = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1);
	mmu.MAS1.B.VALID = 0;
	PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1, mmu.MAS1.R);
	__asm__ volatile ("tlbwe");
#endif
}
Пример #2
0
static void null_pointer_protection(void)
{
#ifdef MPC55XX_NULL_POINTER_PROTECTION
	struct MMU_tag mmu = { .MAS0 = { .B = { .TLBSEL = 1, .ESEL = 1 } } };

	PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mmu.MAS0.R);
	__asm__ volatile ("tlbre");
	mmu.MAS1.R = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1);
	mmu.MAS1.B.VALID = 0;
	PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1, mmu.MAS1.R);
	__asm__ volatile ("tlbwe");
#endif
}
Пример #3
0
void bsp_restart(void *addr)
{
  rtems_interrupt_level level;
  void (*start)(void) = addr;
  #ifdef HAS_UBOOT
    const void *mem_begin = (const void *) bsp_uboot_board_info.bi_memstart;
    size_t mem_size = bsp_uboot_board_info.bi_memsize;
  #else /* HAS_UBOOT */
    const void *mem_begin = bsp_ram_start;
    size_t mem_size = (size_t) bsp_ram_size;
  #endif /* HAS_UBOOT */
  uint32_t hid0;

  rtems_interrupt_disable(level);

  hid0 = PPC_SPECIAL_PURPOSE_REGISTER(HID0);

  if ((hid0 & HID0_DCE) != 0) {
    rtems_cache_flush_multiple_data_lines(mem_begin, mem_size);
  }

  hid0 &= ~(HID0_DCE | HID0_ICE);

  PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0);

  (*start)();
}
Пример #4
0
static void start_thread_if_necessary(uint32_t cpu_index_self)
{
#if QORIQ_THREAD_COUNT > 1
  uint32_t i;

  for (i = 1; i < QORIQ_THREAD_COUNT; ++i) {
    uint32_t cpu_index_next = cpu_index_self + i;

    if (
      is_started_by_u_boot(cpu_index_self)
        && cpu_index_next < rtems_configuration_get_maximum_processors()
        && _SMP_Should_start_processor(cpu_index_next)
    ) {
      /* Thread Initial Next Instruction Address (INIA) */
      PPC_SET_THREAD_MGMT_REGISTER(321, (uint32_t) _start_thread);

      /* Thread Initial Machine State (IMSR) */
      PPC_SET_THREAD_MGMT_REGISTER(289, QORIQ_INITIAL_MSR);

      /* Thread Enable Set (TENS) */
      PPC_SET_SPECIAL_PURPOSE_REGISTER(438, 1U << i);
    }
  }
#endif
}
Пример #5
0
static void t32mppc_clock_initialize(void)
{
  uint64_t frequency = bsp_time_base_frequency / 10;
  uint32_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
  uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);

  PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_DECAR, interval - 1);
  PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(
    BOOKE_TCR,
    BOOKE_TCR_DIE | BOOKE_TCR_ARE
  );
  ppc_set_decrementer_register(interval - 1);

  t32mppc_clock_tc.tc_get_timecount = t32mppc_clock_get_timecount;
  t32mppc_clock_tc.tc_counter_mask = 0xffffffff;
  t32mppc_clock_tc.tc_frequency = bsp_time_base_frequency;
  t32mppc_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
  rtems_timecounter_install(&t32mppc_clock_tc);
}
Пример #6
0
static int ppc_clock_exception_handler_booke( BSP_Exception_frame *frame, unsigned number)
{
	uint32_t msr;

	/* Acknowledge decrementer request */
	PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_DIS);

	/* Increment clock ticks */
	Clock_driver_ticks += 1;

	/* Enable external exceptions */
	msr = ppc_external_exceptions_enable();

	/* Call clock ticker  */
	ppc_clock_tick();

	/* Restore machine state */
	ppc_external_exceptions_disable( msr);

	return 0;
}
Пример #7
0
rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
	/* Current CPU type */
	ppc_cpu_id_t cpu_type = get_ppc_cpu_type();

	/* Make major/minor available to others such as shared memory driver */
	rtems_clock_major = major;
	rtems_clock_minor = minor;

	/*
	 * Set default ticker.
	 *
	 * The function rtems_clock_tick() returns a status code.  This value
	 * will be discarded since the RTEMS documentation claims that it is
	 * always successful.
	 */
	ppc_clock_tick = (void (*)(void)) rtems_clock_tick;

	/* Set the decrementer to the maximum value */
	ppc_set_decrementer_register( PPC_CLOCK_DECREMENTER_MAX);

	/* Decrementer value */
	ppc_clock_decrementer_value = bsp_clicks_per_usec * rtems_configuration_get_microseconds_per_tick() - 1;

	/* Check decrementer value */
	if (ppc_clock_decrementer_value == 0) {
		ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
		RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n");
	}

	/* Set the nanoseconds since last tick handler */
	rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick);

	if (ppc_cpu_is_bookE()) {
		/* Set decrementer auto-reload value */
		PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);

		/* Install exception handler */
		ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke);

		/* Enable decrementer and auto-reload */
		PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
	} else if (cpu_type == PPC_e300c2 || cpu_type == PPC_e300c3) {
		/* TODO: Not tested for e300c2 */

		/* Enable auto-reload */
		PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( HID0, 0x00000040);

		/* Install exception handler */
		ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_e300);
	} else {
		/* Here the decrementer value is actually the interval */
		++ppc_clock_decrementer_value;

		/* Initialize next time base */
		ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value;

		/* Install exception handler */
		ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first);
	}

	/* Set the decrementer value */
	ppc_set_decrementer_register( ppc_clock_decrementer_value);

	return RTEMS_SUCCESSFUL;
}
Пример #8
0
void t32mppc_decrementer_dispatch(void)
{
  PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_TSR, BOOKE_TSR_DIS);
  Clock_isr(NULL);
}
Пример #9
0
rtems_device_driver Clock_initialize(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void *arg
)
{
  uint64_t frequency = bsp_time_base_frequency;
  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
  uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);

  /*
   * Set default ticker.
   */
  ppc_clock_tick = rtems_timecounter_tick;

  if (ppc_cpu_is_bookE() != PPC_BOOKE_405) {
    /* Decrementer value */
    ppc_clock_decrementer_value = interval - 1;

    /* Check decrementer value */
    if (ppc_clock_decrementer_value == 0) {
      ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX;
      RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n");
    }
    if (ppc_cpu_is_bookE()) {
      /* Set decrementer auto-reload value */
      PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value);

      /* Install exception handler */
      ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke);

      /* Enable decrementer and auto-reload */
      PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);
    } else {
      /* Here the decrementer value is actually the interval */
      ++ppc_clock_decrementer_value;

      /* Initialize next time base */
      ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value;

      /* Install exception handler */
      ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first);
    }

    /* Set the decrementer value */
    ppc_set_decrementer_register( ppc_clock_decrementer_value);
  } else {
    /* PIT interval value */
    ppc_clock_decrementer_value = interval;

    /* Install exception handler */
    ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405);

    /* Enable PIT and auto-reload */
    PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(PPC405_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE);

    /* Set PIT auto-reload and initial value */
    PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval);
  }

  /* Install timecounter */
  ppc_tc.tc_get_timecount = ppc_get_timecount;
  ppc_tc.tc_counter_mask = 0xffffffff;
  ppc_tc.tc_frequency = frequency;
  ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
  rtems_timecounter_install(&ppc_tc);

  return RTEMS_SUCCESSFUL;
}
Пример #10
0
rtems_status_code ppc_exc_initialize(
  uint32_t interrupt_disable_mask,
  uintptr_t interrupt_stack_begin,
  uintptr_t interrupt_stack_size
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  const ppc_exc_categories *const categories = ppc_exc_current_categories();
  uintptr_t const interrupt_stack_end = interrupt_stack_begin + interrupt_stack_size;
  uintptr_t interrupt_stack_pointer = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE;
  unsigned vector = 0;
  uint32_t sda_base = 0;
  uint32_t r13 = 0;

  if (categories == NULL) {
    return RTEMS_NOT_IMPLEMENTED;
  }

  /* Assembly code needs SDA_BASE in r13 (SVR4 or EABI). Make sure
   * early init code put it there.
   */
  __asm__ volatile (
    "lis %0, _SDA_BASE_@h\n"
    "ori %0, %0, _SDA_BASE_@l\n"
    "mr  %1, 13\n"
    : "=r" (sda_base), "=r"(r13)
  );

  if (sda_base != r13) {
    return RTEMS_NOT_CONFIGURED;
  }

  /* Ensure proper interrupt stack alignment */
  interrupt_stack_pointer &= ~((uintptr_t) CPU_STACK_ALIGNMENT - 1);

  /* Tag interrupt stack bottom */
  *(uint32_t *) interrupt_stack_pointer = 0;

  /* Move interrupt stack values to special purpose registers */
  PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG1, interrupt_stack_pointer);
  PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG2, interrupt_stack_begin);

  ppc_interrupt_set_disable_mask(interrupt_disable_mask);

  /* Use current MMU / RI settings when running C exception handlers */
  ppc_exc_msr_bits = ppc_machine_state_register() & (MSR_DR | MSR_IR | MSR_RI);

#ifdef __ALTIVEC__
  /* Need vector unit enabled to save/restore altivec context */
  ppc_exc_msr_bits |= MSR_VE;
#endif
 
  if (ppc_cpu_is_bookE() == PPC_BOOKE_STD || ppc_cpu_is_bookE() == PPC_BOOKE_E500) {
    ppc_exc_initialize_booke();
  }

  for (vector = 0; vector <= LAST_VALID_EXC; ++vector) {
    ppc_exc_category category = ppc_exc_category_for_vector(categories, vector);

    if (category != PPC_EXC_INVALID) {
      void *const vector_address = ppc_exc_vector_address(vector);
      uint32_t prologue [16];
      size_t prologue_size = sizeof(prologue);

      sc = ppc_exc_make_prologue(vector, category, prologue, &prologue_size);
      if (sc != RTEMS_SUCCESSFUL) {
        return RTEMS_INTERNAL_ERROR;
      }

      ppc_code_copy(vector_address, prologue, prologue_size);
    }
  }

  /* If we are on a classic PPC with MSR_DR enabled then
   * assert that the mapping for at least this task's
   * stack is write-back-caching enabled (see README/CAVEATS)
   * Do this only if the cache is physically enabled.
   * Since it is not easy to figure that out in a
   * generic way we need help from the BSP: BSPs
   * which run entirely w/o the cache may set
   * ppc_exc_cache_wb_check to zero prior to calling
   * this routine.
   *
   * We run this check only after exception handling is
   * initialized so that we have some chance to get
   * information printed if it fails.
   *
   * Note that it is unsafe to ignore this issue; if
   * the check fails, do NOT disable it unless caches
   * are always physically disabled.
   */
  if (ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits)) {
    /* The size of 63 assumes cache lines are at most 32 bytes */
    uint8_t dummy[63];
    uintptr_t p = (uintptr_t) dummy;
    /* If the dcbz instruction raises an alignment exception
     * then the stack is mapped as write-thru or caching-disabled.
     * The low-level code is not capable of dealing with this
     * ATM.
     */
    p = (p + 31U) & ~31U;
    __asm__ volatile ("dcbz 0, %0"::"b" (p));
    /* If we make it thru here then things seem to be OK */
  }