Merge branch 'master' into ohligs

Conflicts:
	kernel/tests.c
This commit is contained in:
Marian Ohligs 2011-08-29 14:52:23 +02:00
commit ed5dba2672
25 changed files with 846 additions and 327 deletions

View file

@ -40,18 +40,25 @@
#define iRCCE_ANY_SOURCE -1 #define iRCCE_ANY_SOURCE -1
#define iRCCE_PRIOS 5 #define iRCCE_PRIOS 5
#define iRCCE_MAILBOX_EMPTY -2
#define iRCCE_LAST_MAILS_NOT_RECV -3
#define iRCCE_MAILBOX_ALL -4 #define iRCCE_MAILBOX_ALL -4
#define iRCCE_MAILBOX_OPEN 0
#define iRCCE_MAILBOX_CLOSED 1 // status codes
#define iRCCE_ERROR_ID RCCE_ERROR_ID
#define iRCCE_ERROR_TARGET RCCE_ERROR_TARGET
#define iRCCE_ERROR_SOURCE RCCE_ERROR_SOURCE
#define iRCCE_ERROR_GENERAL -1
#define iRCCE_MAILBOX_OPEN -2
#define iRCCE_MAILBOX_CLOSED -3
#define iRCCE_MAILBOX_INVALID -4
#define iRCCE_MAILBOX_EMPTY -5
#define iRCCE_LAST_MAILS_NOT_RECV -6
// iRCCE-mailbox-system tags // iRCCE-mailbox-system tags
#define iRCCE_LAST_MAIL -1 #define iRCCE_LAST_MAIL -1
#define iRCCE_LAST_MAIL -1
#define iRCCE_ANYLENGTH -2 #define iRCCE_ANYLENGTH -2
#define iRCCE_ANYLENGTH_PIGGYBACK -3 #define iRCCE_ANYLENGTH_PIGGYBACK -3
typedef volatile char iRCCE_SHORT_FLAG; typedef volatile char iRCCE_SHORT_FLAG;
typedef struct _iRCCE_SEND_REQUEST { typedef struct _iRCCE_SEND_REQUEST {
@ -112,21 +119,30 @@ typedef struct _iRCCE_WAIT_LIST {
#define iRCCE_MAIL_HEADER_PAYLOAD 13 #define iRCCE_MAIL_HEADER_PAYLOAD 13
/**
* @struct _iRCCE_MAIL_HEADER
* @brief mail that can be send/received by iRCCE_mail_send/iRCCE_mail_recv
*
* _iRCCE_MAIL_HEADER has exactly the size of one cacheline (32 byte). Create an
* object by using the iRCCE_MAIL_HEADER identifier.
*/
typedef struct _iRCCE_MAIL_HEADER { 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 source; /**< UE that will send the header */
int tag; // tag indicating which kind of message we have size_t size; /**< size of the message which will be send/received */
struct _iRCCE_MAIL_HEADER* next;// pointer for queue - could be replaced by list-object int tag; /**< tag indicating which kind of message we have */
char prio; // priority of the mail struct _iRCCE_MAIL_HEADER* next;/**< pointer for queue - could be replaced by list-object */
iRCCE_SHORT_FLAG sent; // flag indicating that header is new char prio; /**< priority of the mail */
iRCCE_SHORT_FLAG closed; // flag indication that mailbox is closed iRCCE_SHORT_FLAG sent; /**< flag indicating that header is new */
char payload[iRCCE_MAIL_HEADER_PAYLOAD]; // payload for small messages iRCCE_SHORT_FLAG closed; /**< flag indication that mailbox is closed */
char payload[iRCCE_MAIL_HEADER_PAYLOAD]; /**< payload for small messages */
/** @} */
} iRCCE_MAIL_HEADER; } iRCCE_MAIL_HEADER;
typedef struct _iRCCE_MAIL_TRASH_BIN { typedef struct _iRCCE_MAIL_HEADER_LIST {
iRCCE_MAIL_HEADER* first; iRCCE_MAIL_HEADER* first;
iRCCE_MAIL_HEADER* last; iRCCE_MAIL_HEADER* last;
} iRCCE_MAIL_TRASH_BIN; } iRCCE_MAIL_HEADER_LIST;
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// //
@ -172,7 +188,8 @@ int iRCCE_irecv_cancel(iRCCE_RECV_REQUEST *, int *);
int iRCCE_mail_send(size_t, int, char, char*, int); int iRCCE_mail_send(size_t, int, char, char*, int);
int iRCCE_mail_recv(iRCCE_MAIL_HEADER**); int iRCCE_mail_recv(iRCCE_MAIL_HEADER**);
// //
// functions to empty mailbox-queue and to check for last mails: // functions to empty mailbox-queue and to check for mails:
int iRCCE_mail_check(int);
int iRCCE_mail_release(iRCCE_MAIL_HEADER**); int iRCCE_mail_release(iRCCE_MAIL_HEADER**);
int iRCCE_last_mail_recv(void); int iRCCE_last_mail_recv(void);
int iRCCE_mailbox_wait(void); int iRCCE_mailbox_wait(void);

View file

@ -36,7 +36,7 @@ extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP];
extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP]; extern volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP];
// queue for received headers // queue for received headers
extern iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS]; extern iRCCE_MAIL_HEADER_LIST iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
// flags for last mail // flags for last mail
extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP]; extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
@ -45,7 +45,8 @@ extern iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
extern iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP]; extern iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP];
// garbage collection for mailbox // garbage collection for mailbox
extern iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage; extern iRCCE_MAIL_HEADER_LIST iRCCE_mail_garbage;
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp threadprivate (iRCCE_isend_queue, iRCCE_irecv_queue) #pragma omp threadprivate (iRCCE_isend_queue, iRCCE_irecv_queue)
#endif #endif

View file

@ -39,16 +39,22 @@ typedef struct {
extern bootinfo_t* bootinfo; extern bootinfo_t* bootinfo;
#define ICC_TAG_IP 0 enum icc_mail_requests {
#define ICC_TAG_SVMREQUEST 1 PING_REQ=1,
#define ICC_TAG_PINGREQUEST 2 PING_RESP,
#define ICC_TAG_PINGRESPONSE 3 SVM_REQUEST,
NOISE,
};
int icc_init(void); int icc_init(void);
int icc_halt(void); int icc_halt(void);
int icc_send_irq(int ue); int icc_send_irq(int ue);
void icc_mail_check(void); void icc_mail_check(int irq);
int icc_mail_ping(void); int icc_mail_ping(void);
int icc_send_gic_irq(int core_num);
int icc_irq_ping(void);
int icc_mail_ping_irq(void);
int icc_mail_noise(void);
#endif #endif

View file

