From 098546fe2597f34f89a3c6bd22f49641fdf339f1 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 17 May 2011 08:09:40 -0700 Subject: [PATCH 1/4] fix typo in the declaration of icc_ping --- arch/x86/include/asm/icc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h index 31fdb2ef..dfc69302 100644 --- a/arch/x86/include/asm/icc.h +++ b/arch/x86/include/asm/icc.h @@ -51,9 +51,9 @@ typedef struct { #define ICC_TYPE_PINGRESPONSE (1 << 3) int icc_init(void); -int icc_ping(); +int icc_ping(int ue); void icc_check(void); - +int icc_halt(void); #endif #ifdef __cplusplus From 7970899fd1dc96f921f9702b03fd07e3024a640d Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 17 May 2011 08:12:56 -0700 Subject: [PATCH 2/4] use HALT instead of NOP8 --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index f70a84ee..c6241d52 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -118,7 +118,7 @@ int mmu_init(void) } else { kputs("Unable to initialize the memory management subsystem\n"); while(1) { - NOP8; + HALT; } } From 08f51532578871c4615ef66c870294dd4308dc6d Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 17 May 2011 08:13:20 -0700 Subject: [PATCH 3/4] add the support of inter core interrupts --- arch/x86/kernel/irq.c | 3 ++ arch/x86/kernel/timer.c | 9 +++- arch/x86/scc/icc.c | 106 +++++++++++++++++++++++++++++++++------- kernel/main.c | 4 ++ kernel/tasks.c | 2 - kernel/tests.c | 2 +- 6 files changed, 103 insertions(+), 23 deletions(-) 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; From fc17e7710de8ea49cc030806c143b7064f8a3d2e Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 18 May 2011 00:37:25 -0700 Subject: [PATCH 4/4] simplify pingpong benchmark --- arch/x86/scc/icc.c | 53 +++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index 734898cc..05292396 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -165,6 +165,7 @@ static inline int icc_send_irq(int ue) // send interrupt to ue do { + NOP1; tmp=ReadConfigReg(addr); } while(tmp & 2); tmp |= 2; @@ -194,29 +195,32 @@ int icc_halt(void) return 0; } +static volatile uint64_t ping_start = 0; +static icc_header_t ping_request = {ICC_TYPE_PINGREQUEST, 0, 0}; +static icc_header_t ping_response = {ICC_TYPE_PINGRESPONSE, 0, 0}; + int icc_ping(int ue) { - icc_header_t ping_header = {ICC_TYPE_PINGREQUEST, 0, sizeof(uint64_t)}; - uint64_t tsc; uint32_t flags; - iRCCE_SEND_REQUEST send_request; if (BUILTIN_EXPECT(ue == my_ue, 0)) return -EINVAL; if (BUILTIN_EXPECT((ue < 0) || (ue >= num_ues), 0)) return -EINVAL; - tsc = rdtsc(); + while(ping_start) { + NOP8; + } + + ping_start = rdtsc(); // iRCCE is not thread save => disable interrupts flags = irq_nested_disable(); - iRCCE_isend((char*) &ping_header, sizeof(icc_header_t), ue, NULL); - iRCCE_isend((char*) &tsc, sizeof(uint64_t), ue, &send_request); + iRCCE_isend((char*) &ping_request, sizeof(icc_header_t), ue, NULL); - // waiting for the completion - while(iRCCE_isend_test(&send_request, NULL) != iRCCE_SUCCESS) - icc_check(); // oh, we have time to check incoming requests + // wait some time + NOP8; // wake up receiver icc_send_irq(ue); @@ -233,30 +237,19 @@ static void interpret_header(icc_header_t* header, int recv_ue) switch(header->type) { case ICC_TYPE_PINGREQUEST: { - icc_header_t response = {ICC_TYPE_PINGRESPONSE, 0, sizeof(uint64_t)}; - iRCCE_RECV_REQUEST recv_req; - uint64_t tsc; - iRCCE_isend((char*) &response, sizeof(icc_header_t), recv_ue, NULL); - if (iRCCE_irecv((char*) &tsc, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS) - iRCCE_irecv_wait(&recv_req); + iRCCE_isend((char*) &ping_response, sizeof(icc_header_t), recv_ue, NULL); - iRCCE_isend((char*) &tsc, sizeof(uint64_t), recv_ue, NULL); - if (iRCCE_isend_push() == iRCCE_PENDING) - iRCCE_isend_push(); + // wait some time + NOP8; + // wake up remote core icc_send_irq(recv_ue); } break; - case ICC_TYPE_PINGRESPONSE: { - uint64_t start, end; - iRCCE_RECV_REQUEST recv_req; - - if (iRCCE_irecv((char*) &start, sizeof(uint64_t), recv_ue, &recv_req) != iRCCE_SUCCESS) - iRCCE_irecv_wait(&recv_req); - end = rdtsc(); - kprintf("Receive ping response. Ticks: %d\n", end-start); - } + case ICC_TYPE_PINGRESPONSE: + kprintf("Receive ping response. Ticks: %d\n", rdtsc()-ping_start); + ping_start = 0; break; default: kprintf("Receive unknown ICC message (%d)\n", header->type); @@ -286,7 +279,6 @@ void icc_check(void) } // pushes the progress of non-blocking communication requests - iRCCE_isend_push(); iRCCE_irecv_push(); for(i=0; i