summaryrefslogtreecommitdiff
path: root/big-little/switcher/context/gic.c
diff options
context:
space:
mode:
Diffstat (limited to 'big-little/switcher/context/gic.c')
-rw-r--r--big-little/switcher/context/gic.c369
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;
}