@ -117,9 +117,37 @@ inline static void *memcpy(void* dest, const void *src, size_t count)
#ifdef HAVE_ARCH_MEMSET #ifdef HAVE_ARCH_MEMSET
#ifdef CONFIG_ROCKCREEK
/** @brief Repeated write of a value to a whole range of bytes /** @brief Repeated write of a value to a whole range of bytes
* *
* Writes a value repeatedly double word wise (4 byte) to a range of bytes * SCC optimized version of memset (see memcpy)
*
* @param dest Destination address
* @param val Value to flood the range with
* @param count Size of target range in bytes
*/
inline static void *memset(void* dest, int val, size_t count)
{
int32_t i, j;
if (BUILTIN_EXPECT(!dest, 0))
return dest;
asm volatile ("cld\n\t"
"1: cmpl $32, %%ebx ; jb 2f\n\t"
"movl (%%edi), %%edx\n\t"
"movl $32, %%ecx\n\t"
"rep stosb\n\t"
"subl $32, %%ebx\n\t"
"jmp 1b\n\t"
"2: movl %%ebx, %%ecx ; rep stosb"
: "=&b"(i), "=&D"(j)
: "a"(val), "1"(dest), "0"(count) : "%edx", "%ecx", "memory","cc");
return dest;
}
#else
/** @brief Repeated write of a value to a whole range of bytes
* *
* @param dest Destination address * @param dest Destination address
* @param val Value to flood the range with * @param val Value to flood the range with
@ -140,6 +168,8 @@ inline static void *memset(void* dest, int val, size_t count)
} }
#endif #endif
#endif
#ifdef HAVE_ARCH_STRLEN #ifdef HAVE_ARCH_STRLEN
/** @brief Standard string length /** @brief Standard string length

View file

@ -63,7 +63,7 @@ SECTION .text
ALIGN 4 ALIGN 4
stublet: stublet:
; initialize stack pointer. ; initialize stack pointer.
mov esp, default_stack_pointer mov esp, [default_stack_pointer]
; initialize cpu features ; initialize cpu features
call cpu_init call cpu_init
; interpret multiboot information ; interpret multiboot information

View file

@ -28,10 +28,10 @@
gdt_ptr_t gp; gdt_ptr_t gp;
static tss_t task_state_segments[MAX_TASKS] __attribute__ ((aligned (PAGE_SIZE))); static tss_t task_state_segments[MAX_TASKS] __attribute__ ((aligned (PAGE_SIZE)));
static unsigned char kstacks[MAX_TASKS][KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE), section (".data"))); static unsigned char kstacks[MAX_TASKS][KERNEL_STACK_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {[0 ... MAX_TASKS-1][0 ... KERNEL_STACK_SIZE-1] = 0xCD};
uint32_t default_stack_pointer = (uint32_t) kstacks[0] + KERNEL_STACK_SIZE - sizeof(size_t);
// currently, our kernel has full access to the ioports // currently, our kernel has full access to the ioports
static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}}; static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}};
unsigned char* default_stack_pointer __attribute__ ((section (".data"))) = kstacks[0] + KERNEL_STACK_SIZE - sizeof(size_t);
/* /*
* This is defined in entry.asm. We use this to properly reload * This is defined in entry.asm. We use this to properly reload

View file

@ -234,8 +234,13 @@ void irq_handler(struct state *s)
/* This is a blank function pointer */ /* This is a blank function pointer */
void (*handler) (struct state * s); void (*handler) (struct state * s);
// at first, we check our work queues // evaluate only irq status register if int_no = 124
if( s->int_no == 124 ) {
check_workqueues_rem_irq();
}
else {
check_workqueues(); check_workqueues();
}
/* /*
* Find out if we have a custom handler to run for this * Find out if we have a custom handler to run for this
@ -278,4 +283,7 @@ leave_handler:
// timer interrupt? // timer interrupt?
if ((s->int_no == 32) || (s->int_no == 123)) if ((s->int_no == 32) || (s->int_no == 123))
scheduler(); // switch to a new task scheduler(); // switch to a new task
// exists a new (driver) task with a higher priority?
else if ((s->int_no >= 32) && (get_highest_priority(CORE_ID) > per_core(current_task)->prio))
scheduler();
} }

View file

@ -170,13 +170,13 @@ static void fpu_init(union fpu_state* fpu)
if (has_fxsr()) { if (has_fxsr()) {
i387_fxsave_t* fx = &fpu->fxsave; i387_fxsave_t* fx = &fpu->fxsave;
memset(fx, 0, sizeof(union fpu_state)); memset(fx, 0x00, sizeof(union fpu_state));
fx->cwd = 0x37f; fx->cwd = 0x37f;
if (has_xmm()) if (has_xmm())
fx->mxcsr = 0x1f80; fx->mxcsr = 0x1f80;
} else { } else {
i387_fsave_t *fp = &fpu->fsave; i387_fsave_t *fp = &fpu->fsave;
memset(fp, 0, sizeof(union fpu_state)); memset(fp, 0x00, sizeof(union fpu_state));
fp->cwd = 0xffff037fu; fp->cwd = 0xffff037fu;
fp->swd = 0xffff0000u; fp->swd = 0xffff0000u;
fp->twd = 0xffffffffu; fp->twd = 0xffffffffu;

View file

@ -92,6 +92,7 @@ static void timer_handler(struct state *s)
int timer_wait(unsigned int ticks) int timer_wait(unsigned int ticks)
{ {
uint64_t eticks = timer_ticks + ticks; uint64_t eticks = timer_ticks + ticks;
task_t* curr_task = per_core(current_task); task_t* curr_task = per_core(current_task);
if (curr_task->status == TASK_IDLE) if (curr_task->status == TASK_IDLE)

View file

@ -84,7 +84,7 @@ inline static size_t copy_page_table(task_t* task, uint32_t pgd_index, page_tabl
new_pgt = kmalloc(sizeof(page_table_t)); new_pgt = kmalloc(sizeof(page_table_t));
if (!new_pgt) if (!new_pgt)
return 0; return 0;
memset(new_pgt, 0, sizeof(page_table_t)); memset(new_pgt, 0x00, sizeof(page_table_t));
if (counter) if (counter)
(*counter)++; (*counter)++;
@ -137,7 +137,7 @@ int create_pgd(task_t* task, int copy)
pgd = kmalloc(sizeof(page_dir_t)); pgd = kmalloc(sizeof(page_dir_t));
if (!pgd) if (!pgd)
return -ENOMEM; return -ENOMEM;
memset(pgd, 0, sizeof(page_dir_t)); memset(pgd, 0x00, sizeof(page_dir_t));
// create a new "page table container" for the new task // create a new "page table container" for the new task
pgt = kmalloc(sizeof(page_table_t)); pgt = kmalloc(sizeof(page_table_t));
@ -145,7 +145,7 @@ int create_pgd(task_t* task, int copy)
kfree(pgd, sizeof(page_dir_t)); kfree(pgd, sizeof(page_dir_t));
return -ENOMEM; return -ENOMEM;
} }
memset(pgt, 0, sizeof(page_table_t)); memset(pgt, 0x00, sizeof(page_table_t));
spinlock_lock(&kslock); spinlock_lock(&kslock);
@ -328,9 +328,9 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag
// clear the page table // clear the page table
if (paging_enabled) if (paging_enabled)
memset((void*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000), 0, PAGE_SIZE); memset((void*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000), 0x00, PAGE_SIZE);
else else
memset(pgt, 0, PAGE_SIZE); memset(pgt, 0x00, PAGE_SIZE);
} else pgt = (page_table_t*) (task->pgd->entries[index] & 0xFFFFF000); } else pgt = (page_table_t*) (task->pgd->entries[index] & 0xFFFFF000);
/* convert physical address to virtual */ /* convert physical address to virtual */
@ -413,10 +413,19 @@ int change_page_permissions(size_t start, size_t end, uint32_t flags)
newflags &= ~PG_PRESENT; newflags &= ~PG_PRESENT;
// update flags // update flags
if (!(flags & VMA_WRITE)) if (!(flags & VMA_WRITE)) {
newflags &= ~PG_RW; newflags &= ~PG_RW;
else #ifdef CONFIG_ROCKCREEK
if (newflags & (PG_SVM_STRONG|PG_SVM_LAZYRELEASE))
newflags &= ~PG_MPE;
#endif
} else {
newflags |= PG_RW; newflags |= PG_RW;
#ifdef CONFIG_ROCKCREEK
if (newflags & (PG_SVM_STRONG|PG_SVM_LAZYRELEASE))
newflags |= PG_MPE;
#endif
}
pgt->entries[index2] = (newflags & 0xFFF) | (phyaddr & 0xFFFFF000); pgt->entries[index2] = (newflags & 0xFFF) | (phyaddr & 0xFFFFF000);

View file

