diff --git a/arch/x86/include/asm/iRCCE.h b/arch/x86/include/asm/iRCCE.h index 8b878bfd..7c071d5b 100644 --- a/arch/x86/include/asm/iRCCE.h +++ b/arch/x86/include/asm/iRCCE.h @@ -30,12 +30,29 @@ #ifndef IRCCE_H #define IRCCE_H -#include +#include "RCCE.h" #define iRCCE_SUCCESS RCCE_SUCCESS -#define iRCCE_PENDING -1 -#define iRCCE_RESERVED -2 -#define iRCCE_NOT_ENQUEUED -3 +#define iRCCE_PENDING -1 +#define iRCCE_RESERVED -2 +#define iRCCE_NOT_ENQUEUED -3 + +#define iRCCE_ANY_SOURCE -1 + +#define iRCCE_PRIOS 5 +#define iRCCE_MAILBOX_EMPTY -2 +#define iRCCE_LAST_MAILS_NOT_RECV -3 +#define iRCCE_MAILBOX_ALL -4 +#define iRCCE_MAILBOX_OPEN 0 +#define iRCCE_MAILBOX_CLOSED 1 + +// iRCCE-mailbox-system tags +#define iRCCE_LAST_MAIL -1 +#define iRCCE_ANYLENGTH -2 +#define iRCCE_ANYLENGTH_PIGGYBACK -3 + + +typedef volatile char iRCCE_SHORT_FLAG; typedef struct _iRCCE_SEND_REQUEST { char *privbuf; // source buffer in local private memory (send buffer) @@ -94,15 +111,33 @@ typedef struct _iRCCE_WAIT_LIST { } iRCCE_WAIT_LIST; +#define iRCCE_MAIL_HEADER_PAYLOAD 13 +typedef struct _iRCCE_MAIL_HEADER { + int source; // UE that will send the header + size_t size; // size of the message which will be send/received + int tag; // tag indicating which kind of message we have + struct _iRCCE_MAIL_HEADER* next;// pointer for queue - could be replaced by list-object + char prio; // priority of the mail + iRCCE_SHORT_FLAG sent; // flag indicating that header is new + iRCCE_SHORT_FLAG closed; // flag indication that mailbox is closed + char payload[iRCCE_MAIL_HEADER_PAYLOAD]; // payload for small messages +} iRCCE_MAIL_HEADER; + +typedef struct _iRCCE_MAIL_TRASH_BIN { + iRCCE_MAIL_HEADER* first; + iRCCE_MAIL_HEADER* last; +} iRCCE_MAIL_TRASH_BIN; + /////////////////////////////////////////////////////////////// // // THE iRCCE API: // -// Initialize function: +// Initialize/Finalize functions: int iRCCE_init(void); +int iRCCE_finalize(void); // // Non-blocking send/recv functions: -int iRCCE_isend(char *, size_t, int, iRCCE_SEND_REQUEST *); +int iRCCE_isend(char *, ssize_t, int, iRCCE_SEND_REQUEST *); int iRCCE_isend_test(iRCCE_SEND_REQUEST *, int *); int iRCCE_isend_wait(iRCCE_SEND_REQUEST *); int iRCCE_isend_push(void); @@ -133,6 +168,18 @@ int iRCCE_wait_any(iRCCE_WAIT_LIST*, iRCCE_SEND_REQUEST **, iRCCE_RECV_REQUEST int iRCCE_isend_cancel(iRCCE_SEND_REQUEST *, int *); int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *, int *); // +// Blocking send/recv functions for mailbox system +int iRCCE_mail_send(size_t, int, char, char*, int); +int iRCCE_mail_recv(iRCCE_MAIL_HEADER**); +// +// functions to empty mailbox-queue and to check for last mails: +int iRCCE_mail_release(iRCCE_MAIL_HEADER**); +int iRCCE_last_mail_recv(void); +int iRCCE_mailbox_wait(void); +int iRCCE_mailbox_flush(void); +int iRCCE_mailbox_close(int); +void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER*); +// /////////////////////////////////////////////////////////////// // // Just for for convenience: diff --git a/arch/x86/include/asm/iRCCE_lib.h b/arch/x86/include/asm/iRCCE_lib.h index 0d8b4e16..372b9cdd 100644 --- a/arch/x86/include/asm/iRCCE_lib.h +++ b/arch/x86/include/asm/iRCCE_lib.h @@ -29,6 +29,23 @@ extern iRCCE_SEND_REQUEST* iRCCE_isend_queue; extern iRCCE_RECV_REQUEST* iRCCE_irecv_queue[RCCE_MAXNP]; +extern iRCCE_RECV_REQUEST* iRCCE_irecv_any_source_queue; + +// pointer to MPB-mailbox-space +extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP]; +extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP]; + +// queue for received headers +extern iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS]; + +// flags for last mail +extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP]; + +// field to store open/closed status of mailboxes +extern iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP]; + +// garbage collection for mailbox +extern iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage; #ifdef _OPENMP #pragma omp threadprivate (iRCCE_isend_queue, iRCCE_irecv_queue) #endif diff --git a/arch/x86/include/asm/icc.h b/arch/x86/include/asm/icc.h index dfc69302..9cca3390 100644 --- a/arch/x86/include/asm/icc.h +++ b/arch/x86/include/asm/icc.h @@ -39,21 +39,17 @@ typedef struct { 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) +#define ICC_TAG_IP 0 +#define ICC_TAG_SVM 1 +#define ICC_TAG_PINGREQUEST 2 +#define ICC_TAG_PINGRESPONSE 3 int icc_init(void); -int icc_ping(int ue); -void icc_check(void); int icc_halt(void); +int icc_send_irq(int ue); +void icc_mail_check(void); +int icc_mail_ping(void); + #endif #ifdef __cplusplus diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 8443ec0a..8765b7cc 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -93,6 +93,11 @@ inline static void outportl(unsigned short _port, unsigned int _data) asm volatile("outl %1, %0"::"dN"(_port), "a"(_data)); } +inline static void uart_putchar(unsigned char _data) +{ + outportb(0x2F8, _data); +} + #ifdef __cplusplus } #endif diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 3c4b621f..413c2932 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -235,7 +235,9 @@ void irq_handler(struct state *s) void (*handler) (struct state * s); // at first, we check our work queues - check_workqueues(); +// if( s->int_no == 124 ) { + check_workqueues(); +// } /* * Find out if we have a custom handler to run for this diff --git a/arch/x86/kernel/processor.c b/arch/x86/kernel/processor.c index 4210c38f..93e5f540 100644 --- a/arch/x86/kernel/processor.c +++ b/arch/x86/kernel/processor.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_ROCKCREEK #include #endif @@ -104,6 +105,8 @@ void udelay(uint32_t usecs) mb(); end = rdtsc(); diff = end > start ? end - start : start - end; + if ((diff < deadline) && (deadline - diff > 50000)) + check_workqueues(); } while(diff < deadline); } diff --git a/arch/x86/scc/Makefile b/arch/x86/scc/Makefile index 2003a259..74d355a4 100644 --- a/arch/x86/scc/Makefile +++ b/arch/x86/scc/Makefile @@ -1,4 +1,4 @@ -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 +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 iRCCE_mailbox.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/iRCCE_admin.c b/arch/x86/scc/iRCCE_admin.c index c61d66b9..2a28f09e 100644 --- a/arch/x86/scc/iRCCE_admin.c +++ b/arch/x86/scc/iRCCE_admin.c @@ -47,6 +47,27 @@ iRCCE_SEND_REQUEST* iRCCE_isend_queue; // recv request queue iRCCE_RECV_REQUEST* iRCCE_irecv_queue[RCCE_MAXNP]; +// recv request queue for those with source = iRCCE_ANY_SOURCE: +iRCCE_RECV_REQUEST* iRCCE_irecv_any_source_queue; + +// mailbox in MPB +volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP]; // store addresses for receiving headers +volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP]; // store addresses for sending headeres + +// mailbox recv queue +iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS]; + +// mail garbage queue +iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage; + +// flag indicating if last header was received +iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP]; + +// field to store open/closed status of mailboxes +iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP]; + + + //-------------------------------------------------------------------------------------- // FUNCTION: iRCCE_init //-------------------------------------------------------------------------------------- @@ -56,12 +77,55 @@ int iRCCE_init(void) { int i; for(i=0; inext; + kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) ); + } + + iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL; + return iRCCE_SUCCESS; +} #endif diff --git a/arch/x86/scc/iRCCE_irecv.c b/arch/x86/scc/iRCCE_irecv.c index e7d5ad1d..4af79efb 100644 --- a/arch/x86/scc/iRCCE_irecv.c +++ b/arch/x86/scc/iRCCE_irecv.c @@ -50,7 +50,9 @@ static int iRCCE_push_recv_request(iRCCE_RECV_REQUEST *request) { char padline[RCCE_LINE_SIZE]; // copy buffer, used if message not multiple of line size int test; // flag for calling iRCCE_test_flag() - if(request->finished) return(iRCCE_SUCCESS); + if(request->finished) { + return(iRCCE_SUCCESS); + } if(request->label == 1) goto label1; if(request->label == 2) goto label2; @@ -167,6 +169,25 @@ static void iRCCE_init_recv_request( return; } +int iRCCE_irecv_search_source() { + int i, j; + int res =iRCCE_ANY_SOURCE; + + for( i=0; inext == NULL ) { + iRCCE_irecv_any_source_queue->next = request; + } + else { + iRCCE_RECV_REQUEST* run = iRCCE_irecv_any_source_queue; + while( run->next != NULL ) run = run->next; + run->next = request; + } + } + return iRCCE_RESERVED; + } + } if (source<0 || source >= RCCE_NP) return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID)); @@ -211,10 +273,10 @@ int iRCCE_irecv(char *privbuf, size_t size, int source, iRCCE_RECV_REQUEST *requ run->next = request; } - if(request == &blocking_irecv_request) { - iRCCE_irecv_wait(request); - return(iRCCE_SUCCESS); - } + if(request == &blocking_irecv_request) { + iRCCE_irecv_wait(request); + return(iRCCE_SUCCESS); + } return(iRCCE_RESERVED); } @@ -243,29 +305,98 @@ int iRCCE_irecv_test(iRCCE_RECV_REQUEST *request, int *test) { } } - source = request->source; + // does request still have no source? + if( request->source == iRCCE_ANY_SOURCE ) { + request->source = iRCCE_irecv_search_source(); - if(request->finished) { - if (test) (*test) = 1; - return(iRCCE_SUCCESS); + if( request->source == iRCCE_ANY_SOURCE ) { + if (test) (*test) = 0; + return iRCCE_RESERVED; + } + else { // take request out of wait_any_source-list + + // find request in queue + if( request == iRCCE_irecv_any_source_queue ) { + iRCCE_irecv_any_source_queue = iRCCE_irecv_any_source_queue->next; + } + else { + iRCCE_RECV_REQUEST* run = iRCCE_irecv_any_source_queue; + while( run->next != request ) run = run->next; + run->next = request->next; + } + + request->next = NULL; + request->sent = &RCCE_sent_flag[request->source]; // set senders flag + source = request->source; + + // queue request in iRCCE_irecv_queue + if(iRCCE_irecv_queue[source] == NULL) { + + if(iRCCE_push_recv_request(request) == iRCCE_SUCCESS) { + if (test) (*test) = 1; + return(iRCCE_SUCCESS); + } + else { + iRCCE_irecv_queue[source] = request; + + if(request == &blocking_irecv_request) { + iRCCE_irecv_wait(request); + if (test) (*test) = 1; + return(iRCCE_SUCCESS); + } + if (test) (*test) = 0; + return(iRCCE_PENDING); + } + } + else { + if(iRCCE_irecv_queue[source]->next == NULL) { + iRCCE_irecv_queue[source]->next = request; + } + else { + iRCCE_RECV_REQUEST *run = iRCCE_irecv_queue[source]; + while(run->next != NULL) run = run->next; + run->next = request; + } + + if(request == &blocking_irecv_request) { + iRCCE_irecv_wait(request); + if (test) (*test) = 1; + return(iRCCE_SUCCESS); + } + + if (test) (*test) = 1; + return(iRCCE_RESERVED); + } + + + } } + else { + + source = request->source; + + if(request->finished) { + if (test) (*test) = 1; + return(iRCCE_SUCCESS); + } + + if(iRCCE_irecv_queue[source] != request) { + if (test) (*test) = 0; + return(iRCCE_RESERVED); + } + + iRCCE_push_recv_request(request); + + if(request->finished) { + iRCCE_irecv_queue[source] = request->next; + + if (test) (*test) = 1; + return(iRCCE_SUCCESS); + } - if(iRCCE_irecv_queue[source] != request) { if (test) (*test) = 0; - return(iRCCE_RESERVED); + return(iRCCE_PENDING); } - - iRCCE_push_recv_request(request); - - if(request->finished) { - iRCCE_irecv_queue[source] = request->next; - - if (test) (*test) = 1; - return(iRCCE_SUCCESS); - } - - if (test) (*test) = 0; - return(iRCCE_PENDING); } @@ -297,6 +428,40 @@ static int iRCCE_irecv_push_source(int source) { } int iRCCE_irecv_push(void) { + iRCCE_RECV_REQUEST* help_request; + + // first check sourceless requests + if( iRCCE_irecv_any_source_queue != NULL) { + while( iRCCE_irecv_any_source_queue != NULL ) { + iRCCE_irecv_any_source_queue->source = iRCCE_irecv_search_source(); + + if( iRCCE_irecv_any_source_queue->source == iRCCE_ANY_SOURCE ) { + + break; + } + // source found for first request in iRCCE_irecv_any_source_queue + else { + // set senders flag + iRCCE_irecv_any_source_queue->sent = &RCCE_sent_flag[iRCCE_irecv_any_source_queue->source]; + + // take request out of irecv_any_source_queue + help_request = iRCCE_irecv_any_source_queue; + iRCCE_irecv_any_source_queue = iRCCE_irecv_any_source_queue->next; + help_request->next = NULL; + + // put request into irecv_queue + if(iRCCE_irecv_queue[help_request->source] == NULL) { + iRCCE_irecv_queue[help_request->source] = help_request; + } + else { + iRCCE_RECV_REQUEST *run = iRCCE_irecv_queue[help_request->source]; + while(run->next != NULL) run = run->next; + run->next = help_request; + } + } + } + + } int i, j; int retval = iRCCE_SUCCESS; @@ -310,7 +475,7 @@ int iRCCE_irecv_push(void) { } } - return retval; + return (iRCCE_irecv_any_source_queue == NULL)? retval : iRCCE_RESERVED; } //-------------------------------------------------------------------------------------- @@ -352,6 +517,24 @@ int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *request, int *test) { return iRCCE_NOT_ENQUEUED; } + + // does request have any source specified? + if( request->source == iRCCE_ANY_SOURCE ) { + for( run = iRCCE_irecv_any_source_queue; run->next != NULL; run = run->next ) { + if( run->next == request ) { + run->next = run->next->next; + + if (test) (*test) = 1; + return iRCCE_SUCCESS; + } + } + + if (test) (*test) = 0; + return iRCCE_NOT_ENQUEUED; + } + + + source = request->source; if(iRCCE_irecv_queue[source] == NULL) { diff --git a/arch/x86/scc/iRCCE_isend.c b/arch/x86/scc/iRCCE_isend.c index 18c9dca0..042de0ce 100644 --- a/arch/x86/scc/iRCCE_isend.c +++ b/arch/x86/scc/iRCCE_isend.c @@ -1,12 +1,12 @@ -//*************************************************************************************** +//****************************************************************************** // Non-blocking send routines. -//*************************************************************************************** +//****************************************************************************** // // Author: Rob F. Van der Wijngaart // Intel Corporation // Date: 008/30/2010 // -//*************************************************************************************** +//****************************************************************************** // // Copyright 2010 Intel Corporation // @@ -34,6 +34,8 @@ // [2010-12-09] added cancel functions for non-blocking send/recv requests // by Carsten Clauss // +// [2011-06-29] added the support of using IPIs +// by Simon Pickartz, Stefan Lankes #include #include @@ -41,6 +43,8 @@ #ifdef CONFIG_ROCKCREEK #include +#include +#include static int iRCCE_push_send_request(iRCCE_SEND_REQUEST *request) { @@ -158,56 +162,121 @@ static void iRCCE_init_send_request( } //-------------------------------------------------------------------------------------- -// FUNCTION: iRCCE_isend +// FUNCTION: iRCCE_isend_general //-------------------------------------------------------------------------------------- // non-blocking send function; returns a handle of type iRCCE_SEND_REQUEST //-------------------------------------------------------------------------------------- static iRCCE_SEND_REQUEST blocking_isend_request; -int iRCCE_isend(char *privbuf, size_t size, int dest, iRCCE_SEND_REQUEST *request) { +static int iRCCE_isend_general(char *privbuf, size_t size, int dest, iRCCE_SEND_REQUEST *request) { - if(request == NULL) request = &blocking_isend_request; - if (dest<0 || dest >= RCCE_NP) - return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID)); - else { - iRCCE_init_send_request(privbuf, RCCE_buff_ptr, RCCE_chunk, - &RCCE_ready_flag[dest], &RCCE_sent_flag[RCCE_IAM], - size, dest, request); - if(iRCCE_isend_queue == NULL) { + iRCCE_init_send_request(privbuf, RCCE_buff_ptr, RCCE_chunk, + &RCCE_ready_flag[dest], &RCCE_sent_flag[RCCE_IAM], + size, dest, request); - if(iRCCE_push_send_request(request) == iRCCE_SUCCESS) { - return(iRCCE_SUCCESS); - } - else { - iRCCE_isend_queue = request; + if(iRCCE_isend_queue == NULL) { - if(request == &blocking_isend_request) { - iRCCE_isend_wait(request); - return(iRCCE_SUCCESS); - } - - return(iRCCE_PENDING); - } + if(iRCCE_push_send_request(request) == iRCCE_SUCCESS) { + return(iRCCE_SUCCESS); } else { - if(iRCCE_isend_queue->next == NULL) { - iRCCE_isend_queue->next = request; - } - else { - iRCCE_SEND_REQUEST *run = iRCCE_isend_queue; - while(run->next != NULL) run = run->next; - run->next = request; - } + iRCCE_isend_queue = request; if(request == &blocking_isend_request) { iRCCE_isend_wait(request); return(iRCCE_SUCCESS); } - return(iRCCE_RESERVED); + return(iRCCE_PENDING); } } + else { + if(iRCCE_isend_queue->next == NULL) { + iRCCE_isend_queue->next = request; + } + else { + iRCCE_SEND_REQUEST *run = iRCCE_isend_queue; + while(run->next != NULL) run = run->next; + run->next = request; + } + + if(request == &blocking_isend_request) { + iRCCE_isend_wait(request); + return(iRCCE_SUCCESS); + } + + return(iRCCE_RESERVED); + } +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_isend +//------------------------------------------------------------------------------ +// wrapper function to differentiate between anylength and normal call +//------------------------------------------------------------------------------ +static iRCCE_SEND_REQUEST blocking_isend_request; +int iRCCE_isend( + char *privbuf, + ssize_t size, + int dest, + iRCCE_SEND_REQUEST *request + ) { + if(request == NULL) request = &blocking_isend_request; + + if (dest<0 || dest >= RCCE_NP) { + return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID)); + } + else { + // anylength call + if( size < 0 ){ + // convert size to positive range */ + int send_size = -size; + + // use header payload + if( send_size <= iRCCE_MAIL_HEADER_PAYLOAD ) { + iRCCE_init_send_request(privbuf, RCCE_buff_ptr, + RCCE_chunk, &RCCE_ready_flag[dest], + &RCCE_sent_flag[RCCE_IAM], + send_size, dest, request); + request->finished = 1; + + iRCCE_mail_send( send_size, + iRCCE_ANYLENGTH_PIGGYBACK, + 0, privbuf, dest ); + NOP8; + NOP8; + icc_send_irq( dest ); + return iRCCE_SUCCESS; + } + // we need an extra isend-call + else { + iRCCE_mail_send( send_size, iRCCE_ANYLENGTH, + 0, NULL, dest ); + NOP8; + NOP8; + icc_send_irq( dest ); + return iRCCE_isend_general( privbuf, send_size, + dest, request ); + } + } + // normal call + else if( size > 0 ) { + return iRCCE_isend_general( privbuf, size, + dest, request ); + } + // do nothing + else { + iRCCE_init_send_request(privbuf, RCCE_buff_ptr, + RCCE_chunk, &RCCE_ready_flag[dest], + &RCCE_sent_flag[RCCE_IAM], + size, dest, request); + request->finished = 1; + return(iRCCE_SUCCESS); + } + + } + } //-------------------------------------------------------------------------------------- diff --git a/arch/x86/scc/iRCCE_mailbox.c b/arch/x86/scc/iRCCE_mailbox.c new file mode 100644 index 00000000..257a12c9 --- /dev/null +++ b/arch/x86/scc/iRCCE_mailbox.c @@ -0,0 +1,482 @@ +/* + * Copyright 2011 Simon Pickartz, 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. + */ + +/* + * Mailbox system + * + * [2011-05-08] implemented mailbox send/recv routines + * by Simon Pickartz, Chair for Operating Systems, + * RWTH Aachen University + */ + +#include +#include + +#ifdef CONFIG_ROCKCREEK +#include + +/** + * + * @file contains implementation of the mailbox system + * @author Simon Pickartz + * + * + */ + + +// forward declaration +static int iRCCE_mailbox_close_one(int rank, int check); + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mailbox_print_header +//------------------------------------------------------------------------------ +// routine for printing given header (debugging purpose) +//------------------------------------------------------------------------------ +/** + * @brief routine for printing a given header + * @param header is a pointer to a given iRCCE_MAIL_HEADER structure +*/ + +void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER* header) { + + kprintf( "\n" + "-------------------------\n" + "| RCK%d\n" + "-------------------------\n" + "| Sender\t: %d\t\n" + "| Size\t\t: %d\t\n" + "| Tag\t\t: %d\t\n" + "| Prio\t\t: %d\t\n" + "| Payload\t: %s\n" + "-------------------------\n\n", + RCCE_IAM, header->source, + header->size, header->tag, + header->prio, header->payload); +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mail_fetch +//------------------------------------------------------------------------------ +/** + * @brief routine to check for new mail in a given mailbox + * @param rank is the ID of the ranks mailbox to be emptied + * + * The function checks if the mailbox has new mail for a given rank. In case of + * new mail it needs memory for the received header. Either there is memory + * in the internal garbage collection or it has to allocated. The next step is + * to check wheter a last-mail was received or a normal one. A last-mail is + * indicated by the iRCCE_LAST_MAIL tag. A last-mail entails the appropriate + * flag in the iRCCE_last_mail array to be set. Otherwise the header has to be + * enqueued in the mailbox_recv_queue accordingly to the priority field. + */ +//------------------------------------------------------------------------------ +static int iRCCE_mail_fetch( + int rank // rank from whom to empty mailbox + ) { + + iRCCE_MAIL_HEADER* header; + + // check for memory in garbage collection or allocate new + if( iRCCE_mail_garbage.first ) { + header = iRCCE_mail_garbage.first; + iRCCE_mail_garbage.first = + iRCCE_mail_garbage.first->next; + + header->next = NULL; + if( iRCCE_mail_garbage.first == NULL ) { + iRCCE_mail_garbage.last = NULL; + } + } + else { + header = (iRCCE_MAIL_HEADER*)kmalloc(sizeof(iRCCE_MAIL_HEADER)); + } + + + // copy header to allocated memory + RC_cache_invalidate(); + iRCCE_memcpy_get( (void*)header, (void*)iRCCE_mailbox_recv[rank], + RCCE_LINE_SIZE ); + + // check if received a last-mail + if( header->tag == iRCCE_LAST_MAIL ) { + iRCCE_last_mail[rank] = 1; + iRCCE_mailbox_close_one( rank, 0 ); // we can close respective mailbox + iRCCE_mail_release( &header ); + } + else { + // check mail priority + int prio = header->prio; + + // enqueue accordingly + if( iRCCE_mailbox_recv_queue[prio] == NULL ) { + iRCCE_mailbox_recv_queue[prio] = header; + } + else { + iRCCE_MAIL_HEADER* run = iRCCE_mailbox_recv_queue[prio]; + while( run->next != NULL ) run = run->next; + run->next = header; + } + } + + + return iRCCE_SUCCESS; +} + + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mailbox_check +//------------------------------------------------------------------------------ +/** + * @brief routine to check for new mail in mailboxes + * + * This function has to be called from time to time. It empties all mailboxes of + * the participating cores if the corresponding sent-flag is set and the mailbox + * is not closed. After calling iRCCE_mail_fetch the sent-flag has to be reset. + * Here we have to use a little trick because we can only write to the MPB in + * cacheline granularity. We set the appropriate flag to zero and afterwords + * touch the MPB on another cacheline. That causes the write combine buffer to + * write out the data. + */ +//------------------------------------------------------------------------------ +static int iRCCE_mailbox_check() { + int i; + + for( i=0; isent ) { + iRCCE_mail_fetch(i); + + // reset senders flag + RC_cache_invalidate(); + iRCCE_mailbox_recv[i]->sent = RCCE_FLAG_UNSET; + *(int *)RCCE_fool_write_combine_buffer = 1; + } + } + } + + return iRCCE_SUCCESS; +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mail_recv +//------------------------------------------------------------------------------ +/** + * @brief routine for fetching received headers out of iRCCE_mailbox_recv_queue + * @param header is the address of a pointer to an iRCCE_MAIL_HEADER structure + * @return iRCCE_SUCCESS if there was new mail; iRCCE_MAILBOX_EMPTY else + * @todo implement fairer dequeue mechanism + * + * The function checks if the receive queue with highest priority (priority 0) + * contains any mail headers. In this case we pop the first element of that list + * in a FIFO maner. Otherwise iRCCE_mailbox_check() has to be called. Afterwards + * the first element of a non-empty receive queue with highest priority is + * returned. + */ +//------------------------------------------------------------------------------ +int iRCCE_mail_recv( + iRCCE_MAIL_HEADER** header // pointer to incoming header + ) { // (memory allocated by iRCCE) + + int i; + + // if there is no mail, check for incoming + if ( !iRCCE_mailbox_recv_queue[0] ) { + iRCCE_mailbox_check(); + } + + // check priority queues + for( i=0; inext; + help_header->next = NULL; + + *header = help_header; + return iRCCE_SUCCESS; + } + } + + // no mail queued + *header = NULL; + return iRCCE_MAILBOX_EMPTY; + +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mail_release +//------------------------------------------------------------------------------ +/** + * @brief routine to store released header by user in garbage collection + * @param header is the address of a pointer to an iRCCE_MAIL_HEADER structure + * @return iRCCE_SUCCESS in any case + * + * This function enqueus a pointer to memory for an iRCCE_MAIL_HEADER structure + * that is not used by the user program anymore. 'header' points to NULL by + * return of the function. + */ +//------------------------------------------------------------------------------ +int iRCCE_mail_release( + iRCCE_MAIL_HEADER** header + ) { + // put header in garbage collection + if( (iRCCE_mail_garbage.first == NULL) + && (iRCCE_mail_garbage.last == NULL ) ) { + + iRCCE_mail_garbage.first = *header; + iRCCE_mail_garbage.last = *header; + } + else { + iRCCE_mail_garbage.last->next = *header; + iRCCE_mail_garbage.last = *header; + } + iRCCE_mail_garbage.last->next = NULL; + + // reset header + *header = NULL; + return iRCCE_SUCCESS; +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mail_send +//------------------------------------------------------------------------------ +/** + * @brief routine to send a mail to a given destination (blocking) + * @param size is the size of the following message. This message may be + * contained in the payload or send by an isend()-call + * @param tag is an integer value to distinguish between different mail types + * @param prio indicates the priority of the mail. 0 is the highest priority + * whereas 4 is the lowest. + * @param payload is a pointer to byte array with a size of + * iRCCE_MAIL_HEADER_PAYLOAD. If NULL is passed nothing is done, otherwise array + * pointed by payload is copied into the header. + * @param dest indicates the destination of the mail in terms of the ID of + * one of the participating ranks + * @return iRCCE_SUCCESS if send was successful. If target mailbox is closed + * iRCCE_MAILBOX_CLOESD is returned. + * + * First it has to be checked if the target mailbox still contains an unread mail. + * If this is the case there is time to empty the own mailboxes. It blocks until + * the receiver has emptied its mailbox. The next step is to acquire the lock + * for the target mailbox to be sure that the mailbox is not closed by the + * receiver while the mail is delivered. After locking the mailbox an + * iRCCE_MAIL_HEADER is generated according with the parameters (but with a + * sent-flag set to zero)and is copied into the target mailbox. After all data + * beeing written the appropropriate sent-flag has to be set with the same trick + * already used in iRCCE_mail_check(). Now the lock can be released. + */ +//------------------------------------------------------------------------------ +int iRCCE_mail_send( + size_t size, // size of following message expected to be send/received + int tag, // tag to indicate message type + char prio, // mail priority + char* payload, // pointer to buffer for header payload + int dest // UE that will receive the header + ) { + + // if dest mailbox is full, check for incoming mail + RC_cache_invalidate(); + while( iRCCE_mailbox_send[dest]->sent ) { + iRCCE_mailbox_check(); + RC_cache_invalidate(); + } + + // check if mailbox is closed + RCCE_acquire_lock( dest ); + RC_cache_invalidate(); + if( iRCCE_mailbox_send[dest]->closed ) { + RCCE_release_lock( dest ); + return iRCCE_MAILBOX_CLOSED; + } + + // prepare header + iRCCE_MAIL_HEADER header = { RCCE_IAM, size, tag, NULL, prio, + RCCE_FLAG_UNSET, RCCE_FLAG_UNSET, + {[0 ... iRCCE_MAIL_HEADER_PAYLOAD-1] = 0} }; + + // payload within the header? + if( payload ) { + memcpy( header.payload, payload, iRCCE_MAIL_HEADER_PAYLOAD ); + } + + // do the actual copy to MPB + RC_cache_invalidate(); + iRCCE_memcpy_put( (void*)iRCCE_mailbox_send[dest], + (void*)&header, RCCE_LINE_SIZE ); + + // set senders flag + RC_cache_invalidate(); + iRCCE_mailbox_send[dest]->sent = RCCE_FLAG_SET; + *(int *)RCCE_fool_write_combine_buffer = 1; + RC_cache_invalidate(); + + RCCE_release_lock( dest ); + + return iRCCE_SUCCESS; +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_last_mail_recv +//------------------------------------------------------------------------------ +/** + * @brief check if all final headers are received from all UEs + * @return iRCCE_SUCCES if all last-mails arrive iRCCE_LAST_MAILS_NOT_RECV + * otherwise + * + * This functions is used to determine if all last-mails arrived at the calling + * UE. Therefore it checks the iRCCE_last_mail array if all flags are set. + */ +//------------------------------------------------------------------------------ +int iRCCE_last_mail_recv(void) { + int i; + int res = iRCCE_SUCCESS; + + for( i=0; inext; + kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) ); + erase_header = iRCCE_mailbox_recv_queue[i]; + } + } + return iRCCE_SUCCESS; +} + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mailbox_close_one +//------------------------------------------------------------------------------ +/** + * @brief routine to close one mailbox + * @return iRCCE_SUCCESS + * @param rank is the ID of the ranks mailbox to be closed + * @param check is a flag indicating wether the mailbox has to be emptied before + * closing or not. This is required for a close-call as a result of a received + * last-mail. + * + * This function closes a mailbox of the given rank. If the check flag is set + * an iRCCE_mail_check()-call is performed. The close procedure has to be locked + * to be sure that no UE sends any mail while closing the mailbox. + */ +//------------------------------------------------------------------------------ +static int iRCCE_mailbox_close_one(int rank, int check) { + RCCE_acquire_lock( RCCE_IAM ); + + // check if it contains new mail + RC_cache_invalidate(); + if( check && iRCCE_mailbox_recv[rank]->sent ) { + iRCCE_mail_fetch(rank); + + } + + // close mailbox + iRCCE_MAIL_HEADER help_header = { 0, 0, 0, NULL, 0, RCCE_FLAG_UNSET, + RCCE_FLAG_SET, {[0 ... iRCCE_MAIL_HEADER_PAYLOAD-1] = 0} }; + + RC_cache_invalidate(); + iRCCE_memcpy_put( (void*)iRCCE_mailbox_recv[rank], + &help_header, RCCE_LINE_SIZE ); + + RCCE_release_lock( RCCE_IAM ); + + iRCCE_mailbox_status[rank] = iRCCE_MAILBOX_CLOSED; + + return iRCCE_SUCCESS; +} + + +//------------------------------------------------------------------------------ +// FUNCTION: iRCCE_mailbox_close() +//------------------------------------------------------------------------------ +/** + * @brief routine to close one or all mailboxes + * @param rank is the ID of the UEs mailbox to be closed if iRCCE_MAILBOX_ALL + * is passed all mailboxes are closed by the calling UE + * @return iRCCE_SUCCESS + * + * This functions closed one or all mailboxes of the calling UE. This is done by + * calling iRCCE_mailbox_close_one for one or all mailboxes. + */ +//------------------------------------------------------------------------------ +int iRCCE_mailbox_close(int rank) { + if( rank == iRCCE_MAILBOX_ALL ) { + int i; + for( i=0; i= RCCE_NP) return(RCCE_error_return(RCCE_debug_comm,RCCE_ERROR_ID)); else { diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index 9845754d..a946bd23 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -172,7 +172,7 @@ int icc_init(void) return 0; } -inline int icc_send_irq(int ue) +int icc_send_irq(int ue) { int tmp, x, y, z, addr; @@ -195,123 +195,103 @@ inline int icc_send_irq(int ue) int icc_halt(void) { uint32_t flags; +#if 0 uint32_t do_send = 1; do { // iRCCE is not thread save => disable interrupts flags = irq_nested_disable(); - if (do_send) + if (do_send) { do_send = (iRCCE_isend_push() == iRCCE_PENDING); - icc_check(); + iRCCE_irecv_push(); + } + icc_mail_check(); irq_nested_enable(flags); - } while(do_send); - HALT; + NOP1; + } while(do_send); +#else + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + icc_mail_check(); + irq_nested_enable(flags); + NOP1; +#endif + //HALT; 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) -{ +int icc_mail_ping( void ) +{ uint32_t flags; + int remote_rank = (my_ue+1)%2; + uint8_t payload[iRCCE_MAIL_HEADER_PAYLOAD]; + uint64_t* timer = (uint64_t*) payload; - if (BUILTIN_EXPECT(ue == my_ue, 0)) - return -EINVAL; - if (BUILTIN_EXPECT((ue < 0) || (ue >= num_ues), 0)) - return -EINVAL; - - while(ping_start) { - NOP8; - } - - ping_start = rdtsc(); - - // iRCCE is not thread save => disable interrupts + if (my_ue) + return -1; + + kprintf( "Hello from mail_ping ... \n" ); + + // disable interrupts flags = irq_nested_disable(); - iRCCE_isend((char*) &ping_request, sizeof(icc_header_t), ue, NULL); + // start timer + *timer = rdtsc(); + + /* send ping request */ + iRCCE_mail_send(sizeof(uint64_t), ICC_TAG_PINGREQUEST, 0, payload, remote_rank); - // wait some time NOP8; + icc_send_irq(remote_rank); - // wake up receiver - icc_send_irq(ue); + /* check for incoming messages */ + icc_mail_check(); + // enable interrupts irq_nested_enable(flags); return 0; } -static void interpret_header(icc_header_t* header, int recv_ue) +void icc_mail_check(void) { - //kprintf("Got ICC message %d from %d\n", header->type, recv_ue); + iRCCE_MAIL_HEADER* header = NULL; + int res; + uint64_t timer; + //char* recv_buffer; - switch(header->type) - { - case ICC_TYPE_PINGREQUEST: { - - iRCCE_isend((char*) &ping_response, sizeof(icc_header_t), recv_ue, NULL); - - // wait some time + // empty mailbox and interpret headers + while( (res = iRCCE_mail_recv( &header )) == iRCCE_SUCCESS ) { + switch(header->tag) + { + case ICC_TAG_PINGREQUEST: + iRCCE_mail_send( header->size, ICC_TAG_PINGRESPONSE, 0, header->payload, header->source ); NOP8; - - // wake up remote core - icc_send_irq(recv_ue); + icc_send_irq( header->source ); + break; + case ICC_TAG_PINGRESPONSE: + timer = rdtsc() - *((uint64_t*) header->payload); + kprintf( "Response received in %d ticks!\n", timer ); + break; + default: + kprintf("Invalid mail: tag = %d\n", header->tag); + break; + } + /*else if( header->tag == iRCCE_ANYLENGTH ) { + recv_buffer = (char*)kmalloc( header->size ); + iRCCE_irecv( recv_buffer, header->size, header->source, NULL ); + iRCCE_mail_send( 0, 2, 0, NULL, header->source ); } - break; - 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); + else if( header->tag == iRCCE_ANYLENGTH_PIGGYBACK ) { + iRCCE_mail_send( 0, 2, 0, NULL, header->source ); + }*/ + + iRCCE_mail_release( &header ); } } -/* - * 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 first_call = 1; - int i, ret; - - if (first_call) { - first_call = 0; - - for(i=0; i #include #include +#include #include #include #include @@ -116,7 +117,7 @@ int STDCALL network_task(void* arg) // start echo and ping server echo_init(); - //ping_init(); + ping_init(); while(!done) { #ifdef CONFIG_PCI @@ -142,14 +143,14 @@ int network_shutdown(void) return 0; } -void tcp_init_ok(void* e) +static void tcp_init_ok(void* e) { - kprintf("TCP/IP init COMPLETE!!!!!!"); + kprintf("TCP/IP init COMPLETE!!"); } int network_init(void) { - tcpip_init(tcp_init_ok,NULL); + tcpip_init(tcp_init_ok, NULL); kprintf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); mmnif_open(); kprintf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); @@ -159,7 +160,7 @@ int network_init(void) #if defined(CONFIG_LWIP) // Initialize lwIP modules - lwip_init(); + tcpip_init(tcp_init_ok, NULL); #endif #if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) diff --git a/kernel/main.c b/kernel/main.c index 75fffb0c..c28fb7c1 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -86,7 +86,6 @@ int main(void) kprintf("This is MetalSVM %s Build %u, %u\n", METALSVM_VERSION, &__BUILD_DATE, &__BUILD_TIME); popbg(); - system_init(); irq_init(); timer_init(); @@ -103,7 +102,6 @@ int main(void) irq_enable(); kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end); - system_calibration(); network_init(); @@ -115,7 +113,6 @@ int main(void) // sleep(5); // list_root(); test_init(); - per_core(current_task)->status = TASK_IDLE; reschedule(); diff --git a/kernel/ping.c b/kernel/ping.c index 98398300..46951113 100644 --- a/kernel/ping.c +++ b/kernel/ping.c @@ -43,7 +43,7 @@ #include #include -#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ +#if LWIP_RAW || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ #include #include @@ -198,19 +198,20 @@ ping_recv(int s) static void ping_thread(void *arg) { - int s; + int s, i; int timeout = PING_RCV_TIMEO; ip_addr_t ping_target; LWIP_UNUSED_ARG(arg); if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) { + LWIP_DEBUGF( PING_DEBUG, ("ping: invalid socket\n")); return; } lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - while (1) { + for(i=0; i<10; i++) { ping_target = PING_TARGET; if (ping_send(s, &ping_target) == ERR_OK) { @@ -227,6 +228,8 @@ ping_thread(void *arg) } sys_msleep(PING_DELAY); } + + lwip_close(s); } #else /* PING_USE_SOCKETS */ diff --git a/kernel/tests.c b/kernel/tests.c index b6138f4d..4cd3a6c5 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -95,13 +95,13 @@ static int STDCALL foo(void* arg) } #ifdef CONFIG_ROCKCREEK -static int STDCALL ping(void* arg) -{ +int STDCALL mail_ping(void* arg) { int i; for(i=0; i<20; i++) { - icc_ping(1); - HALT; + if (BUILTIN_EXPECT(icc_mail_ping(), 0)) + return -1; + udelay(500000); } return 0; @@ -125,7 +125,9 @@ static int STDCALL join_test(void* arg) return 0; } +#ifdef CONFIG_LWIP void ping_send_now(); +#endif __inline int get_core_no(void) { @@ -260,7 +262,7 @@ void* client_task(void* e) close(sd); -return NULL; + return NULL; } @@ -273,7 +275,6 @@ int test_init(void) create_kernel_task(NULL,client_task,NULL); #if 0 - char* argv[] = {"/bin/tests", NULL}; sem_init(&producing, 1); @@ -284,12 +285,12 @@ 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_kernel_task(NULL, mail_ping, NULL); //create_user_task(NULL, "/bin/hello", argv); create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv); - #endif + return 0; } diff --git a/libkern/stdio.c b/libkern/stdio.c index a8bdc9de..281fe11d 100644 --- a/libkern/stdio.c +++ b/libkern/stdio.c @@ -24,15 +24,19 @@ #include #include #include +#include #ifdef CONFIG_VGA #include #endif #define NO_EARLY_PRINT 0 #define VGA_EARLY_PRINT 1 +#define UART_EARLY_PRINT 2 #ifdef CONFIG_VGA static uint32_t early_print = VGA_EARLY_PRINT; +#elif defined(CONFIG_UART) +static uint32_t early_print = UART_EARLY_PRINT; #else static uint32_t early_print = NO_EARLY_PRINT; #endif @@ -56,8 +60,12 @@ int kputchar(int c) kmessages[pos % KMSG_SIZE] = (unsigned char) c; #ifdef CONFIG_VGA if (early_print == VGA_EARLY_PRINT) - vga_putchar(c); + vga_putchar(c); #endif +#ifdef CONFIG_UART + if (early_print == UART_EARLY_PRINT) + uart_putchar(c); +#endif return 1; } @@ -73,6 +81,10 @@ int kputs(const char *str) #ifdef CONFIG_VGA if (early_print == VGA_EARLY_PRINT) vga_putchar(str[i]); +#endif +#ifdef CONFIG_UART + if (early_print == UART_EARLY_PRINT) + uart_putchar(str[i]); #endif } diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index b5045c6e..a35fe663 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -84,8 +84,15 @@ */ #define LWIP_CHECKSUM_ON_COPY 1 +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#define IP_FORWARD 1 + /* DEBUG options */ -#define LWIP_DEBUG 0 +#define LWIP_DEBUG 1 #define DHCP_DEBUG LWIP_DBG_OFF #define ETHARP_DEBUG LWIP_DBG_OFF #define TCPIP_DEBUG LWIP_DBG_OFF @@ -94,7 +101,8 @@ #define MEM_DEBUG LWIP_DBG_OFF #define IP_DEBUG LWIP_DBG_OFF #define INET_DEBUG LWIP_DBG_OFF -#define NETIF_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_ON #define TIMERS_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF #endif diff --git a/mm/memory.c b/mm/memory.c index ad29aedd..11f6fdce 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -30,6 +30,9 @@ #include #endif #ifdef CONFIG_ROCKCREEK +#include +#include +#include #include #endif @@ -93,6 +96,7 @@ int mmu_init(void) size_t kernel_size; unsigned int i; size_t addr; + int ret; // at first, set default value of the bitmap memset(bitmap, 0xFF, sizeof(uint8_t)*BITMAP_SIZE); @@ -148,15 +152,8 @@ int mmu_init(void) } } #elif defined(CONFIG_ROCKCREEK) - for(addr=PRIVATE_MEM1_START; addr> PAGE_SHIFT); - if (addr > addr + PAGE_SIZE) - break; - atomic_int32_inc(&total_pages); - atomic_int32_inc(&total_available_pages); - } - - for(addr=PRIVATE_MEM2_START; addr> PAGE_SHIFT); if (addr > addr + PAGE_SIZE) break; @@ -164,6 +161,15 @@ int mmu_init(void) atomic_int32_inc(&total_available_pages); } + // Note: The last slot belongs always to the private memory. + for(addr=0xFF000000; addr<0xFFFFFFFF; addr+=PAGE_SIZE) { + page_clear_mark(addr >> PAGE_SHIFT); + if (addr > addr + PAGE_SIZE) + break; + atomic_int32_inc(&total_pages); + atomic_int32_inc(&total_available_pages); + } + /* * Mark the bootinfo as used. */ @@ -200,7 +206,30 @@ int mmu_init(void) if ((size_t) &kernel_end & (PAGE_SIZE-1)) alloc_start++; - return paging_init(); + ret = paging_init(); + +#ifdef CONFIG_ROCKCREEK + /* + * Now, we are able to read the FPGA registers and to + * determine the number of slots for private memory. + */ + uint32_t slots = *((volatile uint32_t*) (FPGA_BASE + 0x8244)); + if (slots == 0) + slots = 21; + + kprintf("MetalSVM use %d slots for private memory\n", slots); + + // define the residual private slots as free + for(addr=20*0x1000000; addr<(slots-1)*0x1000000; addr+=PAGE_SIZE) { + page_clear_mark(addr >> PAGE_SHIFT); + if (addr > addr + PAGE_SIZE) + break; + atomic_int32_inc(&total_pages); + atomic_int32_inc(&total_available_pages); + } +#endif + + return ret; } /*