source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c @ fdd9de80

4.115
Last change on this file since fdd9de80 was fdd9de80, checked in by Sebastian Huber <sebastian.huber@…>, on 07/21/11 at 15:03:31

2011-07-21 Sebastian Huber <sebastian.huber@…>

PR 1799/bsps

  • new-exceptions/bspsupport/ppc_exc_async_normal.S: New file.
  • new-exceptions/cpu.c, new-exceptions/cpu_asm.S, new-exceptions/bspsupport/ppc_exc_asm_macros.h, new-exceptions/bspsupport/ppc_exc_global_handler.c, new-exceptions/bspsupport/ppc_exc_prologue.c, new-exceptions/bspsupport/vectors.h: Added support for SPE.
  • configure.ac, preinstall.am, Makefile.am: Added support for qoriq BSPs.
  • Property mode set to 100644
File size: 5.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ppc_exc
5 *
6 * @brief PowerPC Exceptions implementation.
7 */
8
9/*
10 * Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
11 *
12 * Copyright (C) 2009 embedded brains GmbH.
13 *
14 * The license and distribution terms for this file may be
15 * found in the file LICENSE in this distribution or at
16 * http://www.rtems.com/license/LICENSE.
17 *
18 * $Id$
19 */
20
21#include <string.h>
22
23#include <bsp/vectors.h>
24
25/* Offset into minimal prolog where vector number is hardcoded */
26#define PPC_EXC_PROLOG_VEC_OFFSET 2
27
28/* Symbols are defined by the linker */
29extern const char ppc_exc_min_prolog_size [];
30extern const char ppc_exc_tgpr_clr_prolog_size [];
31
32/* Special prologue for handling register shadowing on 603-style CPUs */
33extern const uint32_t ppc_exc_tgpr_clr_prolog [];
34
35/*
36 * Classic prologue which determines the vector dynamically from the offset
37 * address. This must only be used for classic, synchronous exceptions with a
38 * vector offset aligned on a 256-byte boundary.
39 */
40extern const uint32_t ppc_exc_min_prolog_auto [];
41
42/* Minimal prologue templates */
43extern const uint32_t ppc_exc_min_prolog_async_tmpl_std [];
44extern const uint32_t ppc_exc_min_prolog_sync_tmpl_std [];
45extern const uint32_t ppc_exc_min_prolog_async_tmpl_p405_crit [];
46extern const uint32_t ppc_exc_min_prolog_sync_tmpl_p405_crit [];
47extern const uint32_t ppc_exc_min_prolog_async_tmpl_bookE_crit [];
48extern const uint32_t ppc_exc_min_prolog_sync_tmpl_bookE_crit [];
49extern const uint32_t ppc_exc_min_prolog_sync_tmpl_e500_mchk [];
50extern const uint32_t ppc_exc_min_prolog_async_tmpl_e500_mchk [];
51extern const uint32_t ppc_exc_min_prolog_tmpl_naked [];
52extern const uint32_t ppc_exc_min_prolog_async_tmpl_normal [];
53
54static const uint32_t *const ppc_exc_prologue_templates [] = {
55  [PPC_EXC_CLASSIC] = ppc_exc_min_prolog_sync_tmpl_std,
56  [PPC_EXC_CLASSIC_ASYNC] = ppc_exc_min_prolog_async_tmpl_std,
57  [PPC_EXC_405_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_p405_crit,
58  [PPC_EXC_405_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_p405_crit,
59  [PPC_EXC_BOOKE_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_bookE_crit,
60  [PPC_EXC_BOOKE_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_bookE_crit,
61  [PPC_EXC_E500_MACHCHK] = ppc_exc_min_prolog_sync_tmpl_e500_mchk,
62  [PPC_EXC_E500_MACHCHK_ASYNC] = ppc_exc_min_prolog_async_tmpl_e500_mchk,
63  [PPC_EXC_NAKED] = ppc_exc_min_prolog_tmpl_naked
64};
65
66static bool ppc_exc_create_branch_op(
67  unsigned vector,
68  uint32_t *prologue,
69  size_t prologue_size
70)
71{
72  static const uintptr_t BRANCH_OP_CODE = 18 << 26;
73  static const uintptr_t BRANCH_OP_LINK = 0x1;
74  static const uintptr_t BRANCH_OP_ABS = 0x2;
75  static const uintptr_t BRANCH_OP_MSK = 0x3ffffff;
76  size_t branch_op_index = prologue_size / 4 - 1;
77  uintptr_t vector_address = (uintptr_t) ppc_exc_vector_address(vector);
78  uintptr_t branch_op_address = vector_address + 4 * branch_op_index;
79
80  /* This value may have BRANCH_OP_LINK set */
81  uintptr_t target_address = prologue [branch_op_index];
82
83  uintptr_t branch_target_address = target_address - branch_op_address;
84
85  /*
86   * We prefer to use a relative branch.  This has the benefit that custom
87   * minimal prologues in a read-only area are relocatable.
88   */
89  if ((branch_target_address & ~BRANCH_OP_MSK) != 0) {
90    /* Target to far for relative branch (PC ± 32M) */
91    if (target_address >= 0xfe000001 || target_address < 0x01fffffd) {
92      /* Can use an absolute branch */
93      branch_target_address = (target_address | BRANCH_OP_ABS) & BRANCH_OP_MSK;
94    } else {
95      return false;
96    }
97  }
98
99  prologue [branch_op_index] = BRANCH_OP_CODE | branch_target_address;
100
101  return true;
102}
103
104rtems_status_code ppc_exc_make_prologue(
105  unsigned vector,
106  ppc_exc_category category,
107  uint32_t *prologue,
108  size_t *prologue_size
109)
110{
111  const uint32_t *prologue_template = NULL;
112  size_t prologue_template_size = 0;
113  bool fixup_vector = false;
114
115  if (!ppc_exc_is_valid_category(category)) {
116    return RTEMS_INVALID_NUMBER;
117  }
118
119  if (
120    ppc_cpu_has_shadowed_gprs()
121      && (vector == ASM_60X_IMISS_VECTOR
122        || vector == ASM_60X_DLMISS_VECTOR
123        || vector == ASM_60X_DSMISS_VECTOR)
124  ) {
125    prologue_template = ppc_exc_tgpr_clr_prolog;
126    prologue_template_size = (size_t) ppc_exc_tgpr_clr_prolog_size;
127  } else if (
128    category == PPC_EXC_CLASSIC
129      && ppc_cpu_is_bookE() != PPC_BOOKE_STD
130      && ppc_cpu_is_bookE() != PPC_BOOKE_E500
131  ) {
132    prologue_template = ppc_exc_min_prolog_auto;
133    prologue_template_size = (size_t) ppc_exc_min_prolog_size;
134  } else if (
135    category == PPC_EXC_CLASSIC_ASYNC
136      && ppc_cpu_is_bookE() == PPC_BOOKE_E500
137      && (ppc_interrupt_get_disable_mask() & MSR_CE) == 0
138  ) {
139    prologue_template = ppc_exc_min_prolog_async_tmpl_normal;
140    prologue_template_size = (size_t) ppc_exc_min_prolog_size;
141    fixup_vector = true;
142  } else {
143    prologue_template = ppc_exc_prologue_templates [category];
144    prologue_template_size = (size_t) ppc_exc_min_prolog_size;
145    fixup_vector = true;
146  }
147
148  if (prologue_template_size <= *prologue_size) {
149    *prologue_size = prologue_template_size;
150
151    memcpy(prologue, prologue_template, prologue_template_size);
152
153    if (!ppc_exc_create_branch_op(vector, prologue, prologue_template_size)) {
154      return RTEMS_INVALID_ADDRESS;
155    }
156
157    if (fixup_vector) {
158      if (vector <= 0x7fffU) {
159        prologue [PPC_EXC_PROLOG_VEC_OFFSET] =
160          (prologue [PPC_EXC_PROLOG_VEC_OFFSET] & 0xffff8000U)
161            | (vector & 0x7fffU);
162      } else {
163        return RTEMS_INVALID_ID;
164      }
165    }
166  } else {
167    return RTEMS_INVALID_SIZE;
168  }
169
170  return RTEMS_SUCCESSFUL;
171}
Note: See TracBrowser for help on using the repository browser.