diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 247a55ea..3c4b621f 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -234,6 +234,9 @@ void irq_handler(struct state *s) /* This is a blank function pointer */ void (*handler) (struct state * s); + // at first, we check our work queues + check_workqueues(); + /* * Find out if we have a custom handler to run for this * IRQ and then finally, run it diff --git a/arch/x86/kernel/timer.c b/arch/x86/kernel/timer.c index 617d47d9..73c83a51 100644 --- a/arch/x86/kernel/timer.c +++ b/arch/x86/kernel/timer.c @@ -80,8 +80,15 @@ void timer_wait(unsigned int ticks) { uint64_t eticks = timer_ticks + ticks; - while (timer_ticks < eticks) + while (timer_ticks < eticks) { + check_workqueues(); + + // recheck break condition + if (timer_ticks >= eticks) + break; + reschedule(); + } } #define LATCH(f) ((CLOCK_TICK_RATE + f/2) / f) diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index 58a89be5..734898cc 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -18,8 +18,10 @@ #include #include #include +#include #ifdef CONFIG_ROCKCREEK #include +#include #include #include #include @@ -72,9 +74,20 @@ static int scc_clear(void) return 0; } +static void intr_handler(struct state *s) +{ + // reset appropriate bit in the core configuration register + int tmp, z; + + z = Z_PID(RC_COREID[my_ue]); + tmp=ReadConfigReg(CRB_OWN + (z==0 ? GLCFG0 : GLCFG1)); + tmp &= ~2; + SetConfigReg(CRB_OWN + (z==0 ? GLCFG0 : GLCFG1), tmp); +} + int icc_init(void) { - int i; + int i, z, tmp; uint64_t start, end, ticks, freq = 533; uint32_t cr4, msg = 0; @@ -117,9 +130,6 @@ int icc_init(void) num_ues = RCCE_num_ues(); kprintf("Got rank %d of %d ranks\n", my_ue, num_ues); - i = ReadConfigReg(CRB_OWN+GLCFG0); - kprintf("glcfg0 0x%x\n", i); - RCCE_barrier(&RCCE_COMM_WORLD); kputs("RCCE test...\t"); @@ -130,11 +140,60 @@ int icc_init(void) else kprintf("failed! (0x%x)\n", msg); + // reset INTR/LINT0 flag + z = Z_PID(RC_COREID[my_ue]); + tmp=ReadConfigReg(CRB_OWN + (z==0 ? GLCFG0 : GLCFG1)); + tmp &= ~2; + SetConfigReg(CRB_OWN + (z==0 ? GLCFG0 : GLCFG1), tmp); + + // set interrupt handler (INTR/LINT0) + irq_install_handler(124, intr_handler); + kputs("Now, the SCC is initialized!\n"); return 0; } +static inline int icc_send_irq(int ue) +{ + int tmp, x, y, z, addr; + + z = Z_PID(RC_COREID[ue]); + x = X_PID(RC_COREID[ue]); + y = Y_PID(RC_COREID[ue]); + addr = CRB_ADDR(x,y) + (z==0 ? GLCFG0 : GLCFG1); + + // send interrupt to ue + do { + tmp=ReadConfigReg(addr); + } while(tmp & 2); + tmp |= 2; + SetConfigReg(addr, tmp); + + return 0; +} + +int icc_halt(void) +{ + uint32_t flags; + uint32_t do_send = 1; + + do { + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + + if (do_send) + do_send = (iRCCE_isend_push() == iRCCE_PENDING); + icc_check(); + + irq_nested_enable(flags); + } while(do_send); + + HALT; + + return 0; +} + int icc_ping(int ue) { icc_header_t ping_header = {ICC_TYPE_PINGREQUEST, 0, sizeof(uint64_t)}; @@ -159,6 +218,9 @@ int icc_ping(int ue) while(iRCCE_isend_test(&send_request, NULL) != iRCCE_SUCCESS) icc_check(); // oh, we have time to check incoming requests + // wake up receiver + icc_send_irq(ue); + irq_nested_enable(flags); return 0; @@ -180,7 +242,10 @@ static void interpret_header(icc_header_t* header, int recv_ue) iRCCE_irecv_wait(&recv_req); iRCCE_isend((char*) &tsc, sizeof(uint64_t), recv_ue, NULL); - iRCCE_isend_push(); + if (iRCCE_isend_push() == iRCCE_PENDING) + iRCCE_isend_push(); + + icc_send_irq(recv_ue); } break; case ICC_TYPE_PINGRESPONSE: { @@ -206,9 +271,20 @@ void icc_check(void) { static icc_header_t header[MAX_SCC_CORES]; static iRCCE_RECV_REQUEST request[MAX_SCC_CORES]; - static int8_t pending[MAX_SCC_CORES] = {[0 ... MAX_SCC_CORES-1] = 0}; + static int8_t first_call = 1; int i, ret; + if (first_call) { + first_call = 0; + + for(i=0; i 1 spinlock_irqsave_lock(&table_lock); #endif diff --git a/kernel/tests.c b/kernel/tests.c index 72869600..5c26d41d 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -93,7 +93,7 @@ static int STDCALL ping(void* arg) for(i=0; i<20; i++) { icc_ping(1); - sleep(1); + HALT; } return 0;