Merge branch 'master' into ohligs
Conflicts: kernel/tests.c
This commit is contained in:
commit
ed5dba2672
25 changed files with 846 additions and 327 deletions
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ inline static uint32_t irq_nested_disable(void) {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
asm volatile("pushf; cli; popl %0": "=r"(flags) : : "memory");
|
asm volatile("pushf; cli; popl %0": "=r"(flags) : : "memory");
|
||||||
if (flags & (1 << 9))
|
if (flags & (1 << 9))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
check_workqueues();
|
if( s->int_no == 124 ) {
|
||||||
|
check_workqueues_rem_irq();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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
|
||||||
|
@ -277,5 +282,8 @@ void irq_handler(struct state *s)
|
||||||
leave_handler:
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,7 +98,8 @@ 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;
|
||||||
|
|
||||||
// check for memory in garbage collection or allocate new
|
// check for memory in garbage collection or allocate new
|
||||||
|
@ -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,
|
||||||
|
@ -329,10 +433,13 @@ int iRCCE_mail_send(
|
||||||
RC_cache_invalidate();
|
RC_cache_invalidate();
|
||||||
iRCCE_mailbox_send[dest]->sent = RCCE_FLAG_SET;
|
iRCCE_mailbox_send[dest]->sent = RCCE_FLAG_SET;
|
||||||
*(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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -443,6 +567,9 @@ static int iRCCE_mailbox_close_one(int rank, int check) {
|
||||||
RC_cache_invalidate();
|
RC_cache_invalidate();
|
||||||
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 );
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
} while(do_send);
|
|
||||||
#else
|
|
||||||
// iRCCE is not thread save => disable interrupts
|
|
||||||
flags = irq_nested_disable();
|
|
||||||
icc_mail_check();
|
|
||||||
irq_nested_enable(flags);
|
|
||||||
NOP1;
|
NOP1;
|
||||||
#endif
|
|
||||||
//HALT;
|
//HALT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int icc_mail_ping( void )
|
#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)
|
||||||
{
|
{
|
||||||
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();
|
||||||
|
|
||||||
|
for( i=0; i<ROUNDS+1; ++i ) {
|
||||||
|
/* senders part */
|
||||||
|
if( my_ue == CORE_A ) {
|
||||||
|
/* send ping request */
|
||||||
|
iRCCE_mail_send(0, PING_REQ, 0, NULL, CORE_B);
|
||||||
|
|
||||||
// start timer
|
/* wait for response */
|
||||||
*timer = rdtsc();
|
do {
|
||||||
|
res = iRCCE_mail_check(CORE_B);
|
||||||
|
} while( res != iRCCE_SUCCESS );
|
||||||
|
|
||||||
/* send ping request */
|
/* release mail */
|
||||||
iRCCE_mail_send(sizeof(uint64_t), ICC_TAG_PINGREQUEST, 0, payload, remote_rank);
|
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 );
|
||||||
|
|
||||||
NOP8;
|
/* check mail */
|
||||||
icc_send_irq(remote_rank);
|
res = iRCCE_mail_recv(&recv_header);
|
||||||
|
icc_mail_check_tag(recv_header);
|
||||||
|
|
||||||
/* check for incoming messages */
|
/* release mail */
|
||||||
icc_mail_check();
|
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)
|
||||||
{
|
{
|
||||||
iRCCE_MAIL_HEADER* header = NULL;
|
kprintf( "Hello from mail_ping_irq ... \n" );
|
||||||
uint64_t timer;
|
/* return if not core A */
|
||||||
//char* recv_buffer;
|
if( my_ue != CORE_A ) return 0;
|
||||||
|
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t timer = 0;
|
||||||
|
int i;
|
||||||
|
int res;
|
||||||
|
iRCCE_MAIL_HEADER* recv_header = NULL;
|
||||||
|
|
||||||
// empty mailbox and interpret headers
|
kprintf( "my_rank = %d\n", my_ue );
|
||||||
while( iRCCE_mail_recv( &header ) == iRCCE_SUCCESS ) {
|
kprintf( "rem_rank = %d\n", CORE_B );
|
||||||
//iRCCE_mailbox_print_header(header);
|
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);
|
||||||
|
|
||||||
switch(header->tag)
|
/* send interrupt */
|
||||||
{
|
icc_send_gic_irq(CORE_B);
|
||||||
case ICC_TAG_PINGREQUEST:
|
|
||||||
iRCCE_mail_send( header->size, ICC_TAG_PINGRESPONSE, 0, header->payload, header->source );
|
/* wait for response */
|
||||||
NOP8;
|
do {
|
||||||
icc_send_irq( header->source );
|
res = iRCCE_mail_check(CORE_B);
|
||||||
break;
|
} while( res != iRCCE_SUCCESS );
|
||||||
case ICC_TAG_PINGRESPONSE:
|
|
||||||
timer = rdtsc() - *((uint64_t*) header->payload);
|
iRCCE_mail_recv(&recv_header);
|
||||||
kprintf( "Response received in %d ticks!\n", timer );
|
iRCCE_mail_release(&recv_header);
|
||||||
break;
|
|
||||||
case ICC_TAG_SVMREQUEST:
|
/* start timer in first round */
|
||||||
svm_emit_page(((size_t*) header->payload)[1], ((size_t*) header->payload)[0]);
|
if( i == 0 ) timer = rdtsc();
|
||||||
break;
|
|
||||||
default:
|
}
|
||||||
kprintf("Invalid mail: tag = %d\n", header->tag);
|
|
||||||
break;
|
/* stop timer */
|
||||||
}
|
timer = rdtsc() - timer;
|
||||||
/*else if( header->tag == iRCCE_ANYLENGTH ) {
|
|
||||||
recv_buffer = (char*)kmalloc( header->size );
|
kprintf( "timer = %d\n", timer );
|
||||||
iRCCE_irecv( recv_buffer, header->size, header->source, NULL );
|
kprintf( "mail_pingpong needs in average %d nsec (%d ticks)!\n",
|
||||||
iRCCE_mail_send( 0, 2, 0, NULL, header->source );
|
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);
|
||||||
}
|
}
|
||||||
else if( header->tag == iRCCE_ANYLENGTH_PIGGYBACK ) {
|
}
|
||||||
iRCCE_mail_send( 0, 2, 0, NULL, header->source );
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
int source, res;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* 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 ) {
|
||||||
|
icc_mail_check_tag(header);
|
||||||
iRCCE_mail_release( &header );
|
iRCCE_mail_release( &header );
|
||||||
|
NOP8;
|
||||||
|
NOP8;
|
||||||
|
NOP8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,131 +290,135 @@ 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++;
|
||||||
read_offset = rckemacif->rx_read_offset;
|
if (read_offset < 1 || read_offset > rckemacif->rx_buffer_max) {
|
||||||
read_offset++;
|
read_offset = 1;
|
||||||
if (read_offset < 1 || read_offset > rckemacif->rx_buffer_max) {
|
}
|
||||||
read_offset = 1;
|
addr = rckemacif->rx_buffer + read_offset * 32;
|
||||||
}
|
|
||||||
addr = rckemacif->rx_buffer + read_offset * 32;
|
|
||||||
|
|
||||||
length = U16(addr);
|
length = U16(addr);
|
||||||
|
|
||||||
// Check for over/underflow
|
// Check for over/underflow
|
||||||
if ((length < 20) || (length > 1536)) {
|
if ((length < 20) || (length > 1536)) {
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_handler(): illegal packet length %d => drop\n", length));
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_handler(): illegal packet length %d => drop\n", length));
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("start read at %d; write_offset at %d; addr: %p, packet len: %d\n", read_offset, write_offset, addr, length));
|
LWIP_DEBUGF(NETIF_DEBUG, ("start read at %d; write_offset at %d; addr: %p, packet len: %d\n", read_offset, write_offset, addr, length));
|
||||||
|
|
||||||
read_offset = write_offset;
|
read_offset = write_offset;
|
||||||
#if 1
|
#if 1
|
||||||
kprintf("Buffer:\n");
|
kprintf("Buffer:\n");
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
kprintf("%2.2x ", ((char*)addr)[i] & 0xFF);
|
kprintf("%2.2x ", ((char*)addr)[i] & 0xFF);
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
|
|
||||||
kprintf("Buffer0:\n");
|
kprintf("Buffer0:\n");
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
kprintf("%2.2x ", ((char*)rckemacif->rx_buffer)[i] & 0xFF);
|
kprintf("%2.2x ", ((char*)rckemacif->rx_buffer)[i] & 0xFF);
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LINK_STATS_INC(link.memerr);
|
LINK_STATS_INC(link.memerr);
|
||||||
LINK_STATS_INC(link.drop);
|
LINK_STATS_INC(link.drop);
|
||||||
|
|
||||||
goto rxDone;
|
goto rxDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
length += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
||||||
|
#endif
|
||||||
|
//LWIP_DEBUGF(NETIF_DEBUG, ("length %u, read_offset %u, write_offset %u\n", length, read_offset, write_offset));
|
||||||
|
|
||||||
|
p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
|
||||||
|
if (p) {
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (read_offset < write_offset) {
|
||||||
|
for (q=p, i/*counter=0*/; q!=NULL; q=q->next) {
|
||||||
|
memcpy((uint8_t*) q->payload, (uint8_t*)addr + 2, q->len);
|
||||||
|
//for(i=0; i<q->len; i++, counter++) {
|
||||||
|
// ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter];
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ETH_PAD_SIZE
|
read_offset += CLINE_PACKETS(p->len + 2) - 1;
|
||||||
length += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
} else {
|
||||||
#endif
|
int rest;
|
||||||
//LWIP_DEBUGF(NETIF_DEBUG, ("length %u, read_offset %u, write_offset %u\n", length, read_offset, write_offset));
|
int bytesLeft = length;
|
||||||
|
int bytesToCopy = length;
|
||||||
|
|
||||||
p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
|
/* rest to the end of buffer - 2 bytes length information */
|
||||||
if (p) {
|
rest = (rckemacif->rx_buffer_max - read_offset + 1) * 32 - 2;
|
||||||
#if ETH_PAD_SIZE
|
if (length > rest)
|
||||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
bytesToCopy = rest;
|
||||||
#endif
|
LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft));
|
||||||
if (read_offset < write_offset) {
|
|
||||||
for (q=p, counter=0; q!=NULL; q=q->next) {
|
|
||||||
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;
|
for (q=p, counter=0; q!=NULL; q=q->next) {
|
||||||
} else {
|
for(i=0; i<q->len; i++, counter++) {
|
||||||
int rest;
|
if (counter < bytesToCopy)
|
||||||
int bytesLeft = length;
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter];
|
||||||
int bytesToCopy = length;
|
else
|
||||||
|
goto out;
|
||||||
/* rest to the end of buffer - 2 bytes length information */
|
}
|
||||||
rest = (rckemacif->rx_buffer_max - read_offset + 1) * 32 - 2;
|
}
|
||||||
if (length > rest)
|
|
||||||
bytesToCopy = rest;
|
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft));
|
|
||||||
|
|
||||||
for (q=p, counter=0; q!=NULL; q=q->next) {
|
|
||||||
for(i=0; i<q->len; i++, counter++) {
|
|
||||||
if (counter < bytesToCopy)
|
|
||||||
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter];
|
|
||||||
else
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
bytesLeft -= bytesToCopy;
|
bytesLeft -= bytesToCopy;
|
||||||
|
|
||||||
if (bytesLeft != 0) {
|
if (bytesLeft != 0) {
|
||||||
addr = rckemacif->rx_buffer + 0x20;
|
addr = rckemacif->rx_buffer + 0x20;
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0]));
|
LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0]));
|
||||||
for(counter=0; (i<q->len) && (counter < bytesLeft); i++, counter++)
|
for(counter=0; (i<q->len) && (counter < bytesLeft); i++, counter++)
|
||||||
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter];
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter];
|
||||||
for(q=q->next; (q!=NULL) && (counter < bytesLeft); q=q->next) {
|
for(q=q->next; (q!=NULL) && (counter < bytesLeft); q=q->next) {
|
||||||
for(i=0; (i<q->len) && (counter < bytesLeft); i++, counter++) {
|
for(i=0; (i<q->len) && (counter < bytesLeft); i++, counter++) {
|
||||||
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter];
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter];
|
||||||
}
|
|
||||||
}
|
|
||||||
read_offset = CLINE_PACKETS(bytesLeft);
|
|
||||||
} else {
|
|
||||||
read_offset += CLINE_PACKETS(p->len + 2) - 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
read_offset = CLINE_PACKETS(bytesLeft);
|
||||||
|
} else {
|
||||||
|
read_offset += CLINE_PACKETS(p->len + 2) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if ETH_PAD_SIZE
|
#if ETH_PAD_SIZE
|
||||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
#endif
|
#endif
|
||||||
rckemacif_input(netif, p);
|
rckemacif_input(netif, p);
|
||||||
LINK_STATS_INC(link.recv);
|
LINK_STATS_INC(link.recv);
|
||||||
} else {
|
} else {
|
||||||
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_inthandler: not enough memory!\n"));
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_inthandler: not enough memory!\n"));
|
||||||
LINK_STATS_INC(link.memerr);
|
LINK_STATS_INC(link.memerr);
|
||||||
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)));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -228,7 +228,7 @@ int initd(void* arg)
|
||||||
network_init();
|
network_init();
|
||||||
list_root();
|
list_root();
|
||||||
test_init();
|
test_init();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,7 +135,8 @@ static void finish_task_switch(void)
|
||||||
}
|
}
|
||||||
spinlock_unlock(&runqueues[core_id].lock);
|
spinlock_unlock(&runqueues[core_id].lock);
|
||||||
|
|
||||||
irq_enable();
|
if (irq)
|
||||||
|
irq_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Wakeup tasks which are waiting for a message from the current one
|
/** @brief Wakeup tasks which are waiting for a message from the current one
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue