source: rtems/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c @ 53e008b

4.115
Last change on this file since 53e008b was 53e008b, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 10, 2014 at 1:48:05 PM

score: SMP initialization changes

Add and use _CPU_SMP_Start_processor(). Add and use
_CPU_SMP_Finalize_initialization(). This makes most
_CPU_SMP_Initialize() functions a bit simpler since we can calculate the
minimum value of the count of processors requested by the application
configuration and the count of physically or virtually available
processors in the high-level code.

The CPU port has now the ability to signal a processor start failure.
With the support for clustered/partitioned scheduling the presence of
particular processors can be configured to be optional or mandatory.
There will be a fatal error only in case mandatory processors are not
present.

The CPU port may use a timeout to monitor the start of a processor.

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/*
2 * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <assert.h>
16
17#include <rtems/score/smpimpl.h>
18
19#include <libcpu/powerpc-utility.h>
20
21#include <bsp.h>
22#include <bsp/mmu.h>
23#include <bsp/qoriq.h>
24#include <bsp/vectors.h>
25#include <bsp/irq-generic.h>
26#include <bsp/linker-symbols.h>
27
28LINKER_SYMBOL(bsp_exc_vector_base);
29
30void _start_core_1(void);
31
32#define CORE_COUNT 2
33
34#define ONE_CORE(core) (1 << (core))
35
36#define ALL_CORES ((1 << CORE_COUNT) - 1)
37
38#define IPI_INDEX 0
39
40#define TLB_BEGIN 8
41
42#define TLB_END 16
43
44#define TLB_COUNT (TLB_END - TLB_BEGIN)
45
46/*
47 * These values can be obtained with the debugger or a look into the
48 * U-Boot sources (arch/powerpc/cpu/mpc85xx/release.S).
49 */
50#if 1
51  #define BOOT_BEGIN 0x1fff0000
52  #define BOOT_LAST  0x1fffffff
53  #define SPIN_TABLE (BOOT_BEGIN + 0xf2a0)
54#else
55  #define BOOT_BEGIN 0x3fff0000
56  #define BOOT_LAST  0x3fffffff
57  #define SPIN_TABLE (BOOT_BEGIN + 0xf240)
58#endif
59
60#define TLB_BEGIN 8
61
62#define TLB_END 16
63
64#define TLB_COUNT (TLB_END - TLB_BEGIN)
65
66typedef struct {
67  uint32_t addr_upper;
68  uint32_t addr_lower;
69  uint32_t r3_upper;
70  uint32_t r3_lower;
71  uint32_t reserved;
72  uint32_t pir;
73  uint32_t r6_upper;
74  uint32_t r6_lower;
75} uboot_spin_table;
76
77static uint32_t initial_core_1_stack[4096 / sizeof(uint32_t)];
78
79static void mmu_config_undo(void)
80{
81  int i = 0;
82
83  for (i = TLB_BEGIN; i < TLB_END; ++i) {
84    qoriq_tlb1_invalidate(i);
85  }
86}
87
88static void release_core_1(void)
89{
90  const Per_CPU_Control *second_cpu = _Per_CPU_Get_by_index(1);
91  uboot_spin_table *spin_table = (uboot_spin_table *) SPIN_TABLE;
92  qoriq_mmu_context mmu_context;
93
94  qoriq_mmu_context_init(&mmu_context);
95  qoriq_mmu_add(&mmu_context, BOOT_BEGIN, BOOT_LAST, 0, 0, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW);
96  qoriq_mmu_partition(&mmu_context, TLB_COUNT);
97  qoriq_mmu_write_to_tlb1(&mmu_context, TLB_BEGIN);
98
99  spin_table->pir = 1;
100  spin_table->r3_lower = (uint32_t) second_cpu->interrupt_stack_high;
101  spin_table->addr_upper = 0;
102  rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
103  ppc_synchronize_data();
104  spin_table->addr_lower = (uint32_t) _start_core_1;
105  rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
106
107  mmu_config_undo();
108}
109
110void qoriq_secondary_cpu_initialize(void)
111{
112  const Per_CPU_Control *second_cpu = _Per_CPU_Get_by_index(1);
113
114  /* Disable decrementer */
115  PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(BOOKE_TCR, BOOKE_TCR_DIE);
116
117  /* Initialize exception handler */
118  ppc_exc_initialize_with_vector_base(
119    (uintptr_t) second_cpu->interrupt_stack_low,
120    rtems_configuration_get_interrupt_stack_size(),
121    bsp_exc_vector_base
122  );
123
124  /* Now it is possible to make the code execute only */
125  qoriq_mmu_change_perm(
126    FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SX,
127    FSL_EIS_MAS3_SX,
128    FSL_EIS_MAS3_SR
129  );
130
131  /* Initialize interrupt support */
132  bsp_interrupt_facility_initialize();
133
134  bsp_interrupt_vector_enable(QORIQ_IRQ_IPI_0);
135
136  _SMP_Start_multitasking_on_secondary_processor();
137}
138
139static void bsp_inter_processor_interrupt(void *arg)
140{
141  _SMP_Inter_processor_interrupt_handler();
142}
143
144uint32_t _CPU_SMP_Initialize(void)
145{
146  return CORE_COUNT;
147}
148
149bool _CPU_SMP_Start_processor(uint32_t cpu_index)
150{
151  (void) cpu_index;
152
153  release_core_1();
154
155  return true;
156}
157
158void _CPU_SMP_Finalize_initialization(uint32_t cpu_count)
159{
160  if (cpu_count > 1) {
161    rtems_status_code sc;
162
163    sc = rtems_interrupt_handler_install(
164      QORIQ_IRQ_IPI_0,
165      "IPI",
166      RTEMS_INTERRUPT_UNIQUE,
167      bsp_inter_processor_interrupt,
168      NULL
169    );
170    assert(sc == RTEMS_SUCCESSFUL);
171  }
172}
173
174void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
175{
176  uint32_t self = ppc_processor_id();
177  qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg =
178    ONE_CORE(target_processor_index);
179}
Note: See TracBrowser for help on using the repository browser.