[arch][arm] add ARM SMP support

-Also adds support to the following ARM-related drivers:
    dev/cache/pl310
    dev/interrupt/arm_gic
    dev/timer/arm_cortex_a9
This commit is contained in:
Travis Geiselbrecht
2015-02-16 22:55:47 -08:00
parent 16d0a96dff
commit a6f4e6ff15
16 changed files with 535 additions and 143 deletions

View File

@@ -73,10 +73,12 @@ struct int_handler_struct {
void *arg;
};
static struct int_handler_struct int_handler_table[MAX_INT];
static struct int_handler_struct int_handler_table[MAX_INT][SMP_MAX_CPUS];
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
{
uint cpu = arch_curr_cpu_num();
spin_lock_saved_state_t state;
if (vector >= MAX_INT)
@@ -85,8 +87,8 @@ void register_int_handler(unsigned int vector, int_handler handler, void *arg)
spin_lock_save(&gicd_lock, &state, GICD_LOCK_FLAGS);
if (arm_gic_interrupt_change_allowed(vector)) {
int_handler_table[vector].handler = handler;
int_handler_table[vector].arg = arg;
int_handler_table[vector][cpu].handler = handler;
int_handler_table[vector][cpu].arg = arg;
}
spin_unlock_restore(&gicd_lock, state, GICD_LOCK_FLAGS);
@@ -141,7 +143,7 @@ static void gic_set_enable(uint vector, bool enable)
GICREG(0, GICD_ICENABLER(reg)) = mask;
}
void arm_gic_init_secondary_cpu(void)
void arm_gic_init_percpu(void)
{
#if WITH_LIB_SM
GICREG(0, GICC_CTLR) = 0xb; // enable GIC0 and select fiq mode for secure
@@ -183,7 +185,7 @@ void arm_gic_init(void)
for (i = 32; i < MAX_INT; i += 32)
GICREG(0, GICD_IGROUPR(i / 32)) = ~0UL;
#endif
arm_gic_init_secondary_cpu();
arm_gic_init_percpu();
}
static status_t arm_gic_set_secure_locked(u_int irq, bool secure)
@@ -292,7 +294,8 @@ static
enum handler_return __platform_irq(struct arm_iframe *frame)
{
// get the current vector
unsigned int vector = GICREG(0, GICC_IAR) & 0x3ff;
uint32_t iar = GICREG(0, GICC_IAR);
unsigned int vector = iar & 0x3ff;
if (vector >= 0x3fe) {
// spurious
@@ -302,18 +305,22 @@ enum handler_return __platform_irq(struct arm_iframe *frame)
THREAD_STATS_INC(interrupts);
KEVLOG_IRQ_ENTER(vector);
// printf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
uint cpu = arch_curr_cpu_num();
// printf("platform_irq: iar 0x%x cpu %u spsr 0x%x, pc 0x%x, currthread %p, vector %d\n",
// iar, cpu, frame->spsr, frame->pc, get_current_thread(), vector);
// deliver the interrupt
enum handler_return ret;
ret = INT_NO_RESCHEDULE;
if (int_handler_table[vector].handler)
ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
struct int_handler_struct *handler = &int_handler_table[vector][cpu];
if (handler->handler)
ret = handler->handler(handler->arg);
GICREG(0, GICC_EOIR) = vector;
GICREG(0, GICC_EOIR) = iar;
// printf("platform_irq: exit %d\n", ret);
// printf("platform_irq: cpu %u exit %d\n", cpu, ret);
KEVLOG_IRQ_EXIT(vector);

View File

@@ -26,7 +26,7 @@
#include <sys/types.h>
void arm_gic_init(void);
void arm_gic_init_secondary_cpu(void);
void arm_gic_init_percpu(void);
enum {
/* Ignore cpu_mask and forward interrupt to all CPUs other than the current cpu */