From 29ab43f28932f663a320d84800e3c2416eb87317 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 23 Apr 2011 00:13:12 -0700 Subject: [PATCH 1/2] First steps to realize Inter-Core-Communication via RCCE --- arch/x86/include/asm/icc.h | 60 ++++++++++++++++++++++++++++++ arch/x86/include/asm/processor.h | 13 ------- arch/x86/mm/page.c | 1 + arch/x86/scc/Makefile | 2 +- arch/x86/scc/{scc_init.c => icc.c} | 22 ++++++----- fs/initrd.c | 3 ++ include/metalsvm/tasks.h | 15 ++++++++ kernel/main.c | 5 ++- kernel/syscall.c | 2 + kernel/tasks.c | 2 + mm/memory.c | 3 ++ 11 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 arch/x86/include/asm/icc.h rename arch/x86/scc/{scc_init.c => icc.c} (93%) diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h new file mode 100644 index 00000000..0ce1e64f --- /dev/null +++ b/arch/x86/include/asm/icc.h @@ -0,0 +1,60 @@ +/* + * Copyright 2011 Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +/* + * Function and prototypes for MetalSVM's inter core communication + */ + +#ifndef __ARCH_ICC_H__ +#define __ARCH_ICC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_ROCKCREEK + +typedef struct { + uint32_t addr; // address of the initrd + uint32_t size; // size of the initrd + int32_t argc; // number of RCCE arguments + char** argv; // RCCE arguments +} bootinfo_t; + +extern bootinfo_t* bootinfo; + +typedef struct { + uint8_t type; + uint8_t tag; + uint32_t length; +} icc_header_t; + +#define ICC_TYPE_IP (1 << 0) +#define ICC_TYPE_SVM (1 << 1) + +int icc_init(void); +void check_icc(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index faea9d96..a1f6246a 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -39,19 +39,6 @@ extern "C" { #endif -#ifdef CONFIG_ROCKCREEK -typedef struct { - uint32_t addr; // address of the initrd - uint32_t size; // size of the initrd - int32_t argc; // number of RCCE arguments - char** argv; // RCCE arguments -} bootinfo_t; - -extern bootinfo_t* bootinfo; - -int scc_init(void); -#endif - /** @brief Read out time stamp counter * * The rdtsc asm command puts a 64 bit time stamp value diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index fe44d95d..184f8865 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -33,6 +33,7 @@ #ifdef CONFIG_ROCKCREEK #include #include +#include #endif /* diff --git a/arch/x86/scc/Makefile b/arch/x86/scc/Makefile index f32bc11f..2003a259 100644 --- a/arch/x86/scc/Makefile +++ b/arch/x86/scc/Makefile @@ -1,4 +1,4 @@ -C_source := scc_init.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c +C_source := icc.c SCC_API.c iRCCE_admin.c iRCCE_send.c iRCCE_isend.c iRCCE_irecv.c iRCCE_recv.c iRCCE_get.c iRCCE_put.c iRCCE_synch.c RCCE_malloc.c RCCE_shmalloc.c RCCE_debug.c RCCE_qsort.c RCCE_DCMflush.c RCCE_send.c RCCE_recv.c RCCE_flags.c RCCE_comm.c RCCE_put.c RCCE_get.c RCCE_synch.c RCCE_bcast.c RCCE_admin.c # RCCE_power_management.c ASM_source := MODULE := arch_x86_scc diff --git a/arch/x86/scc/scc_init.c b/arch/x86/scc/icc.c similarity index 93% rename from arch/x86/scc/scc_init.c rename to arch/x86/scc/icc.c index d9f2628a..adcd26fb 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/icc.c @@ -17,13 +17,14 @@ #include #include #include +#ifdef CONFIG_ROCKCREEK #include #include #include - -#ifdef CONFIG_ROCKCREEK +#include bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO; +static int num_ues, my_ue; /* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ #define _CR4_MPE 0x00000800 @@ -67,10 +68,9 @@ static int scc_clear(void) return 0; } -int scc_init(void) +int icc_init(void) { - int num_ranks; - int i, my_rank; + int i; uint64_t start, end, ticks, freq = 533; uint32_t cr4, msg = 0; @@ -109,9 +109,9 @@ int scc_init(void) // enable additional outputs RCCE_debug_set(RCCE_DEBUG_ALL); - my_rank = RCCE_ue(); - num_ranks = RCCE_num_ues(); - kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks); + my_ue = RCCE_ue(); + 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); @@ -119,7 +119,7 @@ int scc_init(void) RCCE_barrier(&RCCE_COMM_WORLD); kputs("RCCE test...\t"); - if (my_rank == 0) + if (my_ue == 0) msg = 0x4711; if (RCCE_bcast((char*) &msg, sizeof(msg), 0, RCCE_COMM_WORLD) == RCCE_SUCCESS) kprintf("successfull! (0x%x)\n", msg); @@ -131,4 +131,8 @@ int scc_init(void) return 0; } +void check_icc(void) +{ +} + #endif diff --git a/fs/initrd.c b/fs/initrd.c index c3094b44..a0932eff 100644 --- a/fs/initrd.c +++ b/fs/initrd.c @@ -24,6 +24,9 @@ #include #include #include +#ifdef CONFIG_ROCKCREEK +#include +#endif static vfs_node_t initrd_root; diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index 904f737a..36c9fb9a 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -32,6 +32,10 @@ #include #include #include +#include +#ifdef CONFIG_ROCKCREEK +#include +#endif #ifdef __cplusplus extern "C" { @@ -134,6 +138,17 @@ int sys_fork(void); */ int sys_execve(const char* fname, char** argv, char** env); +static inline void check_workqueues(void) +{ + uint32_t flags = irq_nested_disable(); + +#ifdef CONFIG_ROCKCREEK + check_icc(); +#endif + + irq_nested_enable(flags); +} + #ifdef __cplusplus } #endif diff --git a/kernel/main.c b/kernel/main.c index 8be29f22..0b7ef87f 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -30,6 +30,9 @@ #include #include #include +#ifdef CONFIG_ROCKCREEK +#include +#endif extern int test_init(void); @@ -90,7 +93,7 @@ int main(void) multitasking_init(); mmu_init(); #ifdef CONFIG_ROCKCREEK - scc_init(); + icc_init(); #endif initrd_init(); diff --git a/kernel/syscall.c b/kernel/syscall.c index d3ed8a41..d3eba333 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -70,6 +70,8 @@ int syscall_handler(uint32_t sys_nr, ...) int ret = -EINVAL; va_list vl; + check_workqueues(); + va_start(vl, sys_nr); switch(sys_nr) diff --git a/kernel/tasks.c b/kernel/tasks.c index 26774de7..b85f3cd1 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -710,6 +710,8 @@ void scheduler(void) unsigned int i; unsigned int new_id; + check_workqueues(); + #if MAX_CORES > 1 spinlock_irqsave_lock(&table_lock); #endif diff --git a/mm/memory.c b/mm/memory.c index 376bb81e..f70a84ee 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -29,6 +29,9 @@ #ifdef CONFIG_MULTIBOOT #include #endif +#ifdef CONFIG_ROCKCREEK +#include +#endif /* * 0 => free From 3a0e42eef1a3bdc365940872628782d23841dc0d Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 24 Apr 2011 07:27:27 -0700 Subject: [PATCH 2/2] add ping pong test and some bug fixes in the ICC part --- arch/x86/include/asm/icc.h | 9 ++-- arch/x86/scc/icc.c | 100 ++++++++++++++++++++++++++++++++++++- include/metalsvm/tasks.h | 2 +- include/metalsvm/time.h | 8 ++- kernel/tests.c | 18 +++++++ 5 files changed, 131 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h index 0ce1e64f..31fdb2ef 100644 --- a/arch/x86/include/asm/icc.h +++ b/arch/x86/include/asm/icc.h @@ -45,11 +45,14 @@ typedef struct { uint32_t length; } icc_header_t; -#define ICC_TYPE_IP (1 << 0) -#define ICC_TYPE_SVM (1 << 1) +#define ICC_TYPE_IP (1 << 0) +#define ICC_TYPE_SVM (1 << 1) +#define ICC_TYPE_PINGREQUEST (1 << 2) +#define ICC_TYPE_PINGRESPONSE (1 << 3) int icc_init(void); -void check_icc(void); +int icc_ping(); +void icc_check(void); #endif diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index adcd26fb..58a89be5 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_ROCKCREEK #include #include @@ -29,6 +30,9 @@ static int num_ues, my_ue; /* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */ #define _CR4_MPE 0x00000800 +/* maximal number of SCC's cores */ +#define MAX_SCC_CORES (NUM_ROWS*NUM_COLS*NUM_CORES) + /* * This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c). * @@ -131,8 +135,102 @@ int icc_init(void) return 0; } -void check_icc(void) +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(); + + // 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); + + // waiting for the completion + while(iRCCE_isend_test(&send_request, NULL) != iRCCE_SUCCESS) + icc_check(); // oh, we have time to check incoming requests + + irq_nested_enable(flags); + + return 0; +} + +static void interpret_header(icc_header_t* header, int recv_ue) +{ + //kprintf("Got ICC message %d from %d\n", header->type, 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*) &tsc, sizeof(uint64_t), recv_ue, NULL); + iRCCE_isend_push(); + } + 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); + } + break; + default: + kprintf("Receive unknown ICC message (%d)\n", header->type); + } +} + +/* + * By entering this function, interrupts are already disables + * => No race by using the static variables + */ +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}; + int i, ret; + + // pushes the progress of non-blocking communication requests + iRCCE_isend_push(); + iRCCE_irecv_push(); + + for(i=0; i #include #include +#ifdef CONFIG_ROCKCREEK +#include +#endif static sem_t consuming, producing; static mailbox_int32_t mbox; @@ -83,6 +86,20 @@ static int STDCALL foo(void* arg) return 42; } +#ifdef CONFIG_ROCKCREEK +static int STDCALL ping(void* arg) +{ + int i; + + for(i=0; i<20; i++) { + icc_ping(1); + sleep(1); + } + + return 0; +} +#endif + static int STDCALL join_test(void* arg) { tid_t id, ret; @@ -112,6 +129,7 @@ int test_init(void) //create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); + //create_kernel_task(NULL, ping, NULL); //create_user_task(NULL, "/bin/hello", argv); create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv);