diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h new file mode 100644 index 00000000..31fdb2ef --- /dev/null +++ b/arch/x86/include/asm/icc.h @@ -0,0 +1,63 @@ +/* + * 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) +#define ICC_TYPE_PINGREQUEST (1 << 2) +#define ICC_TYPE_PINGRESPONSE (1 << 3) + +int icc_init(void); +int icc_ping(); +void icc_check(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 53% rename from arch/x86/scc/scc_init.c rename to arch/x86/scc/icc.c index d9f2628a..58a89be5 100644 --- a/arch/x86/scc/scc_init.c +++ b/arch/x86/scc/icc.c @@ -17,17 +17,22 @@ #include #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 +/* 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). * @@ -67,10 +72,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 +113,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 +123,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 +135,102 @@ int scc_init(void) return 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(); + + // 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 +#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..5329fc61 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 + icc_check(); +#endif + + irq_nested_enable(flags); +} + #ifdef __cplusplus } #endif diff --git a/include/metalsvm/time.h b/include/metalsvm/time.h index 702207b9..aa47e47a 100644 --- a/include/metalsvm/time.h +++ b/include/metalsvm/time.h @@ -69,7 +69,13 @@ void timer_wait(unsigned int ticks); */ uint64_t get_clock_tick(void); -static inline void sleep(unsigned int i) { timer_wait(i*TIMER_FREQ); } +/** @brief sleep some seconds + * + * This function sleeps some seconds + * + * @paran sec Amount of seconds to wait + */ +static inline void sleep(unsigned int sec) { timer_wait(sec*TIMER_FREQ); } #ifdef __cplusplus } 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 85290fca..d849354f 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -103,6 +103,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 d7e4d4a0..88a9bfba 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -714,6 +714,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/kernel/tests.c b/kernel/tests.c index 71b91e20..b239128b 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -24,6 +24,9 @@ #include #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/hello", argv); //create_user_task(NULL, "/bin/jacobi", argv); 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