1*21b818c0SJeenu Viswambharan /* 2*21b818c0SJeenu Viswambharan * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*21b818c0SJeenu Viswambharan * 4*21b818c0SJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 5*21b818c0SJeenu Viswambharan */ 6*21b818c0SJeenu Viswambharan 7*21b818c0SJeenu Viswambharan /* 8*21b818c0SJeenu Viswambharan * Exception handlers at EL3, their priority levels, and management. 9*21b818c0SJeenu Viswambharan */ 10*21b818c0SJeenu Viswambharan 11*21b818c0SJeenu Viswambharan #include <assert.h> 12*21b818c0SJeenu Viswambharan #include <cpu_data.h> 13*21b818c0SJeenu Viswambharan #include <debug.h> 14*21b818c0SJeenu Viswambharan #include <ehf.h> 15*21b818c0SJeenu Viswambharan #include <interrupt_mgmt.h> 16*21b818c0SJeenu Viswambharan #include <platform.h> 17*21b818c0SJeenu Viswambharan 18*21b818c0SJeenu Viswambharan /* Output EHF logs as verbose */ 19*21b818c0SJeenu Viswambharan #define EHF_LOG(...) VERBOSE("EHF: " __VA_ARGS__) 20*21b818c0SJeenu Viswambharan 21*21b818c0SJeenu Viswambharan #define EHF_INVALID_IDX (-1) 22*21b818c0SJeenu Viswambharan 23*21b818c0SJeenu Viswambharan /* For a valid handler, return the actual function pointer; otherwise, 0. */ 24*21b818c0SJeenu Viswambharan #define RAW_HANDLER(h) \ 25*21b818c0SJeenu Viswambharan ((ehf_handler_t) ((h & _EHF_PRI_VALID) ? (h & ~_EHF_PRI_VALID) : 0)) 26*21b818c0SJeenu Viswambharan 27*21b818c0SJeenu Viswambharan #define PRI_BIT(idx) (((ehf_pri_bits_t) 1) << idx) 28*21b818c0SJeenu Viswambharan 29*21b818c0SJeenu Viswambharan /* 30*21b818c0SJeenu Viswambharan * Convert index into secure priority using the platform-defined priority bits 31*21b818c0SJeenu Viswambharan * field. 32*21b818c0SJeenu Viswambharan */ 33*21b818c0SJeenu Viswambharan #define IDX_TO_PRI(idx) \ 34*21b818c0SJeenu Viswambharan ((idx << (7 - exception_data.pri_bits)) & 0x7f) 35*21b818c0SJeenu Viswambharan 36*21b818c0SJeenu Viswambharan /* Check whether a given index is valid */ 37*21b818c0SJeenu Viswambharan #define IS_IDX_VALID(idx) \ 38*21b818c0SJeenu Viswambharan ((exception_data.ehf_priorities[idx].ehf_handler & _EHF_PRI_VALID) != 0) 39*21b818c0SJeenu Viswambharan 40*21b818c0SJeenu Viswambharan /* Returns whether given priority is in secure priority range */ 41*21b818c0SJeenu Viswambharan #define IS_PRI_SECURE(pri) ((pri & 0x80) == 0) 42*21b818c0SJeenu Viswambharan 43*21b818c0SJeenu Viswambharan /* To be defined by the platform */ 44*21b818c0SJeenu Viswambharan extern const ehf_priorities_t exception_data; 45*21b818c0SJeenu Viswambharan 46*21b818c0SJeenu Viswambharan /* Translate priority to the index in the priority array */ 47*21b818c0SJeenu Viswambharan static int pri_to_idx(unsigned int priority) 48*21b818c0SJeenu Viswambharan { 49*21b818c0SJeenu Viswambharan int idx; 50*21b818c0SJeenu Viswambharan 51*21b818c0SJeenu Viswambharan idx = EHF_PRI_TO_IDX(priority, exception_data.pri_bits); 52*21b818c0SJeenu Viswambharan assert((idx >= 0) && (idx < exception_data.num_priorities)); 53*21b818c0SJeenu Viswambharan assert(IS_IDX_VALID(idx)); 54*21b818c0SJeenu Viswambharan 55*21b818c0SJeenu Viswambharan return idx; 56*21b818c0SJeenu Viswambharan } 57*21b818c0SJeenu Viswambharan 58*21b818c0SJeenu Viswambharan /* Return whether there are outstanding priority activation */ 59*21b818c0SJeenu Viswambharan static int has_valid_pri_activations(pe_exc_data_t *pe_data) 60*21b818c0SJeenu Viswambharan { 61*21b818c0SJeenu Viswambharan return pe_data->active_pri_bits != 0; 62*21b818c0SJeenu Viswambharan } 63*21b818c0SJeenu Viswambharan 64*21b818c0SJeenu Viswambharan static pe_exc_data_t *this_cpu_data(void) 65*21b818c0SJeenu Viswambharan { 66*21b818c0SJeenu Viswambharan return &get_cpu_data(ehf_data); 67*21b818c0SJeenu Viswambharan } 68*21b818c0SJeenu Viswambharan 69*21b818c0SJeenu Viswambharan /* 70*21b818c0SJeenu Viswambharan * Return the current priority index of this CPU. If no priority is active, 71*21b818c0SJeenu Viswambharan * return EHF_INVALID_IDX. 72*21b818c0SJeenu Viswambharan */ 73*21b818c0SJeenu Viswambharan static int get_pe_highest_active_idx(pe_exc_data_t *pe_data) 74*21b818c0SJeenu Viswambharan { 75*21b818c0SJeenu Viswambharan if (!has_valid_pri_activations(pe_data)) 76*21b818c0SJeenu Viswambharan return EHF_INVALID_IDX; 77*21b818c0SJeenu Viswambharan 78*21b818c0SJeenu Viswambharan /* Current priority is the right-most bit */ 79*21b818c0SJeenu Viswambharan return __builtin_ctz(pe_data->active_pri_bits); 80*21b818c0SJeenu Viswambharan } 81*21b818c0SJeenu Viswambharan 82*21b818c0SJeenu Viswambharan /* 83*21b818c0SJeenu Viswambharan * Mark priority active by setting the corresponding bit in active_pri_bits and 84*21b818c0SJeenu Viswambharan * programming the priority mask. 85*21b818c0SJeenu Viswambharan * 86*21b818c0SJeenu Viswambharan * This API is to be used as part of delegating to lower ELs other than for 87*21b818c0SJeenu Viswambharan * interrupts; e.g. while handling synchronous exceptions. 88*21b818c0SJeenu Viswambharan * 89*21b818c0SJeenu Viswambharan * This API is expected to be invoked before restoring context (Secure or 90*21b818c0SJeenu Viswambharan * Non-secure) in preparation for the respective dispatch. 91*21b818c0SJeenu Viswambharan */ 92*21b818c0SJeenu Viswambharan void ehf_activate_priority(unsigned int priority) 93*21b818c0SJeenu Viswambharan { 94*21b818c0SJeenu Viswambharan int idx, cur_pri_idx; 95*21b818c0SJeenu Viswambharan unsigned int old_mask, run_pri; 96*21b818c0SJeenu Viswambharan pe_exc_data_t *pe_data = this_cpu_data(); 97*21b818c0SJeenu Viswambharan 98*21b818c0SJeenu Viswambharan /* 99*21b818c0SJeenu Viswambharan * Query interrupt controller for the running priority, or idle priority 100*21b818c0SJeenu Viswambharan * if no interrupts are being handled. The requested priority must be 101*21b818c0SJeenu Viswambharan * less (higher priority) than the active running priority. 102*21b818c0SJeenu Viswambharan */ 103*21b818c0SJeenu Viswambharan run_pri = plat_ic_get_running_priority(); 104*21b818c0SJeenu Viswambharan if (priority >= run_pri) { 105*21b818c0SJeenu Viswambharan ERROR("Running priority higher (0x%x) than requested (0x%x)\n", 106*21b818c0SJeenu Viswambharan run_pri, priority); 107*21b818c0SJeenu Viswambharan panic(); 108*21b818c0SJeenu Viswambharan } 109*21b818c0SJeenu Viswambharan 110*21b818c0SJeenu Viswambharan /* 111*21b818c0SJeenu Viswambharan * If there were priority activations already, the requested priority 112*21b818c0SJeenu Viswambharan * must be less (higher priority) than the current highest priority 113*21b818c0SJeenu Viswambharan * activation so far. 114*21b818c0SJeenu Viswambharan */ 115*21b818c0SJeenu Viswambharan cur_pri_idx = get_pe_highest_active_idx(pe_data); 116*21b818c0SJeenu Viswambharan idx = pri_to_idx(priority); 117*21b818c0SJeenu Viswambharan if ((cur_pri_idx != EHF_INVALID_IDX) && (idx >= cur_pri_idx)) { 118*21b818c0SJeenu Viswambharan ERROR("Activation priority mismatch: req=0x%x current=0x%x\n", 119*21b818c0SJeenu Viswambharan priority, IDX_TO_PRI(cur_pri_idx)); 120*21b818c0SJeenu Viswambharan panic(); 121*21b818c0SJeenu Viswambharan } 122*21b818c0SJeenu Viswambharan 123*21b818c0SJeenu Viswambharan /* Set the bit corresponding to the requested priority */ 124*21b818c0SJeenu Viswambharan pe_data->active_pri_bits |= PRI_BIT(idx); 125*21b818c0SJeenu Viswambharan 126*21b818c0SJeenu Viswambharan /* 127*21b818c0SJeenu Viswambharan * Program priority mask for the activated level. Check that the new 128*21b818c0SJeenu Viswambharan * priority mask is setting a higher priority level than the existing 129*21b818c0SJeenu Viswambharan * mask. 130*21b818c0SJeenu Viswambharan */ 131*21b818c0SJeenu Viswambharan old_mask = plat_ic_set_priority_mask(priority); 132*21b818c0SJeenu Viswambharan if (priority >= old_mask) { 133*21b818c0SJeenu Viswambharan ERROR("Requested priority (0x%x) lower than Priority Mask (0x%x)\n", 134*21b818c0SJeenu Viswambharan priority, old_mask); 135*21b818c0SJeenu Viswambharan panic(); 136*21b818c0SJeenu Viswambharan } 137*21b818c0SJeenu Viswambharan 138*21b818c0SJeenu Viswambharan /* 139*21b818c0SJeenu Viswambharan * If this is the first activation, save the priority mask. This will be 140*21b818c0SJeenu Viswambharan * restored after the last deactivation. 141*21b818c0SJeenu Viswambharan */ 142*21b818c0SJeenu Viswambharan if (cur_pri_idx == EHF_INVALID_IDX) 143*21b818c0SJeenu Viswambharan pe_data->init_pri_mask = old_mask; 144*21b818c0SJeenu Viswambharan 145*21b818c0SJeenu Viswambharan EHF_LOG("activate prio=%d\n", get_pe_highest_active_idx(pe_data)); 146*21b818c0SJeenu Viswambharan } 147*21b818c0SJeenu Viswambharan 148*21b818c0SJeenu Viswambharan /* 149*21b818c0SJeenu Viswambharan * Mark priority inactive by clearing the corresponding bit in active_pri_bits, 150*21b818c0SJeenu Viswambharan * and programming the priority mask. 151*21b818c0SJeenu Viswambharan * 152*21b818c0SJeenu Viswambharan * This API is expected to be used as part of delegating to to lower ELs other 153*21b818c0SJeenu Viswambharan * than for interrupts; e.g. while handling synchronous exceptions. 154*21b818c0SJeenu Viswambharan * 155*21b818c0SJeenu Viswambharan * This API is expected to be invoked after saving context (Secure or 156*21b818c0SJeenu Viswambharan * Non-secure), having concluded the respective dispatch. 157*21b818c0SJeenu Viswambharan */ 158*21b818c0SJeenu Viswambharan void ehf_deactivate_priority(unsigned int priority) 159*21b818c0SJeenu Viswambharan { 160*21b818c0SJeenu Viswambharan int idx, cur_pri_idx; 161*21b818c0SJeenu Viswambharan pe_exc_data_t *pe_data = this_cpu_data(); 162*21b818c0SJeenu Viswambharan unsigned int old_mask, run_pri; 163*21b818c0SJeenu Viswambharan 164*21b818c0SJeenu Viswambharan /* 165*21b818c0SJeenu Viswambharan * Query interrupt controller for the running priority, or idle priority 166*21b818c0SJeenu Viswambharan * if no interrupts are being handled. The requested priority must be 167*21b818c0SJeenu Viswambharan * less (higher priority) than the active running priority. 168*21b818c0SJeenu Viswambharan */ 169*21b818c0SJeenu Viswambharan run_pri = plat_ic_get_running_priority(); 170*21b818c0SJeenu Viswambharan if (priority >= run_pri) { 171*21b818c0SJeenu Viswambharan ERROR("Running priority higher (0x%x) than requested (0x%x)\n", 172*21b818c0SJeenu Viswambharan run_pri, priority); 173*21b818c0SJeenu Viswambharan panic(); 174*21b818c0SJeenu Viswambharan } 175*21b818c0SJeenu Viswambharan 176*21b818c0SJeenu Viswambharan /* 177*21b818c0SJeenu Viswambharan * Deactivation is allowed only when there are priority activations, and 178*21b818c0SJeenu Viswambharan * the deactivation priority level must match the current activated 179*21b818c0SJeenu Viswambharan * priority. 180*21b818c0SJeenu Viswambharan */ 181*21b818c0SJeenu Viswambharan cur_pri_idx = get_pe_highest_active_idx(pe_data); 182*21b818c0SJeenu Viswambharan idx = pri_to_idx(priority); 183*21b818c0SJeenu Viswambharan if ((cur_pri_idx == EHF_INVALID_IDX) || (idx != cur_pri_idx)) { 184*21b818c0SJeenu Viswambharan ERROR("Deactivation priority mismatch: req=0x%x current=0x%x\n", 185*21b818c0SJeenu Viswambharan priority, IDX_TO_PRI(cur_pri_idx)); 186*21b818c0SJeenu Viswambharan panic(); 187*21b818c0SJeenu Viswambharan } 188*21b818c0SJeenu Viswambharan 189*21b818c0SJeenu Viswambharan /* Clear bit corresponding to highest priority */ 190*21b818c0SJeenu Viswambharan pe_data->active_pri_bits &= (pe_data->active_pri_bits - 1); 191*21b818c0SJeenu Viswambharan 192*21b818c0SJeenu Viswambharan /* 193*21b818c0SJeenu Viswambharan * Restore priority mask corresponding to the next priority, or the 194*21b818c0SJeenu Viswambharan * one stashed earlier if there are no more to deactivate. 195*21b818c0SJeenu Viswambharan */ 196*21b818c0SJeenu Viswambharan idx = get_pe_highest_active_idx(pe_data); 197*21b818c0SJeenu Viswambharan if (idx == EHF_INVALID_IDX) 198*21b818c0SJeenu Viswambharan old_mask = plat_ic_set_priority_mask(pe_data->init_pri_mask); 199*21b818c0SJeenu Viswambharan else 200*21b818c0SJeenu Viswambharan old_mask = plat_ic_set_priority_mask(priority); 201*21b818c0SJeenu Viswambharan 202*21b818c0SJeenu Viswambharan if (old_mask >= priority) { 203*21b818c0SJeenu Viswambharan ERROR("Deactivation priority (0x%x) lower than Priority Mask (0x%x)\n", 204*21b818c0SJeenu Viswambharan priority, old_mask); 205*21b818c0SJeenu Viswambharan panic(); 206*21b818c0SJeenu Viswambharan } 207*21b818c0SJeenu Viswambharan 208*21b818c0SJeenu Viswambharan EHF_LOG("deactivate prio=%d\n", get_pe_highest_active_idx(pe_data)); 209*21b818c0SJeenu Viswambharan } 210*21b818c0SJeenu Viswambharan 211*21b818c0SJeenu Viswambharan /* 212*21b818c0SJeenu Viswambharan * Top-level EL3 interrupt handler. 213*21b818c0SJeenu Viswambharan */ 214*21b818c0SJeenu Viswambharan static uint64_t ehf_el3_interrupt_handler(uint32_t id, uint32_t flags, 215*21b818c0SJeenu Viswambharan void *handle, void *cookie) 216*21b818c0SJeenu Viswambharan { 217*21b818c0SJeenu Viswambharan int pri, idx, intr, intr_raw, ret = 0; 218*21b818c0SJeenu Viswambharan ehf_handler_t handler; 219*21b818c0SJeenu Viswambharan 220*21b818c0SJeenu Viswambharan /* 221*21b818c0SJeenu Viswambharan * Top-level interrupt type handler from Interrupt Management Framework 222*21b818c0SJeenu Viswambharan * doesn't acknowledge the interrupt; so the interrupt ID must be 223*21b818c0SJeenu Viswambharan * invalid. 224*21b818c0SJeenu Viswambharan */ 225*21b818c0SJeenu Viswambharan assert(id == INTR_ID_UNAVAILABLE); 226*21b818c0SJeenu Viswambharan 227*21b818c0SJeenu Viswambharan /* 228*21b818c0SJeenu Viswambharan * Acknowledge interrupt. Proceed with handling only for valid interrupt 229*21b818c0SJeenu Viswambharan * IDs. This situation may arise because of Interrupt Management 230*21b818c0SJeenu Viswambharan * Framework identifying an EL3 interrupt, but before it's been 231*21b818c0SJeenu Viswambharan * acknowledged here, the interrupt was either deasserted, or there was 232*21b818c0SJeenu Viswambharan * a higher-priority interrupt of another type. 233*21b818c0SJeenu Viswambharan */ 234*21b818c0SJeenu Viswambharan intr_raw = plat_ic_acknowledge_interrupt(); 235*21b818c0SJeenu Viswambharan intr = plat_ic_get_interrupt_id(intr_raw); 236*21b818c0SJeenu Viswambharan if (intr == INTR_ID_UNAVAILABLE) 237*21b818c0SJeenu Viswambharan return 0; 238*21b818c0SJeenu Viswambharan 239*21b818c0SJeenu Viswambharan /* Having acknowledged the interrupt, get the running priority */ 240*21b818c0SJeenu Viswambharan pri = plat_ic_get_running_priority(); 241*21b818c0SJeenu Viswambharan 242*21b818c0SJeenu Viswambharan /* Check EL3 interrupt priority is in secure range */ 243*21b818c0SJeenu Viswambharan assert(IS_PRI_SECURE(pri)); 244*21b818c0SJeenu Viswambharan 245*21b818c0SJeenu Viswambharan /* 246*21b818c0SJeenu Viswambharan * Translate the priority to a descriptor index. We do this by masking 247*21b818c0SJeenu Viswambharan * and shifting the running priority value (platform-supplied). 248*21b818c0SJeenu Viswambharan */ 249*21b818c0SJeenu Viswambharan idx = pri_to_idx(pri); 250*21b818c0SJeenu Viswambharan 251*21b818c0SJeenu Viswambharan /* Validate priority */ 252*21b818c0SJeenu Viswambharan assert(pri == IDX_TO_PRI(idx)); 253*21b818c0SJeenu Viswambharan 254*21b818c0SJeenu Viswambharan handler = RAW_HANDLER(exception_data.ehf_priorities[idx].ehf_handler); 255*21b818c0SJeenu Viswambharan if (!handler) { 256*21b818c0SJeenu Viswambharan ERROR("No EL3 exception handler for priority 0x%x\n", 257*21b818c0SJeenu Viswambharan IDX_TO_PRI(idx)); 258*21b818c0SJeenu Viswambharan panic(); 259*21b818c0SJeenu Viswambharan } 260*21b818c0SJeenu Viswambharan 261*21b818c0SJeenu Viswambharan /* 262*21b818c0SJeenu Viswambharan * Call registered handler. Pass the raw interrupt value to registered 263*21b818c0SJeenu Viswambharan * handlers. 264*21b818c0SJeenu Viswambharan */ 265*21b818c0SJeenu Viswambharan ret = handler(intr_raw, flags, handle, cookie); 266*21b818c0SJeenu Viswambharan 267*21b818c0SJeenu Viswambharan return ret; 268*21b818c0SJeenu Viswambharan } 269*21b818c0SJeenu Viswambharan 270*21b818c0SJeenu Viswambharan /* 271*21b818c0SJeenu Viswambharan * Initialize the EL3 exception handling. 272*21b818c0SJeenu Viswambharan */ 273*21b818c0SJeenu Viswambharan void ehf_init(void) 274*21b818c0SJeenu Viswambharan { 275*21b818c0SJeenu Viswambharan unsigned int flags = 0; 276*21b818c0SJeenu Viswambharan int ret __unused; 277*21b818c0SJeenu Viswambharan 278*21b818c0SJeenu Viswambharan /* Ensure EL3 interrupts are supported */ 279*21b818c0SJeenu Viswambharan assert(plat_ic_has_interrupt_type(INTR_TYPE_EL3)); 280*21b818c0SJeenu Viswambharan 281*21b818c0SJeenu Viswambharan /* 282*21b818c0SJeenu Viswambharan * Make sure that priority water mark has enough bits to represent the 283*21b818c0SJeenu Viswambharan * whole priority array. 284*21b818c0SJeenu Viswambharan */ 285*21b818c0SJeenu Viswambharan assert(exception_data.num_priorities <= (sizeof(ehf_pri_bits_t) * 8)); 286*21b818c0SJeenu Viswambharan 287*21b818c0SJeenu Viswambharan assert(exception_data.ehf_priorities); 288*21b818c0SJeenu Viswambharan 289*21b818c0SJeenu Viswambharan /* 290*21b818c0SJeenu Viswambharan * Bit 7 of GIC priority must be 0 for secure interrupts. This means 291*21b818c0SJeenu Viswambharan * platforms must use at least 1 of the remaining 7 bits. 292*21b818c0SJeenu Viswambharan */ 293*21b818c0SJeenu Viswambharan assert((exception_data.pri_bits >= 1) || (exception_data.pri_bits < 8)); 294*21b818c0SJeenu Viswambharan 295*21b818c0SJeenu Viswambharan /* Route EL3 interrupts when in Secure and Non-secure. */ 296*21b818c0SJeenu Viswambharan set_interrupt_rm_flag(flags, NON_SECURE); 297*21b818c0SJeenu Viswambharan set_interrupt_rm_flag(flags, SECURE); 298*21b818c0SJeenu Viswambharan 299*21b818c0SJeenu Viswambharan /* Register handler for EL3 interrupts */ 300*21b818c0SJeenu Viswambharan ret = register_interrupt_type_handler(INTR_TYPE_EL3, 301*21b818c0SJeenu Viswambharan ehf_el3_interrupt_handler, flags); 302*21b818c0SJeenu Viswambharan assert(ret == 0); 303*21b818c0SJeenu Viswambharan } 304*21b818c0SJeenu Viswambharan 305*21b818c0SJeenu Viswambharan /* 306*21b818c0SJeenu Viswambharan * Register a handler at the supplied priority. Registration is allowed only if 307*21b818c0SJeenu Viswambharan * a handler hasn't been registered before, or one wasn't provided at build 308*21b818c0SJeenu Viswambharan * time. The priority for which the handler is being registered must also accord 309*21b818c0SJeenu Viswambharan * with the platform-supplied data. 310*21b818c0SJeenu Viswambharan */ 311*21b818c0SJeenu Viswambharan void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler) 312*21b818c0SJeenu Viswambharan { 313*21b818c0SJeenu Viswambharan int idx; 314*21b818c0SJeenu Viswambharan 315*21b818c0SJeenu Viswambharan /* Sanity check for handler */ 316*21b818c0SJeenu Viswambharan assert(handler != NULL); 317*21b818c0SJeenu Viswambharan 318*21b818c0SJeenu Viswambharan /* Handler ought to be 4-byte aligned */ 319*21b818c0SJeenu Viswambharan assert((((uintptr_t) handler) & 3) == 0); 320*21b818c0SJeenu Viswambharan 321*21b818c0SJeenu Viswambharan /* Ensure we register for valid priority */ 322*21b818c0SJeenu Viswambharan idx = pri_to_idx(pri); 323*21b818c0SJeenu Viswambharan assert(idx < exception_data.num_priorities); 324*21b818c0SJeenu Viswambharan assert(IDX_TO_PRI(idx) == pri); 325*21b818c0SJeenu Viswambharan 326*21b818c0SJeenu Viswambharan /* Return failure if a handler was already registered */ 327*21b818c0SJeenu Viswambharan if (exception_data.ehf_priorities[idx].ehf_handler != _EHF_NO_HANDLER) { 328*21b818c0SJeenu Viswambharan ERROR("Handler already registered for priority 0x%x\n", pri); 329*21b818c0SJeenu Viswambharan panic(); 330*21b818c0SJeenu Viswambharan } 331*21b818c0SJeenu Viswambharan 332*21b818c0SJeenu Viswambharan /* 333*21b818c0SJeenu Viswambharan * Install handler, and retain the valid bit. We assume that the handler 334*21b818c0SJeenu Viswambharan * is 4-byte aligned, which is usually the case. 335*21b818c0SJeenu Viswambharan */ 336*21b818c0SJeenu Viswambharan exception_data.ehf_priorities[idx].ehf_handler = 337*21b818c0SJeenu Viswambharan (((uintptr_t) handler) | _EHF_PRI_VALID); 338*21b818c0SJeenu Viswambharan 339*21b818c0SJeenu Viswambharan EHF_LOG("register pri=0x%x handler=%p\n", pri, handler); 340*21b818c0SJeenu Viswambharan } 341