File indexing completed on 2025-05-11 08:23:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <string.h>
0020
0021 #include <bsp/vectors.h>
0022
0023
0024 #define PPC_EXC_PROLOG_VEC_OFFSET 2
0025
0026
0027 extern const char ppc_exc_min_prolog_size [];
0028 extern const char ppc_exc_tgpr_clr_prolog_size [];
0029
0030
0031 extern const uint32_t ppc_exc_tgpr_clr_prolog [];
0032
0033
0034
0035
0036
0037
0038 extern const uint32_t ppc_exc_min_prolog_auto [];
0039
0040
0041 extern const uint32_t ppc_exc_min_prolog_async_tmpl_std [];
0042 extern const uint32_t ppc_exc_min_prolog_sync_tmpl_std [];
0043 extern const uint32_t ppc_exc_min_prolog_async_tmpl_p405_crit [];
0044 extern const uint32_t ppc_exc_min_prolog_sync_tmpl_p405_crit [];
0045 extern const uint32_t ppc_exc_min_prolog_async_tmpl_bookE_crit [];
0046 extern const uint32_t ppc_exc_min_prolog_sync_tmpl_bookE_crit [];
0047 extern const uint32_t ppc_exc_min_prolog_sync_tmpl_e500_mchk [];
0048 extern const uint32_t ppc_exc_min_prolog_async_tmpl_e500_mchk [];
0049 extern const uint32_t ppc_exc_min_prolog_tmpl_naked [];
0050 extern const uint32_t ppc_exc_min_prolog_async_tmpl_normal [];
0051
0052 static const uint32_t *const ppc_exc_prologue_templates [] = {
0053 [PPC_EXC_CLASSIC] = ppc_exc_min_prolog_sync_tmpl_std,
0054 [PPC_EXC_CLASSIC_ASYNC] = ppc_exc_min_prolog_async_tmpl_std,
0055 [PPC_EXC_405_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_p405_crit,
0056 [PPC_EXC_405_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_p405_crit,
0057 [PPC_EXC_BOOKE_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_bookE_crit,
0058 [PPC_EXC_BOOKE_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_bookE_crit,
0059 [PPC_EXC_E500_MACHCHK] = ppc_exc_min_prolog_sync_tmpl_e500_mchk,
0060 [PPC_EXC_E500_MACHCHK_ASYNC] = ppc_exc_min_prolog_async_tmpl_e500_mchk,
0061 [PPC_EXC_NAKED] = ppc_exc_min_prolog_tmpl_naked
0062 };
0063
0064 static bool ppc_exc_create_branch_op(
0065 unsigned vector,
0066 void *vector_base,
0067 uint32_t *prologue,
0068 size_t prologue_size
0069 )
0070 {
0071 static const uintptr_t BRANCH_OP_CODE = 18 << 26;
0072
0073 static const uintptr_t BRANCH_OP_ABS = 0x2;
0074 static const uintptr_t BRANCH_OP_MSK = 0x3ffffff;
0075 size_t branch_op_index = prologue_size / 4 - 1;
0076 uintptr_t vector_address =
0077 (uintptr_t) ppc_exc_vector_address(vector, vector_base);
0078 uintptr_t branch_op_address = vector_address + 4 * branch_op_index;
0079
0080
0081 uintptr_t target_address = prologue [branch_op_index];
0082
0083 uintptr_t branch_target_address = target_address - branch_op_address;
0084
0085
0086
0087
0088
0089 if ((branch_target_address & ~BRANCH_OP_MSK) != 0) {
0090
0091 if (target_address >= 0xfe000001 || target_address < 0x01fffffd) {
0092
0093 branch_target_address = (target_address | BRANCH_OP_ABS) & BRANCH_OP_MSK;
0094 } else {
0095 return false;
0096 }
0097 }
0098
0099 prologue [branch_op_index] = BRANCH_OP_CODE | branch_target_address;
0100
0101 return true;
0102 }
0103
0104 rtems_status_code ppc_exc_make_prologue(
0105 unsigned vector,
0106 void *vector_base,
0107 ppc_exc_category category,
0108 uint32_t *prologue,
0109 size_t *prologue_size
0110 )
0111 {
0112 const uint32_t *prologue_template = NULL;
0113 size_t prologue_template_size = 0;
0114 bool fixup_vector = false;
0115
0116 if (!ppc_exc_is_valid_category(category)) {
0117 return RTEMS_INVALID_NUMBER;
0118 }
0119
0120 if (
0121 ppc_cpu_has_shadowed_gprs()
0122 && (vector == ASM_60X_IMISS_VECTOR
0123 || vector == ASM_60X_DLMISS_VECTOR
0124 || vector == ASM_60X_DSMISS_VECTOR)
0125 ) {
0126 prologue_template = ppc_exc_tgpr_clr_prolog;
0127 prologue_template_size = (size_t) ppc_exc_tgpr_clr_prolog_size;
0128 } else if (
0129 category == PPC_EXC_CLASSIC
0130 && ppc_cpu_is_bookE() != PPC_BOOKE_STD
0131 && ppc_cpu_is_bookE() != PPC_BOOKE_E500
0132 ) {
0133 prologue_template = ppc_exc_min_prolog_auto;
0134 prologue_template_size = (size_t) ppc_exc_min_prolog_size;
0135 #ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
0136 } else if (
0137 category == PPC_EXC_CLASSIC_ASYNC
0138 && ppc_cpu_is_bookE() == PPC_BOOKE_E500
0139 && (ppc_interrupt_get_disable_mask() & MSR_CE) == 0
0140 ) {
0141 prologue_template = ppc_exc_min_prolog_async_tmpl_normal;
0142 prologue_template_size = 16;
0143 fixup_vector = true;
0144 #endif
0145 } else {
0146 prologue_template = ppc_exc_prologue_templates [category];
0147 prologue_template_size = (size_t) ppc_exc_min_prolog_size;
0148 fixup_vector = true;
0149 }
0150
0151 if (prologue_template_size <= *prologue_size) {
0152 *prologue_size = prologue_template_size;
0153
0154 memcpy(prologue, prologue_template, prologue_template_size);
0155
0156 if (
0157 !ppc_exc_create_branch_op(
0158 vector,
0159 vector_base,
0160 prologue,
0161 prologue_template_size
0162 )
0163 ) {
0164 return RTEMS_INVALID_ADDRESS;
0165 }
0166
0167 if (fixup_vector) {
0168 if (vector <= 0x7fffU) {
0169 prologue [PPC_EXC_PROLOG_VEC_OFFSET] =
0170 (prologue [PPC_EXC_PROLOG_VEC_OFFSET] & 0xffff8000U)
0171 | (vector & 0x7fffU);
0172 } else {
0173 return RTEMS_INVALID_ID;
0174 }
0175 }
0176 } else {
0177 return RTEMS_INVALID_SIZE;
0178 }
0179
0180 return RTEMS_SUCCESSFUL;
0181 }