diff options
Diffstat (limited to 'big-little/switcher/context/gic.c')
-rw-r--r-- | big-little/switcher/context/gic.c | 369 |
1 files changed, 186 insertions, 183 deletions
diff --git a/big-little/switcher/context/gic.c b/big-little/switcher/context/gic.c index 6dfc87f..5ae13a7 100644 --- a/big-little/switcher/context/gic.c +++ b/big-little/switcher/context/gic.c @@ -18,45 +18,45 @@ * contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. - */ + */ #include "virt_helpers.h" #include "misc.h" struct set_and_clear_regs { - volatile unsigned int set[32], clear[32]; + volatile unsigned int set[32], clear[32]; }; typedef struct { - /* 0x000 */ volatile unsigned int control; - const unsigned int controller_type; - const unsigned int implementer; - const char padding1[116]; - /* 0x080 */ volatile unsigned int security[32]; - /* 0x100 */ struct set_and_clear_regs enable; - /* 0x200 */ struct set_and_clear_regs pending; - /* 0x300 */ struct set_and_clear_regs active; - /* 0x400 */ volatile unsigned int priority[256]; - /* 0x800 */ volatile unsigned int target[256]; - /* 0xC00 */ volatile unsigned int configuration[64]; - /* 0xD00 */ const char padding3[512]; - /* 0xF00 */ volatile unsigned int software_interrupt; - const char padding4[12]; - /* 0xF10 */ volatile unsigned int sgi_clr_pending[4]; - /* 0xF20 */ volatile unsigned int sgi_set_pending[4]; - const char padding5[176]; - /* 0xFE0 */ unsigned const int peripheral_id[4]; - /* 0xFF0 */ unsigned const int primecell_id[4]; + /* 0x000 */ volatile unsigned int control; + const unsigned int controller_type; + const unsigned int implementer; + const char padding1[116]; + /* 0x080 */ volatile unsigned int security[32]; + /* 0x100 */ struct set_and_clear_regs enable; + /* 0x200 */ struct set_and_clear_regs pending; + /* 0x300 */ struct set_and_clear_regs active; + /* 0x400 */ volatile unsigned int priority[256]; + /* 0x800 */ volatile unsigned int target[256]; + /* 0xC00 */ volatile unsigned int configuration[64]; + /* 0xD00 */ const char padding3[512]; + /* 0xF00 */ volatile unsigned int software_interrupt; + const char padding4[12]; + /* 0xF10 */ volatile unsigned int sgi_clr_pending[4]; + /* 0xF20 */ volatile unsigned int sgi_set_pending[4]; + const char padding5[176]; + /* 0xFE0 */ unsigned const int peripheral_id[4]; + /* 0xFF0 */ unsigned const int primecell_id[4]; } interrupt_distributor; typedef struct { - /* 0x00 */ volatile unsigned int control; - /* 0x04 */ volatile unsigned int priority_mask; - /* 0x08 */ volatile unsigned int binary_point; - /* 0x0c */ volatile unsigned const int interrupt_ack; - /* 0x10 */ volatile unsigned int end_of_interrupt; - /* 0x14 */ volatile unsigned const int running_priority; - /* 0x18 */ volatile unsigned const int highest_pending; + /* 0x00 */ volatile unsigned int control; + /* 0x04 */ volatile unsigned int priority_mask; + /* 0x08 */ volatile unsigned int binary_point; + /* 0x0c */ volatile unsigned const int interrupt_ack; + /* 0x10 */ volatile unsigned int end_of_interrupt; + /* 0x14 */ volatile unsigned const int running_priority; + /* 0x18 */ volatile unsigned const int highest_pending; } cpu_interface; /* @@ -65,11 +65,11 @@ typedef struct { */ void save_gic_interface(unsigned int *pointer, unsigned gic_interface_address) { - cpu_interface *ci = (cpu_interface *) gic_interface_address; + cpu_interface *ci = (cpu_interface *) gic_interface_address; - pointer[0] = ci->control; - pointer[1] = ci->priority_mask; - pointer[2] = ci->binary_point; + pointer[0] = ci->control; + pointer[1] = ci->priority_mask; + pointer[2] = ci->binary_point; } @@ -79,55 +79,55 @@ void save_gic_interface(unsigned int *pointer, unsigned gic_interface_address) * Requires 19 words of memory */ int save_gic_distributor_private(unsigned int *pointer, - unsigned gic_distributor_address) + unsigned gic_distributor_address) { - interrupt_distributor *id = - (interrupt_distributor *) gic_distributor_address; - unsigned int *ptr = 0x0; - - *pointer = id->enable.set[0]; - ++pointer; - memcpy((void *) pointer, (const void *) id->priority, 8 << 2); - pointer += 8; - memcpy((void *) pointer, (const void *) id->target, 8 << 2); - pointer += 8; - - /* Save just the PPI configurations (SGIs are not configurable) */ - *pointer = id->configuration[1]; - ++pointer; - - /* - * Private peripheral interrupts need to be replayed on - * the destination cpu interface for consistency. This - * is the responsibility of the peripheral driver. When - * it sees a pending interrupt while saving its context - * it should record enough information to recreate the - * interrupt while restoring. - * We don't save the Pending/Active status and clear it - * so that it does not interfere when we are back. - */ - id->pending.clear[0] = 0xffffffff; - id->active.clear[0] = 0xffffffff; - - /* - * IPIs are different and can be replayed just by saving - * and restoring the set/clear pending registers - */ - ptr = pointer; - memcpy((void *) pointer, (const void *) id->sgi_set_pending, 4 << 2); - pointer += 8; - - /* - * Clear the pending SGIs on this cpuif so that they don't - * interfere with the wfi later on. - */ - memcpy((void *) id->sgi_clr_pending, (const void *) ptr, 4 << 2); - - if (*pointer) { - return -1; - } else { - return 0; - } + interrupt_distributor *id = + (interrupt_distributor *) gic_distributor_address; + unsigned int *ptr = 0x0; + + *pointer = id->enable.set[0]; + ++pointer; + memcpy((void *)pointer, (const void *)id->priority, 8 << 2); + pointer += 8; + memcpy((void *)pointer, (const void *)id->target, 8 << 2); + pointer += 8; + + /* Save just the PPI configurations (SGIs are not configurable) */ + *pointer = id->configuration[1]; + ++pointer; + + /* + * Private peripheral interrupts need to be replayed on + * the destination cpu interface for consistency. This + * is the responsibility of the peripheral driver. When + * it sees a pending interrupt while saving its context + * it should record enough information to recreate the + * interrupt while restoring. + * We don't save the Pending/Active status and clear it + * so that it does not interfere when we are back. + */ + id->pending.clear[0] = 0xffffffff; + id->active.clear[0] = 0xffffffff; + + /* + * IPIs are different and can be replayed just by saving + * and restoring the set/clear pending registers + */ + ptr = pointer; + memcpy((void *)pointer, (const void *)id->sgi_set_pending, 4 << 2); + pointer += 8; + + /* + * Clear the pending SGIs on this cpuif so that they don't + * interfere with the wfi later on. + */ + memcpy((void *)id->sgi_clr_pending, (const void *)ptr, 4 << 2); + + if (*pointer) { + return -1; + } else { + return 0; + } } /* @@ -136,89 +136,90 @@ int save_gic_distributor_private(unsigned int *pointer, * Returns non-zero if an SPI interrupt is pending (after saving all required context) */ int save_gic_distributor_shared(unsigned int *pointer, - unsigned gic_distributor_address) + unsigned gic_distributor_address) { - int retval = 0; - interrupt_distributor *id = - (interrupt_distributor *) gic_distributor_address; - unsigned num_spis = 0; - - /* Calculate how many SPIs the GIC supports */ - num_spis = 32 * (id->controller_type & 0x1f); - - /* Save rest of GIC configuration */ - if (num_spis) { - memcpy((void *) pointer, (const void *) (id->target + 8), (num_spis / 4) << 2); - pointer += num_spis / 4; - } - - /* Save control register */ - *pointer = id->control; - ++pointer; - - return retval; + int retval = 0; + interrupt_distributor *id = + (interrupt_distributor *) gic_distributor_address; + unsigned num_spis = 0; + + /* Calculate how many SPIs the GIC supports */ + num_spis = 32 * (id->controller_type & 0x1f); + + /* Save rest of GIC configuration */ + if (num_spis) { + memcpy((void *)pointer, (const void *)(id->target + 8), + (num_spis / 4) << 2); + pointer += num_spis / 4; + } + + /* Save control register */ + *pointer = id->control; + ++pointer; + + return retval; } void restore_gic_interface(unsigned int *pointer, - unsigned gic_interface_address) + unsigned gic_interface_address) { - cpu_interface *ci = (cpu_interface *) gic_interface_address; + cpu_interface *ci = (cpu_interface *) gic_interface_address; - ci->priority_mask = pointer[1]; - ci->binary_point = pointer[2]; + ci->priority_mask = pointer[1]; + ci->binary_point = pointer[2]; - /* Restore control register last */ - ci->control = pointer[0]; + /* Restore control register last */ + ci->control = pointer[0]; } void restore_gic_distributor_private(unsigned int *pointer, - unsigned gic_distributor_address) + unsigned gic_distributor_address) { - interrupt_distributor *id = - (interrupt_distributor *) gic_distributor_address; - unsigned ctr, prev_val = 0, prev_ctr = 0; - - id->enable.set[0] = *pointer; - ++pointer; - - memcpy((void *) id->priority, (const void *) pointer, 8 << 2); - pointer += 8; - memcpy((void *) id->target, (const void *) pointer, 8 << 2); - pointer += 8; - - /* Restore just the PPI configurations (SGIs are not configurable) */ - id->configuration[1] = *pointer; - ++pointer; - - /* - * Clear active and pending PPIs as they will be recreated by the - * peripiherals - */ - id->active.clear[0] = 0xffffffff; - id->pending.clear[0] = 0xffffffff; - - /* - * Restore pending IPIs - */ - for (ctr = 0; ctr < 4; ctr++) { - if(!pointer[ctr]) - continue; - - if(pointer[ctr] == prev_val) { - pointer[ctr] = pointer[prev_ctr]; - } else { - prev_val = pointer[ctr]; - prev_ctr = ctr; - remap_cpuif(&pointer[ctr]); - } - } - - memcpy((void *) id->sgi_set_pending, (const void *) pointer, 4 << 2); - pointer += 4; - - id->pending.set[0] = *pointer; - - return; + interrupt_distributor *id = + (interrupt_distributor *) gic_distributor_address; + unsigned ctr, prev_val = 0, prev_ctr = 0; + + id->enable.set[0] = *pointer; + ++pointer; + + memcpy((void *)id->priority, (const void *)pointer, 8 << 2); + pointer += 8; + memcpy((void *)id->target, (const void *)pointer, 8 << 2); + pointer += 8; + + /* Restore just the PPI configurations (SGIs are not configurable) */ + id->configuration[1] = *pointer; + ++pointer; + + /* + * Clear active and pending PPIs as they will be recreated by the + * peripiherals + */ + id->active.clear[0] = 0xffffffff; + id->pending.clear[0] = 0xffffffff; + + /* + * Restore pending IPIs + */ + for (ctr = 0; ctr < 4; ctr++) { + if (!pointer[ctr]) + continue; + + if (pointer[ctr] == prev_val) { + pointer[ctr] = pointer[prev_ctr]; + } else { + prev_val = pointer[ctr]; + prev_ctr = ctr; + remap_cpuif(&pointer[ctr]); + } + } + + memcpy((void *)id->sgi_set_pending, (const void *)pointer, 4 << 2); + pointer += 4; + + id->pending.set[0] = *pointer; + + return; } /* @@ -229,36 +230,38 @@ void restore_gic_distributor_private(unsigned int *pointer, * critical path. */ void restore_gic_distributor_shared(unsigned int *pointer, - unsigned gic_distributor_address) + unsigned gic_distributor_address) { - interrupt_distributor *id = - (interrupt_distributor *) gic_distributor_address; - unsigned num_spis; - unsigned ctr, prev_val = 0, prev_ctr = 0; - - /* Calculate how many SPIs the GIC supports */ - num_spis = 32 * ((id->controller_type) & 0x1f); - - /* Restore rest of GIC configuration */ - if (num_spis) { - - memcpy((void *) pointer, (const void *) (id->target + 8), (num_spis / 4) << 2); - - for (ctr = 0; ctr < num_spis / 4; ctr++) { - if(!pointer[ctr]) - continue; - - if(pointer[ctr] == prev_val) { - pointer[ctr] = pointer[prev_ctr]; - } else { - prev_val = pointer[ctr]; - prev_ctr = ctr; - remap_cpuif(&pointer[ctr]); - } - } - - memcpy((void *) (id->target + 8), (const void *) pointer, (num_spis / 4) << 2); - } - - return; + interrupt_distributor *id = + (interrupt_distributor *) gic_distributor_address; + unsigned num_spis; + unsigned ctr, prev_val = 0, prev_ctr = 0; + + /* Calculate how many SPIs the GIC supports */ + num_spis = 32 * ((id->controller_type) & 0x1f); + + /* Restore rest of GIC configuration */ + if (num_spis) { + + memcpy((void *)pointer, (const void *)(id->target + 8), + (num_spis / 4) << 2); + + for (ctr = 0; ctr < num_spis / 4; ctr++) { + if (!pointer[ctr]) + continue; + + if (pointer[ctr] == prev_val) { + pointer[ctr] = pointer[prev_ctr]; + } else { + prev_val = pointer[ctr]; + prev_ctr = ctr; + remap_cpuif(&pointer[ctr]); + } + } + + memcpy((void *)(id->target + 8), (const void *)pointer, + (num_spis / 4) << 2); + } + + return; } |