@ -21,6 +21,7 @@
#include <metalsvm/stdio.h> #include <metalsvm/stdio.h>
#include <metalsvm/stdlib.h> #include <metalsvm/stdlib.h>
#include <metalsvm/mmu.h> #include <metalsvm/mmu.h>
#include <metalsvm/tasks.h>
#include <metalsvm/page.h> #include <metalsvm/page.h>
#include <metalsvm/errno.h> #include <metalsvm/errno.h>
#include <asm/irqflags.h> #include <asm/irqflags.h>
@ -121,17 +122,17 @@ int svm_access_request(size_t addr)
//kprintf("send access request to %d of 0x%x\n", remote_rank, phyaddr); //kprintf("send access request to %d of 0x%x\n", remote_rank, phyaddr);
/* send ping request */ /* send ping request */
iRCCE_mail_send(2*sizeof(size_t), ICC_TAG_SVMREQUEST, 0, payload, remote_rank); iRCCE_mail_send(2*sizeof(size_t), SVM_REQUEST, 0, payload, remote_rank);
request[remote_rank]++; request[remote_rank]++;
NOP8; NOP8;
icc_send_irq(remote_rank); icc_send_gic_irq(remote_rank);
/* check for incoming messages */ /* check for incoming messages */
icc_mail_check(); icc_mail_check(0);
while (page_owner[pageid] != my_ue) { while (page_owner[pageid] != my_ue) {
NOP4; check_workqueues_rem_irq();
} }
return change_page_permissions(addr, addr+PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE); return change_page_permissions(addr, addr+PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE);
@ -229,10 +230,9 @@ int svm_emit_page(size_t phyaddr, int ue)
((size_t*) payload)[1] = phyaddr; ((size_t*) payload)[1] = phyaddr;
/* send ping request */ /* send ping request */
iRCCE_mail_send(2*sizeof(size_t), ICC_TAG_SVMREQUEST, 0, payload, remote_rank); iRCCE_mail_send(2*sizeof(size_t), SVM_REQUEST, 0, payload, remote_rank);
/* send interrupt */
NOP8; icc_send_gic_irq(remote_rank);
icc_send_irq(remote_rank);
forward[remote_rank]++; forward[remote_rank]++;
} else { } else {

View file

@ -55,10 +55,10 @@ volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_recv[RCCE_MAXNP]; // store addresses f
volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP]; // store addresses for sending headeres volatile iRCCE_MAIL_HEADER* iRCCE_mailbox_send[RCCE_MAXNP]; // store addresses for sending headeres
// mailbox recv queue // mailbox recv queue
iRCCE_MAIL_HEADER* iRCCE_mailbox_recv_queue[iRCCE_PRIOS]; iRCCE_MAIL_HEADER_LIST iRCCE_mailbox_recv_queue[iRCCE_PRIOS];
// mail garbage queue // mail garbage queue
iRCCE_MAIL_TRASH_BIN iRCCE_mail_garbage; iRCCE_MAIL_HEADER_LIST iRCCE_mail_garbage;
// flag indicating if last header was received // flag indicating if last header was received
iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP]; iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
@ -66,12 +66,19 @@ iRCCE_SHORT_FLAG iRCCE_last_mail[RCCE_MAXNP];
// field to store open/closed status of mailboxes // field to store open/closed status of mailboxes
iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP]; iRCCE_SHORT_FLAG iRCCE_mailbox_status[RCCE_MAXNP];
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// FUNCTION: iRCCE_init // FUNCTION: iRCCE_init
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// initialize the library /**
* @brief initialize the library
*
* To initialize the mailbox system the function calles RCCE_malloc() as often
* as there are UEs participating. As a result the respective mailboxes are
* located at the begin of the local MPB directly behind the space reserved for
* flags by RCCE_init(). In iRCCE_mailbox_recv[i] a pointer to the mailbox is
* saved respectively. To access the send mailboxes at the receiving UEs the
* coresponding pointers are saved in iRCCE_mailbox_send[i] resprectively.
*/
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
int iRCCE_init(void) { int iRCCE_init(void) {
int i; int i;
@ -93,8 +100,10 @@ int iRCCE_init(void) {
// init mail-priority lists // init mail-priority lists
for( i=0; i<iRCCE_PRIOS; ++i ) { for( i=0; i<iRCCE_PRIOS; ++i ) {
iRCCE_mailbox_recv_queue[i] = NULL; iRCCE_mailbox_recv_queue[i].first = NULL;
iRCCE_mailbox_recv_queue[i].last = NULL;
} }
// allocate space in MPB for mailbox and set senders mailbox-pointer // allocate space in MPB for mailbox and set senders mailbox-pointer
for( i=0; i<RCCE_NP; i++ ) { for( i=0; i<RCCE_NP; i++ ) {
iRCCE_mailbox_recv[i] = (iRCCE_MAIL_HEADER*)RCCE_malloc(RCCE_LINE_SIZE); iRCCE_mailbox_recv[i] = (iRCCE_MAIL_HEADER*)RCCE_malloc(RCCE_LINE_SIZE);
@ -119,6 +128,8 @@ int iRCCE_finalize(void) {
iRCCE_MAIL_HEADER* run; iRCCE_MAIL_HEADER* run;
iRCCE_MAIL_HEADER* erase_header; iRCCE_MAIL_HEADER* erase_header;
iRCCE_mailbox_flush();
for( run = iRCCE_mail_garbage.first; run != NULL; ) { for( run = iRCCE_mail_garbage.first; run != NULL; ) {
erase_header = run; erase_header = run;
run = run->next; run = run->next;
@ -126,6 +137,7 @@ int iRCCE_finalize(void) {
} }
iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL; iRCCE_mail_garbage.first = iRCCE_mail_garbage.last = NULL;
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
} }
#endif #endif

View file

@ -244,18 +244,18 @@ int iRCCE_isend(
iRCCE_mail_send( send_size, iRCCE_mail_send( send_size,
iRCCE_ANYLENGTH_PIGGYBACK, iRCCE_ANYLENGTH_PIGGYBACK,
0, privbuf, dest ); 0, privbuf, dest );
NOP8; //NOP8;
NOP8; //NOP8;
icc_send_irq( dest ); //send_irq( dest );
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
} }
// we need an extra isend-call // we need an extra isend-call
else { else {
iRCCE_mail_send( send_size, iRCCE_ANYLENGTH, iRCCE_mail_send( send_size, iRCCE_ANYLENGTH,
0, NULL, dest ); 0, NULL, dest );
NOP8; //NOP8;
NOP8; //NOP8;
icc_send_irq( dest ); //send_irq( dest );
return iRCCE_isend_general( privbuf, send_size, return iRCCE_isend_general( privbuf, send_size,
dest, request ); dest, request );
} }

View file

@ -1,28 +1,36 @@
/* //******************************************************************************
* Copyright 2011 Simon Pickartz, Chair for Operating Systems, // Mailbox system.
* RWTH Aachen University //******************************************************************************
* //
* Licensed under the Apache License, Version 2.0 (the "License"); // Author: Simon Pickartz,
* you may not use this file except in compliance with the License. // Chair for Operating Systems,
* You may obtain a copy of the License at // RWTH Aachen University
* // Date: 005/08/2011
* 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, // Copyright 2010 Intel Corporation
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
* See the License for the specific language governing permissions and // Licensed under the Apache License, Version 2.0 (the "License");
* limitations under the License. // you may not use this file except in compliance with the License.
* // You may obtain a copy of the License at
* This file is part of MetalSVM. //
*/ // 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.
//
//
/* /**
* Mailbox system *
* @file contains implementation of the mailbox system
* @author Simon Pickartz
*
* *
* [2011-05-08] implemented mailbox send/recv routines
* by Simon Pickartz, Chair for Operating Systems,
* RWTH Aachen University
*/ */
#include <metalsvm/stdlib.h> #include <metalsvm/stdlib.h>
@ -30,6 +38,7 @@
#ifdef CONFIG_ROCKCREEK #ifdef CONFIG_ROCKCREEK
#include <asm/iRCCE_lib.h> #include <asm/iRCCE_lib.h>
#include <asm/irqflags.h>
/** /**
* *
@ -89,6 +98,7 @@ void iRCCE_mailbox_print_header(iRCCE_MAIL_HEADER* header) {
static int iRCCE_mail_fetch( static int iRCCE_mail_fetch(
int rank // rank from whom to empty mailbox int rank // rank from whom to empty mailbox
) { ) {
/* interrupts should already be disabled! */
iRCCE_MAIL_HEADER* header; iRCCE_MAIL_HEADER* header;
@ -109,7 +119,7 @@ static int iRCCE_mail_fetch(
// copy header to allocated memory // copy header to allocated memory
RC_cache_invalidate(); //RC_cache_invalidate();
iRCCE_memcpy_get( (void*)header, (void*)iRCCE_mailbox_recv[rank], iRCCE_memcpy_get( (void*)header, (void*)iRCCE_mailbox_recv[rank],
RCCE_LINE_SIZE ); RCCE_LINE_SIZE );
@ -124,14 +134,17 @@ static int iRCCE_mail_fetch(
int prio = header->prio; int prio = header->prio;
// enqueue accordingly // enqueue accordingly
if( iRCCE_mailbox_recv_queue[prio] == NULL ) { header->next = NULL;
iRCCE_mailbox_recv_queue[prio] = header;
if( iRCCE_mailbox_recv_queue[prio].first == NULL ) {
iRCCE_mailbox_recv_queue[prio].first = header;
iRCCE_mailbox_recv_queue[prio].last = header;
} }
else { else {
iRCCE_MAIL_HEADER* run = iRCCE_mailbox_recv_queue[prio]; iRCCE_mailbox_recv_queue[prio].last->next = header;
while( run->next != NULL ) run = run->next; iRCCE_mailbox_recv_queue[prio].last = header;
run->next = header;
} }
} }
@ -154,29 +167,92 @@ static int iRCCE_mail_fetch(
* write out the data. * write out the data.
*/ */
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static int iRCCE_mailbox_check() { iRCCE_MAIL_HEADER dummy_header = {0, 0, 0, NULL, 0, 0, 0, {[0 ... iRCCE_MAIL_HEADER_PAYLOAD-1] = 0} };
int i;
static int iRCCE_mailbox_check() {
int i,j;
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
for( j=1; j<RCCE_NP; ++j ) {
i = (j+RCCE_IAM)%RCCE_NP;
for( i=0; i<RCCE_NP; ++i ) {
if( i == RCCE_IAM ) continue;
// only check open mailboxes // only check open mailboxes
if( iRCCE_mailbox_status[i] == iRCCE_MAILBOX_OPEN ) { if( iRCCE_mailbox_status[i] == iRCCE_MAILBOX_OPEN ) {
RC_cache_invalidate(); RC_cache_invalidate();
if( iRCCE_mailbox_recv[i]->sent ) { if( iRCCE_mailbox_recv[i]->sent ) {
iRCCE_mail_fetch(i); iRCCE_mail_fetch(i);
// reset senders flag // reset senders flag
RC_cache_invalidate(); RC_cache_invalidate();
iRCCE_mailbox_recv[i]->sent = RCCE_FLAG_UNSET; *(iRCCE_mailbox_recv[i]) = dummy_header;
*(int *)RCCE_fool_write_combine_buffer = 1;
} }
} }
} }
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
} }
//------------------------------------------------------------------------------
// FUNCTION: iRCCE_mail_check
//------------------------------------------------------------------------------
/**
* @brief routine to check one specific mailbox
* @param sender is the core ID from which the mailbox is checked
*
* This function may be called by the user application to check one specific
* mailbox. It is recommended to use it in combination with an inter core
* interrupt.
*
*/
//------------------------------------------------------------------------------
int iRCCE_mail_check(int sender) {
uint32_t flags;
// check all mailboxes in case of wildcard
if( sender == iRCCE_MAILBOX_ALL ) {
iRCCE_mailbox_check();
return iRCCE_SUCCESS;
}
// verify sender's ID
if( (sender < 0) || (sender > RCCE_NP) || (sender == RCCE_IAM) ) {
return iRCCE_ERROR_SOURCE;
}
// check if mailbox is open
if( iRCCE_mailbox_status[sender] == iRCCE_MAILBOX_CLOSED ) {
return iRCCE_MAILBOX_CLOSED;
}
RC_cache_invalidate();
if( iRCCE_mailbox_recv[sender]->sent ) {
/* disable interrupts */
flags = irq_nested_disable();
iRCCE_mail_fetch(sender);
// reset senders flag
RC_cache_invalidate();
*(iRCCE_mailbox_recv[sender]) = dummy_header;
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS;
}
else {
return iRCCE_MAILBOX_EMPTY;
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// FUNCTION: iRCCE_mail_recv // FUNCTION: iRCCE_mail_recv
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -198,28 +274,39 @@ int iRCCE_mail_recv(
) { // (memory allocated by iRCCE) ) { // (memory allocated by iRCCE)
int i; int i;
uint32_t flags;
// if there is no mail, check for incoming iRCCE_MAIL_HEADER* help_header;
if ( !iRCCE_mailbox_recv_queue[0] ) {
iRCCE_mailbox_check();
}
// check priority queues // check priority queues
for( i=0; i<iRCCE_PRIOS; ++i ) { for( i=0; i<iRCCE_PRIOS; ++i ) {
if ( iRCCE_mailbox_recv_queue[i] ) { if ( iRCCE_mailbox_recv_queue[i].first ) {
iRCCE_MAIL_HEADER* help_header = /* disable interrupts */
iRCCE_mailbox_recv_queue[i]; flags = irq_nested_disable();
iRCCE_mailbox_recv_queue[i] =
iRCCE_mailbox_recv_queue[i]->next; help_header = iRCCE_mailbox_recv_queue[i].first;
iRCCE_mailbox_recv_queue[i].first =
iRCCE_mailbox_recv_queue[i].first->next;
if( iRCCE_mailbox_recv_queue[i].first == NULL ) {
iRCCE_mailbox_recv_queue[i].last = NULL;
}
help_header->next = NULL; help_header->next = NULL;
*header = help_header; *header = help_header;
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
} }
} }
// no mail queued // no mail queued
*header = NULL; *header = NULL;
return iRCCE_MAILBOX_EMPTY; return iRCCE_MAILBOX_EMPTY;
} }
@ -240,6 +327,11 @@ int iRCCE_mail_recv(
int iRCCE_mail_release( int iRCCE_mail_release(
iRCCE_MAIL_HEADER** header iRCCE_MAIL_HEADER** header
) { ) {
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
// put header in garbage collection // put header in garbage collection
if( (iRCCE_mail_garbage.first == NULL) if( (iRCCE_mail_garbage.first == NULL)
&& (iRCCE_mail_garbage.last == NULL ) ) { && (iRCCE_mail_garbage.last == NULL ) ) {
@ -255,6 +347,10 @@ int iRCCE_mail_release(
// reset header // reset header
*header = NULL; *header = NULL;
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
} }
@ -294,6 +390,12 @@ int iRCCE_mail_send(
char* payload, // pointer to buffer for header payload char* payload, // pointer to buffer for header payload
int dest // UE that will receive the header int dest // UE that will receive the header
) { ) {
uint32_t flags;
// verify sender's ID
if( (dest < 0) || (dest > RCCE_NP) || (dest == RCCE_IAM) ) {
return iRCCE_ERROR_TARGET;
}
// if dest mailbox is full, check for incoming mail // if dest mailbox is full, check for incoming mail
RC_cache_invalidate(); RC_cache_invalidate();
@ -301,7 +403,6 @@ int iRCCE_mail_send(
iRCCE_mailbox_check(); iRCCE_mailbox_check();
RC_cache_invalidate(); RC_cache_invalidate();
} }
// check if mailbox is closed // check if mailbox is closed
RCCE_acquire_lock( dest ); RCCE_acquire_lock( dest );
RC_cache_invalidate(); RC_cache_invalidate();
@ -310,6 +411,9 @@ int iRCCE_mail_send(
return iRCCE_MAILBOX_CLOSED; return iRCCE_MAILBOX_CLOSED;
} }
/* disable interrupts */
// flags = irq_nested_disable();
// prepare header // prepare header
iRCCE_MAIL_HEADER header = { RCCE_IAM, size, tag, NULL, prio, iRCCE_MAIL_HEADER header = { RCCE_IAM, size, tag, NULL, prio,
RCCE_FLAG_UNSET, RCCE_FLAG_UNSET, RCCE_FLAG_UNSET, RCCE_FLAG_UNSET,
@ -331,6 +435,9 @@ int iRCCE_mail_send(
*(int *)RCCE_fool_write_combine_buffer = 1; *(int *)RCCE_fool_write_combine_buffer = 1;
RC_cache_invalidate(); RC_cache_invalidate();
/* enable interrupts */
// irq_nested_enable(flags);
RCCE_release_lock( dest ); RCCE_release_lock( dest );
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
@ -397,16 +504,28 @@ int iRCCE_mailbox_wait(void) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int iRCCE_mailbox_flush(void) { int iRCCE_mailbox_flush(void) {
int i; int i;
uint32_t flags;
/* disable interrupts */
flags = irq_nested_disable();
// empty priority queues
for( i=0; i<iRCCE_PRIOS; ++i ) { for( i=0; i<iRCCE_PRIOS; ++i ) {
iRCCE_MAIL_HEADER* erase_header = iRCCE_mailbox_recv_queue[i]; iRCCE_MAIL_HEADER* erase_header =
iRCCE_mailbox_recv_queue[i].first;
while( erase_header != NULL ) { while( erase_header != NULL ) {
iRCCE_mailbox_recv_queue[i] = iRCCE_mailbox_recv_queue[i]->next; iRCCE_mailbox_recv_queue[i].first =
iRCCE_mailbox_recv_queue[i].first->next;
kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) ); kfree( erase_header, sizeof(iRCCE_MAIL_HEADER) );
erase_header = iRCCE_mailbox_recv_queue[i]; erase_header = iRCCE_mailbox_recv_queue[i].first;
} }
} }
/* enable interrupts */
irq_nested_enable(flags);
return iRCCE_SUCCESS; return iRCCE_SUCCESS;
} }
@ -422,16 +541,21 @@ int iRCCE_mailbox_flush(void) {
* last-mail. * last-mail.
* *
* This function closes a mailbox of the given rank. If the check flag is set * 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 * an iRCCE_mailbox_check()-call is performed. The close procedure has to be
* to be sure that no UE sends any mail while closing the mailbox. * locked to be sure that no UE sends any mail while closing the mailbox.
*/ */
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static int iRCCE_mailbox_close_one(int rank, int check) { static int iRCCE_mailbox_close_one(int rank, int check) {
uint32_t flags;
RCCE_acquire_lock( RCCE_IAM ); RCCE_acquire_lock( RCCE_IAM );
/* disable interrupts */
flags = irq_nested_disable();
// check if it contains new mail // check if it contains new mail
RC_cache_invalidate(); RC_cache_invalidate();
if( check && iRCCE_mailbox_recv[rank]->sent ) { if( check && iRCCE_mailbox_recv[rank]->sent ) {
iRCCE_mail_fetch(rank); iRCCE_mail_fetch(rank);
} }
@ -444,6 +568,9 @@ static int iRCCE_mailbox_close_one(int rank, int check) {
iRCCE_memcpy_put( (void*)iRCCE_mailbox_recv[rank], iRCCE_memcpy_put( (void*)iRCCE_mailbox_recv[rank],
&help_header, RCCE_LINE_SIZE ); &help_header, RCCE_LINE_SIZE );
/* enable interrupts */
irq_nested_enable(flags);
RCCE_release_lock( RCCE_IAM ); RCCE_release_lock( RCCE_IAM );
iRCCE_mailbox_status[rank] = iRCCE_MAILBOX_CLOSED; iRCCE_mailbox_status[rank] = iRCCE_MAILBOX_CLOSED;

View file

@ -27,6 +27,12 @@
#include <asm/icc.h> #include <asm/icc.h>
#include <asm/svm.h> #include <asm/svm.h>
#define IRQ_STATUS 0xD000
#define IRQ_MASK 0xD200
#define IRQ_RESET 0xD400
#define IRQ_REQUEST 0xD600
#define IRQ_CONFIG 0xD800
#include <net/mmnif.h> #include <net/mmnif.h>
@ -84,7 +90,7 @@ static void intr_handler(struct state *s)
int tmp, z; int tmp, z;
#ifdef CONFIG_LWIP #ifdef CONFIG_LWIP
mmnif_irqhandler(); //mmnif_irqhandler();
#endif #endif
z = Z_PID(RC_COREID[my_ue]); z = Z_PID(RC_COREID[my_ue]);
@ -97,7 +103,7 @@ int icc_init(void)
{ {
int i, z, tmp; int i, z, tmp;
uint64_t start, end, ticks, freq = 533; uint64_t start, end, ticks, freq = 533;
uint32_t cr4, msg = 0; uint32_t cr4;
kputs("Initialize Rock Creek!\n"); kputs("Initialize Rock Creek!\n");
@ -176,9 +182,46 @@ int icc_init(void)
kprintf("set L2CFG to 0x%x\n", (uint32_t) tmp); kprintf("set L2CFG to 0x%x\n", (uint32_t) tmp);
#endif #endif
tmp=ReadConfigReg(CRB_OWN + (z==0 ? L2CFG0 : L2CFG1));
kputs("In the config registers is the L2 cache ");
if (tmp & (1 << L2CFG_WAYDISABLE_BIT))
kputs("disabled!\n");
else
kputs("enabled!\n");
kputs("In CR0 is caching ");
if (read_cr0() & (1 << 30))
kputs("disabled!\n");
else
kputs("enabled!\n");
kputs("In CR0 is writethrough caching ");
if (read_cr0() & (1 << 29))
kputs("enabled!\n");
else
kputs("disabled!\n");
// set interrupt handler (INTR/LINT0) // set interrupt handler (INTR/LINT0)
irq_install_handler(124, intr_handler); irq_install_handler(124, intr_handler);
// unmask interrupts
volatile uint64_t* irq_mask = (volatile uint64_t*)(FPGA_BASE + IRQ_MASK + my_ue*8);
*irq_mask &= 0;
// reset interrupt reg
volatile uint64_t* irq_reset = (volatile uint64_t*)(FPGA_BASE + IRQ_RESET + my_ue*8);
*irq_reset = ~(0);
// set remote interrupts to LINT 0
volatile int* irq_config = (volatile int*)(FPGA_BASE + IRQ_CONFIG + my_ue*4);
*irq_config = 0;
volatile int* irq_status = (volatile int*)(FPGA_BASE + IRQ_STATUS + my_ue*8);
kprintf( "irq_mask = %x\n", *irq_mask );
kprintf( "irq_config = %x\n", *irq_config );
kprintf( "status_reg = %x\n", *irq_status );
kputs("Now, the SCC is initialized!\n"); kputs("Now, the SCC is initialized!\n");
return 0; return 0;
@ -206,107 +249,290 @@ int icc_send_irq(int ue)
int icc_halt(void) int icc_halt(void)
{ {
uint32_t flags; icc_mail_check(0);
#if 0
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);
iRCCE_irecv_push();
}
icc_mail_check();
irq_nested_enable(flags);
NOP1; 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; //HALT;
return 0; return 0;
} }
#define ROUNDS 100000
#define CORE_A 0 // sender
#define CORE_B 1 // receiver
int icc_send_gic_irq(int core_num) {
volatile uint64_t* irq_request = (volatile uint64_t*)(FPGA_BASE+IRQ_REQUEST+my_ue*8);
uint64_t bit_pos;
// determine bit position and set according bit
bit_pos = (1 << core_num);
*irq_request = bit_pos;
return 0;
}
int icc_irq_ping(void)
{
if( my_ue == 2 ) return -1 ;
icc_send_gic_irq(2);
kprintf( "my_ue = %d\n", my_ue );
kprintf( "sending irq to 1!\n");
return 0;
}
static inline void icc_mail_check_tag(iRCCE_MAIL_HEADER* mail) {
char* recv_buffer;
if( !mail ) return;
switch( mail->tag ) {
case iRCCE_ANYLENGTH:
recv_buffer = (char*)kmalloc( mail->size );
iRCCE_irecv(recv_buffer, mail->size,
mail->source, NULL );
break;
case PING_REQ:
iRCCE_mail_send(0, PING_RESP, 0, NULL, mail->source);
break;
case SVM_REQUEST:
svm_emit_page(((size_t*) mail->payload)[1], ((size_t*) mail->payload)[0]);
break;
case NOISE:
// kprintf( "XXX " );
default:
// kprintf( "icc_mail_check_tag: uknown tag id %d\n", mail->tag );
break;
}
}
int icc_mail_ping(void) int icc_mail_ping(void)
{ {
uint32_t flags; uint32_t flags;
int remote_rank = (my_ue+1)%2; uint64_t timer = 0;
uint8_t payload[iRCCE_MAIL_HEADER_PAYLOAD]; int i;
uint64_t* timer = (uint64_t*) payload; int res;
iRCCE_MAIL_HEADER* recv_header = NULL;
if (my_ue) /* leave function if not participating in pingpong */
return -1; if( (my_ue != CORE_A) && (my_ue != CORE_B) ) return -1;
kprintf( "my_ue = %d\n", my_ue );
kprintf( "Hello from mail_ping ... \n" ); kprintf( "Hello from mail_ping ... \n" );
kprintf( "rounds = %d\n", ROUNDS );
// disable interrupts // disable interrupts
flags = irq_nested_disable(); flags = irq_nested_disable();
// start timer for( i=0; i<ROUNDS+1; ++i ) {
*timer = rdtsc(); /* senders part */
if( my_ue == CORE_A ) {
/* send ping request */ /* send ping request */
iRCCE_mail_send(sizeof(uint64_t), ICC_TAG_PINGREQUEST, 0, payload, remote_rank); iRCCE_mail_send(0, PING_REQ, 0, NULL, CORE_B);
NOP8; /* wait for response */
icc_send_irq(remote_rank); do {
res = iRCCE_mail_check(CORE_B);
} while( res != iRCCE_SUCCESS );
/* check for incoming messages */ /* release mail */
icc_mail_check(); iRCCE_mail_recv(&recv_header);
iRCCE_mail_release(&recv_header);
}
/* receivers part */
else {
/* wait for request */
do {
res = iRCCE_mail_check(CORE_A);
} while( res != iRCCE_SUCCESS );
/* check mail */
res = iRCCE_mail_recv(&recv_header);
icc_mail_check_tag(recv_header);
/* release mail */
iRCCE_mail_release(&recv_header);
}
/* start timer in first round */
if( i == 0 ) timer = rdtsc();
}
/* stop timer */
timer = rdtsc() - timer;
if( my_ue == CORE_A ) {
kprintf( "timer = %ld\n", timer );
kprintf( "mail_pingpong needs in average %d ns (%d ticks)!\n",
timer*1000/(2*ROUNDS*get_cpu_frequency()), timer/(2*ROUNDS) );
}
// enable interrupts
irq_nested_enable(flags); irq_nested_enable(flags);
return 0; return 0;
} }
void icc_mail_check(void)
int icc_mail_ping_irq(void)
{
kprintf( "Hello from mail_ping_irq ... \n" );
/* return if not core A */
if( my_ue != CORE_A ) return 0;
uint32_t flags;
uint64_t timer = 0;
int i;
int res;
iRCCE_MAIL_HEADER* recv_header = NULL;
kprintf( "my_rank = %d\n", my_ue );
kprintf( "rem_rank = %d\n", CORE_B );
kprintf( "rounds = %d\n", ROUNDS );
// disable interrupts
flags = irq_nested_disable();
for( i=0; i<ROUNDS+1; ++i ) {
/* send ping request */
iRCCE_mail_send(0, PING_REQ, 0, NULL, CORE_B);
/* send interrupt */
icc_send_gic_irq(CORE_B);
/* wait for response */
do {
res = iRCCE_mail_check(CORE_B);
} while( res != iRCCE_SUCCESS );
iRCCE_mail_recv(&recv_header);
iRCCE_mail_release(&recv_header);
/* start timer in first round */
if( i == 0 ) timer = rdtsc();
}
/* stop timer */
timer = rdtsc() - timer;
kprintf( "timer = %d\n", timer );
kprintf( "mail_pingpong needs in average %d nsec (%d ticks)!\n",
timer*1000/(2*ROUNDS*533), timer/(2*ROUNDS) );
irq_nested_enable(flags);
return 0;
}
#define _iRQ_NOISE_ 0
int icc_mail_noise(void) {
int i, j, res;
int num_ranks = RCCE_num_ues();
iRCCE_MAIL_HEADER* recv_mail = NULL;
// leave function if not participating
if( !((my_ue == 4) || (my_ue == 2) || (my_ue == CORE_B)) ) {
kprintf( "mail_noise: leaving" );
return -1;
}
kprintf( "Hello from icc_mail_noise: my_ue = %d\n", my_ue );
kprintf( "num_ues = %d\n", num_ranks );
for( i=0; i<10000; ++i ) {
if( !(i%1000) ) kprintf( "%d ", i );
/* send a mail to each UE */
for( j=0; j<num_ranks; ++j ) {
if( !((j == 4) || (j == 2)/* || (j == CORE_B) */) )
continue;
/* send noise mail */
iRCCE_mail_send(0, NOISE, 1, NULL, j);
#ifdef _IRQ_NOISE_
kprintf( "sending irq ... " );
icc_send_gic_irq(j);
#endif
iRCCE_mail_recv(&recv_mail);
icc_mail_check_tag(recv_mail);
if( recv_mail ) iRCCE_mail_release(&recv_mail);
}
}
kprintf( "XXX XXX XXX" );
do {
iRCCE_mail_check(iRCCE_MAILBOX_ALL);
res = iRCCE_mail_recv(&recv_mail);
icc_mail_check_tag(recv_mail);
if( recv_mail ) iRCCE_mail_release(&recv_mail);
} while( res == iRCCE_SUCCESS );
return 0;
}
/*
* Routine to check mailboxes. If irq = 1 is passed only those boxes are checked that
* refere to the cores with set bit in status register.
*
*/
void icc_mail_check(int irq)
{ {
iRCCE_MAIL_HEADER* header = NULL; iRCCE_MAIL_HEADER* header = NULL;
uint64_t timer; int source, res;
//char* recv_buffer; volatile uint64_t* irq_status_reg = NULL;
volatile uint64_t* irq_reset_reg = NULL;
uint64_t irq_status = 0;
uint64_t irq_reset = 0;
uint32_t flags;
// empty mailbox and interpret headers /* disable interrupts */
flags = irq_nested_disable();
if( irq == 1 ) {
/* read status register */
irq_status_reg = (volatile uint64_t*)(FPGA_BASE + IRQ_STATUS + my_ue*8);
irq_status = irq_reset = *irq_status_reg;
/* determine interrupt sources */
irq_status >>= 6; // shift emac bits
for( source = 0; irq_status != 0; irq_status >>= 1, ++source ) {
if( (irq_status & 0x1) != 0 ) {
res = iRCCE_mail_check(source);
}
}
/* reset status register */
irq_reset_reg = (volatile uint64_t*)(FPGA_BASE + IRQ_RESET + my_ue*8);
*irq_reset_reg = irq_reset;
}
else {
iRCCE_mail_check(iRCCE_MAILBOX_ALL);
}
/* enable interrupts */
irq_nested_enable(flags);
/* empty mail queue */
while( iRCCE_mail_recv(&header) == iRCCE_SUCCESS ) { while( iRCCE_mail_recv(&header) == iRCCE_SUCCESS ) {
//iRCCE_mailbox_print_header(header); icc_mail_check_tag(header);
switch(header->tag)
{
case ICC_TAG_PINGREQUEST:
iRCCE_mail_send( header->size, ICC_TAG_PINGRESPONSE, 0, header->payload, header->source );
NOP8;
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;
case ICC_TAG_SVMREQUEST:
svm_emit_page(((size_t*) header->payload)[1], ((size_t*) header->payload)[0]);
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 );
}
else if( header->tag == iRCCE_ANYLENGTH_PIGGYBACK ) {
iRCCE_mail_send( 0, 2, 0, NULL, header->source );
}*/
iRCCE_mail_release( &header ); iRCCE_mail_release( &header );
NOP8;
NOP8;
NOP8;
} }
} }

View file

@ -290,24 +290,21 @@ static void rckemacif_input(struct netif* netif, struct pbuf* p)
static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset) static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset)
{ {
rckemacif_t* rckemacif = netif->state; rckemacif_t* rckemacif = netif->state;
unsigned short read_offset; unsigned short read_offset = rckemacif->rx_read_offset;
unsigned int counter; unsigned int counter;
volatile void *addr; volatile void *addr = NULL;
uint16_t i, length; uint16_t i, length = 0;
uint32_t packets = 0;
struct pbuf *p; struct pbuf *p;
struct pbuf* q; struct pbuf* q;
if (write_offset > rckemacif->rx_buffer_max) { if (write_offset > rckemacif->rx_buffer_max) {
LWIP_DEBUGF(NETIF_DEBUG, ("Warning, write offset > buffer max!! (%d > %d)\n", write_offset, rckemacif->rx_buffer_max)); LWIP_DEBUGF(NETIF_DEBUG, ("Warning, write offset > buffer max!! (%d > %d)\n", write_offset, rckemacif->rx_buffer_max));
read_offset = 1; read_offset = 1;
write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset); goto rxDone;
rckemacif->rx_read_offset = read_offset;
return;
} }
while(1) { again:
if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) {
read_offset = rckemacif->rx_read_offset;
read_offset++; read_offset++;
if (read_offset < 1 || read_offset > rckemacif->rx_buffer_max) { if (read_offset < 1 || read_offset > rckemacif->rx_buffer_max) {
read_offset = 1; read_offset = 1;
@ -352,11 +349,13 @@ static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset)
#if ETH_PAD_SIZE #if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif #endif
if (read_offset < write_offset) { if (read_offset < write_offset) {
for (q=p, counter=0; q!=NULL; q=q->next) { for (q=p, i/*counter=0*/; q!=NULL; q=q->next) {
for(i=0; i<q->len; i++, counter++) { memcpy((uint8_t*) q->payload, (uint8_t*)addr + 2, q->len);
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; //for(i=0; i<q->len; i++, counter++) {
} // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter];
//}
} }
read_offset += CLINE_PACKETS(p->len + 2) - 1; read_offset += CLINE_PACKETS(p->len + 2) - 1;
@ -409,12 +408,17 @@ out:
LINK_STATS_INC(link.drop); LINK_STATS_INC(link.drop);
} }
packets++;
rxDone: rxDone:
/* set new read pointer */ /* set new read pointer */
//LWIP_DEBUGF(NETIF_DEBUG, ("Update rx read offset: %d\n", read_offset)); //LWIP_DEBUGF(NETIF_DEBUG, ("Update rx read offset: %d\n", read_offset));
write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset); write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset);
rckemacif->rx_read_offset = read_offset; rckemacif->rx_read_offset = read_offset;
} else break;
if (read_offset != write_offset) {
if (packets < 5 /*max_num*/)
goto again;
} }
} }
@ -464,6 +468,8 @@ err_t rckemacif_init(struct netif* netif)
int subdest; int subdest;
int route; int route;
LWIP_DEBUGF(NETIF_DEBUG, ("Initialize eMAC device...\n"));
LWIP_ASSERT("netif != NULL", (netif != NULL)); LWIP_ASSERT("netif != NULL", (netif != NULL));
// Find out who I am... // Find out who I am...
@ -639,7 +645,7 @@ err_t rckemacif_init(struct netif* netif)
LWIP_DEBUGF(NETIF_DEBUG, (" ADD_FILTER_MOD set: %x\n", add_filter_mod)); LWIP_DEBUGF(NETIF_DEBUG, (" ADD_FILTER_MOD set: %x\n", add_filter_mod));
} }
sleep(3); RCCE_barrier(&RCCE_COMM_WORLD);
/* Start address */ /* Start address */
LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer %p (%lx phys)\n", rckemacif->rx_buffer, virt_to_phys((uint32_t)rckemacif->rx_buffer))); LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer %p (%lx phys)\n", rckemacif->rx_buffer, virt_to_phys((uint32_t)rckemacif->rx_buffer)));

View file

@ -80,7 +80,7 @@ inline static int spinlock_destroy(spinlock_t* s) {
* - -EINVAL (-22) on failure * - -EINVAL (-22) on failure
*/ */
inline static int spinlock_lock(spinlock_t* s) { inline static int spinlock_lock(spinlock_t* s) {
int32_t ticket; //int32_t ticket;
task_t* curr_task; task_t* curr_task;
if (BUILTIN_EXPECT(!s, 0)) if (BUILTIN_EXPECT(!s, 0))
@ -172,7 +172,7 @@ inline static int spinlock_irqsave_destroy(spinlock_irqsave_t* s) {
*/ */
inline static int spinlock_irqsave_lock(spinlock_irqsave_t* s) { inline static int spinlock_irqsave_lock(spinlock_irqsave_t* s) {
uint32_t flags; uint32_t flags;
int32_t ticket; //int32_t ticket;
if (BUILTIN_EXPECT(!s, 0)) if (BUILTIN_EXPECT(!s, 0))
return -EINVAL; return -EINVAL;
@ -183,10 +183,14 @@ inline static int spinlock_irqsave_lock(spinlock_irqsave_t* s) {
return 0; return 0;
} }
#if 0
ticket = atomic_int32_inc(&s->queue); ticket = atomic_int32_inc(&s->queue);
while (atomic_int32_read(&s->dequeue) != ticket) { while (atomic_int32_read(&s->dequeue) != ticket) {
NOP1; NOP1;
} }
#else
while( atomic_int32_test_and_set(&s->dequeue,0) );
#endif
s->coreid = CORE_ID; s->coreid = CORE_ID;
s->flags = flags; s->flags = flags;
@ -211,7 +215,11 @@ inline static int spinlock_irqsave_unlock(spinlock_irqsave_t* s) {
flags = s->flags; flags = s->flags;
s->coreid = (uint32_t) -1; s->coreid = (uint32_t) -1;
s->flags = 0; s->flags = 0;
#if 0
atomic_int32_inc(&s->dequeue); atomic_int32_inc(&s->dequeue);
#else
atomic_int32_set(&s->dequeue,1);
#endif
irq_nested_enable(flags); irq_nested_enable(flags);
} }

View file

@ -176,6 +176,13 @@ size_t get_idle_task(uint32_t id);
*/ */
int sys_execve(const char* fname, char** argv, char** env); int sys_execve(const char* fname, char** argv, char** env);
/** @brief determines the highest priority of all ready tasks on core core_id
*
* @param core_id core id
* @return highest priority
*/
uint32_t get_highest_priority(uint32_t core_id);
/** @brief Call to rescheduling /** @brief Call to rescheduling
* *
* This is a purely assembled procedure for rescheduling * This is a purely assembled procedure for rescheduling
@ -185,12 +192,16 @@ void reschedule(void);
static inline void check_workqueues(void) static inline void check_workqueues(void)
{ {
#ifdef CONFIG_ROCKCREEK #ifdef CONFIG_ROCKCREEK
uint32_t flags = irq_nested_disable(); icc_mail_check(0);
icc_mail_check();
irq_nested_enable(flags);
#endif #endif
} }
static inline void check_workqueues_rem_irq(void)
{
#ifdef CONFIG_ROCKCREEK
icc_mail_check(1);
#endif
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -153,7 +153,7 @@ int network_init(void)
} }
} }
#else #else
mmnif_open(); //mmnif_open();
#endif #endif
// start echo and ping server // start echo and ping server
@ -169,7 +169,7 @@ int network_shutdown(void)
{ {
#ifdef CONFIG_LWIP #ifdef CONFIG_LWIP
#ifdef CONFIG_ROCKCREEK #ifdef CONFIG_ROCKCREEK
mmnif_close(); //mmnif_close();
#elif defined(CONFIG_PCI) #elif defined(CONFIG_PCI)
dhcp_release(default_netif); dhcp_release(default_netif);
dhcp_stop(default_netif); dhcp_stop(default_netif);

View file

@ -96,7 +96,7 @@ int main(void)
while(1) { while(1) {
#ifdef CONFIG_ROCKCREEK #ifdef CONFIG_ROCKCREEK
icc_halt(); //icc_halt();
#else #else
HALT; HALT;
#endif #endif

View file

@ -193,7 +193,7 @@ int syscall_handler(uint32_t sys_nr, ...)
int ret = -EINVAL; int ret = -EINVAL;
va_list vl; va_list vl;
check_workqueues(); check_workqueues_rem_irq();
va_start(vl, sys_nr); va_start(vl, sys_nr);

View file

@ -69,6 +69,10 @@ task_t* get_current_task(void) {
return per_core(current_task); return per_core(current_task);
} }
uint32_t get_highest_priority(uint32_t core_id) {
return last_set(runqueues[core_id].prio_bitmap);
}
int multitasking_init(void) { int multitasking_init(void) {
if (BUILTIN_EXPECT(task_table[0].status != TASK_IDLE, 0)) { if (BUILTIN_EXPECT(task_table[0].status != TASK_IDLE, 0)) {
kputs("Task 0 is not an idle task\n"); kputs("Task 0 is not an idle task\n");
@ -108,7 +112,7 @@ size_t get_idle_task(uint32_t id)
#endif #endif
} }
static void finish_task_switch(void) static void finish_task_switch(uint32_t irq)
{ {
uint8_t prio; uint8_t prio;
uint32_t core_id = CORE_ID; uint32_t core_id = CORE_ID;
@ -131,6 +135,7 @@ static void finish_task_switch(void)
} }
spinlock_unlock(&runqueues[core_id].lock); spinlock_unlock(&runqueues[core_id].lock);
if (irq)
irq_enable(); irq_enable();
} }
@ -396,7 +401,7 @@ int sys_fork(void)
// Leave the function without releasing the locks // Leave the function without releasing the locks
// because the locks are already released // because the locks are already released
// by the parent task! // by the parent task!
finish_task_switch(); finish_task_switch(1);
return 0; return 0;
} }
@ -431,7 +436,7 @@ static int STDCALL kernel_entry(void* args)
int ret; int ret;
kernel_args_t* kernel_args = (kernel_args_t*) args; kernel_args_t* kernel_args = (kernel_args_t*) args;
finish_task_switch(); finish_task_switch(1);
if (BUILTIN_EXPECT(!kernel_args, 0)) if (BUILTIN_EXPECT(!kernel_args, 0))
return -EINVAL; return -EINVAL;
@ -556,7 +561,7 @@ static int load_task(load_args_t* largs)
kprintf("Could not map 0x%x at 0x%x\n", addr, prog_header.virt_addr); kprintf("Could not map 0x%x at 0x%x\n", addr, prog_header.virt_addr);
// clear pages // clear pages
memset((void*) prog_header.virt_addr, 0, npages*PAGE_SIZE); memset((void*) prog_header.virt_addr, 0x00, npages*PAGE_SIZE);
// set starting point of the heap // set starting point of the heap
if (curr_task->start_heap < prog_header.virt_addr+prog_header.mem_size) if (curr_task->start_heap < prog_header.virt_addr+prog_header.mem_size)
@ -592,7 +597,7 @@ static int load_task(load_args_t* largs)
kprintf("Could not map stack at 0x%x\n", stack); kprintf("Could not map stack at 0x%x\n", stack);
return -ENOMEM; return -ENOMEM;
} }
memset((void*) stack, 0, npages*PAGE_SIZE); memset((void*) stack, 0x00, npages*PAGE_SIZE);
// create vma regions for the user-level stack // create vma regions for the user-level stack
flags = VMA_CACHEABLE; flags = VMA_CACHEABLE;
@ -695,7 +700,7 @@ static int STDCALL user_entry(void* arg)
{ {
int ret; int ret;
finish_task_switch(); finish_task_switch(1);
if (BUILTIN_EXPECT(!arg, 0)) if (BUILTIN_EXPECT(!arg, 0))
return -EINVAL; return -EINVAL;
@ -1028,8 +1033,9 @@ int set_timer(uint64_t deadline)
if (runqueues[core_id].timers.last) if (runqueues[core_id].timers.last)
runqueues[core_id].timers.last->next = curr_task; runqueues[core_id].timers.last->next = curr_task;
runqueues[core_id].timers.last = curr_task; runqueues[core_id].timers.last = curr_task;
if (!runqueues[core_id].timers.first) // obsolete lines...
runqueues[core_id].timers.first = curr_task; //if (!runqueues[core_id].timers.first)
// runqueues[core_id].timers.first = curr_task;
} else { } else {
curr_task->prev = tmp->prev; curr_task->prev = tmp->prev;
curr_task->next = tmp; curr_task->next = tmp;
@ -1209,7 +1215,9 @@ void scheduler(void)
// remove timer from queue // remove timer from queue
runqueues[core_id].timers.first = runqueues[core_id].timers.first->next; runqueues[core_id].timers.first = runqueues[core_id].timers.first->next;
if (!runqueues[core_id].timers.first) if (runqueues[core_id].timers.first)
runqueues[core_id].timers.first->prev = NULL;
else
runqueues[core_id].timers.last = NULL; runqueues[core_id].timers.last = NULL;
task->flags &= ~TASK_TIMER; task->flags &= ~TASK_TIMER;
@ -1281,6 +1289,7 @@ get_task_out:
//kprintf("schedule from %u to %u with prio %u on core %u\n", //kprintf("schedule from %u to %u with prio %u on core %u\n",
// orig_task->id, curr_task->id, (uint32_t)curr_task->prio, CORE_ID); // orig_task->id, curr_task->id, (uint32_t)curr_task->prio, CORE_ID);
switch_task(curr_task->id); switch_task(curr_task->id);
finish_task_switch(0);
} }
} }

View file

@ -103,15 +103,18 @@ static int foo(void* arg)
} }
#ifdef CONFIG_ROCKCREEK #ifdef CONFIG_ROCKCREEK
int mail_ping(void* arg) { static int mail_ping(void* arg) {
int i; //icc_mail_ping();
icc_mail_ping_irq();
//icc_irq_ping();
//icc_halt();
for(i=0; i<20; i++) { return 0;
if (BUILTIN_EXPECT(icc_mail_ping(), 0))
return -1;
udelay(500000);
} }
static int mail_noise(void*arg) {
icc_mail_noise(); // generate noise in the mesh
return 0; return 0;
} }
@ -133,7 +136,7 @@ static int svm_test(void *arg)
my_ue = RCCE_ue(); my_ue = RCCE_ue();
num_ues = RCCE_num_ues(); num_ues = RCCE_num_ues();
#if 1 #if 0
if (!my_ue) { if (!my_ue) {
// allocate and initialize SVM region // allocate and initialize SVM region
A[0] = (int*) kmalloc(3*N*N*sizeof(int)); A[0] = (int*) kmalloc(3*N*N*sizeof(int));
@ -166,7 +169,7 @@ static int svm_test(void *arg)
end = rdtsc(); end = rdtsc();
kprintf("Calculation time (seq): %llu\n", end-start); kprintf("Calculation time (seq): %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start);
kfree(A[0], 3*N*N*sizeof(int)); kfree(A[0], 3*N*N*sizeof(int));
} }
@ -204,11 +207,9 @@ static int svm_test(void *arg)
start = rdtsc(); start = rdtsc();
start = rdtsc(); start = rdtsc();
#ifndef LAZY
// Now, we need only read access on A and B // Now, we need only read access on A and B
change_page_permissions((size_t) A[0], (size_t) (A[0]+2*N*N), VMA_CACHEABLE|VMA_READ); change_page_permissions((size_t) A[0], (size_t) (A[0]+2*N*N), VMA_CACHEABLE|VMA_READ);
RCCE_barrier(&RCCE_COMM_WORLD); RCCE_barrier(&RCCE_COMM_WORLD);
#endif
// start calculation // start calculation
for(i=my_ue*(N/num_ues); i<(my_ue+1)*(N/num_ues); i++) for(i=my_ue*(N/num_ues); i<(my_ue+1)*(N/num_ues); i++)
@ -239,7 +240,7 @@ static int svm_test(void *arg)
RCCE_barrier(&RCCE_COMM_WORLD); RCCE_barrier(&RCCE_COMM_WORLD);
kprintf("Calculation time (par): %llu\n", end-start); kprintf("Calculation time (par): %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start);
svmfree((void*) A[0], 3*N*sizeof(int)); svmfree((void*) A[0], 3*N*sizeof(int));
@ -412,13 +413,12 @@ int test_init(void)
//create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO); //create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO);
//create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO); //create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, producer, NULL);
//create_kernel_task(NULL, consumer, NULL);
//create_kernel_task(NULL, mail_ping, NULL);
//create_kernel_task(NULL, svm_test, NULL);
//create_kernel_task(NULL, producer, , NORMAL_PRIO); //create_kernel_task(NULL, producer, , NORMAL_PRIO);
//create_kernel_task(NULL, consumer, NULL, NORMAL_PRIO); //create_kernel_task(NULL, consumer, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, mail_ping, NULL, NORMAL_PRIO); //create_kernel_task(NULL, mail_ping, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, mail_noise, NULL, NORMAL_PRIO);
//create_kernel_task(NULL, svm_test, NULL, NORMAL_PRIO);
//create_user_task(NULL, "/bin/hello", argv); //create_user_task(NULL, "/bin/hello", argv);
create_user_task(NULL, "/bin/mshell", argv); create_user_task(NULL, "/bin/mshell", argv);
//create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv);

View file

@ -1,3 +1,51 @@
# pid mch-route mch-dest-id mch-offset-base testcase # pid mch-route mch-dest-id mch-offset-base testcase
0x00 0x00 6 0x00 metalsvm.obj 0 metalsvm.obj
0x01 0x00 6 0x01 metalsvm.obj 1 metalsvm.obj
2 metalsvm.obj
3 metalsvm.obj
4 metalsvm.obj
5 metalsvm.obj
6 metalsvm.obj
7 metalsvm.obj
8 metalsvm.obj
9 metalsvm.obj
10 metalsvm.obj
11 metalsvm.obj
12 metalsvm.obj
13 metalsvm.obj
14 metalsvm.obj
15 metalsvm.obj
16 metalsvm.obj
17 metalsvm.obj
18 metalsvm.obj
19 metalsvm.obj
20 metalsvm.obj
21 metalsvm.obj
22 metalsvm.obj
23 metalsvm.obj
24 metalsvm.obj
25 metalsvm.obj
26 metalsvm.obj
27 metalsvm.obj
28 metalsvm.obj
29 metalsvm.obj
30 metalsvm.obj
31 metalsvm.obj
32 metalsvm.obj
33 metalsvm.obj
34 metalsvm.obj
35 metalsvm.obj
36 metalsvm.obj
37 metalsvm.obj
38 metalsvm.obj
39 metalsvm.obj
40 metalsvm.obj
41 metalsvm.obj
42 metalsvm.obj
43 metalsvm.obj
44 metalsvm.obj
45 metalsvm.obj
46 metalsvm.obj
47 metalsvm.obj