mirror of https://github.com/l4ka/hazelnut.git
353 lines
7.0 KiB
C
353 lines
7.0 KiB
C
#include <l4/l4.h>
|
|
|
|
#include <l4/helpers.h>
|
|
#include <l4io.h>
|
|
|
|
|
|
//#define PERFMON
|
|
|
|
#define PING_PONG_PRIO 128
|
|
|
|
int MIGRATE = 0;
|
|
int INTER_AS = 1;
|
|
int SMALL_AS = 0;
|
|
|
|
|
|
#if 1
|
|
extern "C" void memset(char* p, char c, int size)
|
|
{
|
|
for (;size--;)
|
|
*(p++)=c;
|
|
}
|
|
#endif
|
|
|
|
|
|
static inline void rdpmc(int no, qword_t* res)
|
|
{
|
|
#if (__ARCH__ == x86)
|
|
dword_t dummy;
|
|
__asm__ __volatile__ (
|
|
#if defined(PERFMON)
|
|
"rdpmc"
|
|
#else
|
|
""
|
|
#endif
|
|
: "=a"(*(dword_t*)res), "=d"(*((dword_t*)res + 1)), "=c"(dummy)
|
|
: "c"(no)
|
|
: "memory");
|
|
#endif
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_ARCH_X86)
|
|
#define rdtsc(x) __asm__ __volatile__ ("rdtsc" : "=a"(x): : "edx");
|
|
#else
|
|
#define rdtsc(x) x = 0
|
|
#endif
|
|
|
|
|
|
|
|
#define WHATTODO \
|
|
"sub %%ebp,%%ebp \n\t" \
|
|
"sub %%ecx,%%ecx \n\t" \
|
|
"sub %%eax,%%eax \n\t" \
|
|
IPC_SYSENTER
|
|
|
|
|
|
|
|
l4_threadid_t master_tid;
|
|
l4_threadid_t ping_tid;
|
|
l4_threadid_t pong_tid;
|
|
|
|
|
|
dword_t ping_stack[1024];
|
|
dword_t pong_stack[1024];
|
|
|
|
void pong_thread(void)
|
|
{
|
|
#if (__ARCH__ != x86)
|
|
dword_t dummy;
|
|
l4_msgdope_t dope;
|
|
#endif
|
|
l4_threadid_t t = ping_tid;
|
|
|
|
if (MIGRATE)
|
|
while (!get_current_cpu())
|
|
/* wait */;
|
|
|
|
while(1)
|
|
#if (__ARCH__ != x86)
|
|
l4_ipc_call(t,
|
|
0,
|
|
3, 2, 1,
|
|
0,
|
|
&dummy, &dummy, &dummy,
|
|
L4_IPC_NEVER, &dope);
|
|
#else
|
|
__asm__ __volatile__ (
|
|
"pushl %%ebp \n\t"
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
"popl %%ebp \n\t"
|
|
:
|
|
: "S"(t.raw)
|
|
: "eax", "ecx", "edx", "ebx", "edi");
|
|
#endif
|
|
}
|
|
|
|
void ping_thread(void)
|
|
{
|
|
dword_t in, out;
|
|
#ifdef PERFMON
|
|
qword_t cnt0,cnt1;
|
|
#endif
|
|
dword_t dummy;
|
|
l4_msgdope_t dope;
|
|
l4_threadid_t t = pong_tid;
|
|
dword_t go = 1;
|
|
|
|
/* Wait for pong thread to come up. */
|
|
l4_ipc_receive(t, 0,
|
|
&dummy, &dummy, &dummy,
|
|
L4_IPC_NEVER, &dope);
|
|
|
|
while (go)
|
|
{
|
|
for (int j = 10; j--;)
|
|
{
|
|
dword_t i;
|
|
#define ROUNDS 100000
|
|
i = ROUNDS;
|
|
#define FACTOR (8)
|
|
i /= FACTOR; i *= FACTOR;
|
|
#ifdef PERFMON
|
|
rdpmc(0,&cnt0);
|
|
#endif
|
|
rdtsc(in);
|
|
register l4_threadid_t t = pong_tid;
|
|
for (;i; i -= FACTOR)
|
|
{
|
|
#if (__ARCH__ != x86)
|
|
for (int j = 0; j < FACTOR; j++)
|
|
l4_ipc_call(t,
|
|
0,
|
|
1, 2, 3,
|
|
0,
|
|
&dummy, &dummy, &dummy,
|
|
L4_IPC_NEVER, &dope);
|
|
#else
|
|
__asm__ __volatile__ (
|
|
"pushl %%ebp \n\t"
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
WHATTODO
|
|
"popl %%ebp \n\t"
|
|
:
|
|
: "S"(t.raw)
|
|
: "eax", "ecx", "edx", "ebx", "edi");
|
|
#endif
|
|
}
|
|
rdtsc(out);
|
|
#ifdef PERFMON
|
|
rdpmc(0,&cnt1);
|
|
printf("rdpmc(0) = %Ld\n", cnt0);
|
|
printf("rdpmc(1) = %Ld\n", cnt1);
|
|
printf("events: %ld.%02ld\n",
|
|
(((long)(cnt1-cnt0) )/(ROUNDS*2)),
|
|
(((long)(cnt1-cnt0)*100)/(ROUNDS*2))%100);
|
|
#endif
|
|
printf("%d cycles (%d)\n",
|
|
(out-in),
|
|
(unsigned int) (((long)(out-in) )/(ROUNDS*2)));
|
|
outdec((out-in)/2); kd_display(" cycles\\r\\n");
|
|
}
|
|
enter_kdebug("done");
|
|
|
|
for (;;)
|
|
{
|
|
outstring("What now?\r\n"
|
|
" g - Continue\r\n"
|
|
" q - Quit/New measurement\r\n\r\n");
|
|
char c = kd_inchar();
|
|
if ( c == 'g' ) { break; }
|
|
if ( c == 'q' ) { go = 0; break; }
|
|
}
|
|
}
|
|
|
|
/* Tell master that we're finished. */
|
|
l4_ipc_send(master_tid, 0, 0, 0, 0, L4_IPC_NEVER, &dope);
|
|
|
|
for (;;)
|
|
l4_sleep(0);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
|
|
#define PAGE_BITS 12
|
|
#define PAGE_SIZE (1 << PAGE_BITS)
|
|
#define PAGE_MASK (~(PAGE_SIZE-1))
|
|
|
|
dword_t pager_stack[512];
|
|
|
|
void pager(void)
|
|
{
|
|
l4_threadid_t t;
|
|
l4_msgdope_t dope;
|
|
dword_t dw0, dw1, dw2;
|
|
dword_t map = 2;
|
|
|
|
while (4)
|
|
{
|
|
l4_ipc_wait(&t, 0, &dw0, &dw1, &dw2, L4_IPC_NEVER, &dope);
|
|
|
|
while(5)
|
|
{
|
|
/* touch page */
|
|
// *((volatile dword_t*) dw0) = *((volatile dword_t*) dw0);
|
|
dw0 &= PAGE_MASK;
|
|
dw1 = dw0 | 0x32;
|
|
l4_ipc_reply_and_wait(t, (void *) map,
|
|
dw0, dw1, dw2,
|
|
&t, 0,
|
|
&dw0, &dw1, &dw2,
|
|
L4_IPC_NEVER, &dope);
|
|
if (L4_IPC_ERROR(dope))
|
|
{
|
|
printf("%s: error reply_and_wait (%x)\n",
|
|
__FUNCTION__, dope.raw);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
l4_threadid_t thepager, foo;
|
|
l4_msgdope_t dope;
|
|
dword_t dummy;
|
|
|
|
// printf("KVER=%x\n", ({int v; asm("hlt" : "=a"(v)); v;}));
|
|
|
|
// printf("KVER=%x\n", l4_get_kernelversion());
|
|
|
|
// enter_kdebug("xxx");
|
|
// __asm__ __volatile__ ("int $30;jmp 1f;.ascii \"huhu\";1:");
|
|
// enter_kdebug("yyy");
|
|
|
|
printf("KTEST using the following code sequence for IPC:\n");
|
|
outstring("KTEST using the following code sequence for IPC:\n");
|
|
printf("->->->->->-\n"); outstring("->->->->->-\n\r\t");
|
|
printf("%s", IPC_SYSENTER); outstring(IPC_SYSENTER);
|
|
printf("\r-<-<-<-<-<-\n"); outstring("\r-<-<-<-<-<-\n");
|
|
|
|
/* Create pager */
|
|
thepager = master_tid = l4_myself();
|
|
thepager.id.thread = 1;
|
|
l4_thread_ex_regs(thepager,
|
|
(dword_t) pager,
|
|
(dword_t) pager_stack + sizeof(pager_stack),
|
|
&foo, &foo, &dummy, &dummy, &dummy);
|
|
|
|
for (;;)
|
|
{
|
|
for (;;)
|
|
{
|
|
outstring("\nPlease select ipc type:\n");
|
|
outstring("\r\n"
|
|
"0: INTER-AS\r\n"
|
|
"1: INTER-AS (small)\r\n"
|
|
"2: INTRA-AS\r\n"
|
|
"3: XCPU\r\n");
|
|
char c = kd_inchar();
|
|
if (c == '0') { INTER_AS=1; MIGRATE=0; SMALL_AS=0; break; };
|
|
if (c == '1') { INTER_AS=1; MIGRATE=0; SMALL_AS=1; break; };
|
|
if (c == '2') { INTER_AS=0; MIGRATE=0; SMALL_AS=0; break; };
|
|
if (c == '3') { INTER_AS=0; MIGRATE=1; SMALL_AS=0; break; };
|
|
}
|
|
|
|
extern dword_t _end, _start;
|
|
for (ptr_t x = (&_start); x < &_end; x++)
|
|
{
|
|
dword_t q;
|
|
q = *(volatile dword_t*)x;
|
|
}
|
|
|
|
ping_tid = pong_tid = master_tid;
|
|
|
|
if (INTER_AS)
|
|
{
|
|
ping_tid.id.task += 1;
|
|
pong_tid.id.task += 2;
|
|
ping_tid.id.thread = 0;
|
|
pong_tid.id.thread = 0;
|
|
|
|
l4_task_new(pong_tid, 255,
|
|
(dword_t) &pong_stack[1024],
|
|
(dword_t) pong_thread, thepager);
|
|
|
|
l4_task_new(ping_tid, 255,
|
|
(dword_t) &ping_stack[1024],
|
|
(dword_t) ping_thread, thepager);
|
|
|
|
#ifdef PING_PONG_PRIO
|
|
l4_set_prio(ping_tid, PING_PONG_PRIO);
|
|
l4_set_prio(pong_tid, PING_PONG_PRIO);
|
|
#endif
|
|
|
|
if (SMALL_AS)
|
|
{
|
|
l4_set_small(ping_tid, l4_make_small_id(2, 0));
|
|
l4_set_small(pong_tid, l4_make_small_id(2, 1));
|
|
}
|
|
|
|
if (MIGRATE)
|
|
l4_migrate_thread(pong_tid, 1);
|
|
}
|
|
else
|
|
{
|
|
ping_tid.id.thread = 2;
|
|
pong_tid.id.thread = 3;
|
|
foo = get_current_pager(master_tid);
|
|
|
|
l4_thread_ex_regs(pong_tid,
|
|
(dword_t) pong_thread,
|
|
(dword_t) pong_stack + sizeof(pong_stack),
|
|
&foo, &foo, &dummy, &dummy, &dummy);
|
|
|
|
l4_thread_ex_regs(ping_tid,
|
|
(dword_t) ping_thread,
|
|
(dword_t) ping_stack + sizeof(ping_stack),
|
|
&foo, &foo, &dummy, &dummy, &dummy);
|
|
|
|
if (MIGRATE)
|
|
l4_migrate_thread(pong_tid, 1);
|
|
}
|
|
|
|
/* Wait for measurement to finish. */
|
|
l4_ipc_receive(ping_tid, 0,
|
|
&dummy, &dummy, &dummy,
|
|
L4_IPC_NEVER, &dope);
|
|
|
|
if (INTER_AS)
|
|
{
|
|
l4_task_new(ping_tid, 0, 0, 0, L4_NIL_ID);
|
|
l4_task_new(pong_tid, 0, 0, 0, L4_NIL_ID);
|
|
}
|
|
}
|
|
|
|
for (;;)
|
|
enter_kdebug("EOW");
|
|
}
|