From 7b6a2424e08bc994c06ebfe65107ed296724f576 Mon Sep 17 00:00:00 2001 From: Pablo Reble Date: Tue, 8 Nov 2011 09:22:49 -0800 Subject: [PATCH 1/2] - implemented first draft of L2 flush --- apps/tests.c | 22 +++--- arch/x86/include/asm/page.h | 1 + arch/x86/include/asm/svm.h | 4 +- arch/x86/mm/svm.c | 129 ++++++++++++++++++++++++--------- include/metalsvm/tasks_types.h | 1 + 5 files changed, 114 insertions(+), 43 deletions(-) diff --git a/apps/tests.c b/apps/tests.c index 7774bc78..4fc876cb 100644 --- a/apps/tests.c +++ b/apps/tests.c @@ -17,6 +17,8 @@ * This file is part of MetalSVM. */ +//#define SVM_WB + #include #include #include @@ -137,6 +139,8 @@ static int svm_test(void *arg) int my_ue, num_ues; register int tmp; + kputs("Start SVM test...\n"); + RCCE_barrier(&RCCE_COMM_WORLD); my_ue = RCCE_ue(); num_ues = RCCE_num_ues(); @@ -214,7 +218,7 @@ static int svm_test(void *arg) } } - svm_flush(); + svm_flush(0); RCCE_barrier(&RCCE_COMM_WORLD); kputs("Start parallel calculation...\n"); @@ -236,7 +240,7 @@ static int svm_test(void *arg) } } - svm_flush(); + svm_flush(0); RCCE_barrier(&RCCE_COMM_WORLD); end = rdtsc(); @@ -318,21 +322,21 @@ int test_init(void) char* server_argv[] = {"/bin/server", "6789", NULL}; char* client_argv[] = {"/bin/client", "192.168.0.1", "6789", NULL}; - sem_init(&producing, 1); - sem_init(&consuming, 0); - mailbox_int32_init(&mbox); + //sem_init(&producing, 1); + //sem_init(&consuming, 0); + //mailbox_int32_init(&mbox); - create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO); - create_kernel_task(NULL, join_test, NULL, 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, producer, , NORMAL_PRIO); //create_kernel_task(NULL, consumer, 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_kernel_task(NULL, svm_test, NULL, NORMAL_PRIO); //create_kernel_task(NULL, pi, NULL, NORMAL_PRIO); //create_kernel_task(NULL, laplace, NULL, NORMAL_PRIO); //create_user_task(NULL, "/bin/hello", argv); - create_user_task(NULL, "/bin/tests", argv); + //create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/mshell", argv); //create_user_task(NULL, "/bin/jacobi", argv); diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 5d35ac53..349bca82 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -67,6 +67,7 @@ /// Pattern flag #define PG_PAT (1 << _PAGE_BIT_PAT) /// This virtual address range is used by SVM system as marked +#define PG_SVM PG_SVM_STRONG #define PG_SVM_STRONG (1 << _PAGE_BIT_SVM_STRONG) /// This virtual address range is used by SVM system as marked #define PG_SVM_LAZYRELEASE (1 << _PAGE_BIT_SVM_LAZYRELEASE) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 9e32616c..6638e1b6 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -31,6 +31,8 @@ extern "C" { #ifdef CONFIG_ROCKCREEK +#define SVM_WB + #define SVM_STRONG (1 << 0) #define SVM_LAZYRELEASE (1 << 1) #define SVM_L2 (1 << 4) @@ -91,7 +93,7 @@ static inline void svm_flush(void) *(int *)RCCE_fool_write_combine_buffer = 1; } #else -void svm_flush(void); +void svm_flush(size_t addr); #endif #endif diff --git a/arch/x86/mm/svm.c b/arch/x86/mm/svm.c index be3d8d77..b719fa39 100644 --- a/arch/x86/mm/svm.c +++ b/arch/x86/mm/svm.c @@ -40,7 +40,7 @@ t_vcharp RC_SHM_BUFFER_START(); /* - * Information to realize L2 flush + * Details on L2 cache (nedded for flushing) */ #define OWN_MPB 0xd8000000 @@ -69,36 +69,6 @@ __attribute__((always_inline)) static inline void svm_purge_set(const size_t set static size_t dummy_base = OWN_MPB + L2_CAPACITY; static size_t dummy_offset = 0; -/* - * Function to flush one page with L2 cache enabled! - */ - -void svm_flush_page(const size_t address) -{ - size_t line; - size_t dummy = dummy_base + dummy_offset; - size_t addr; - uint32_t flags; - - /* toggle between dummy areas */ - if(dummy_offset) - dummy_offset = 0; - else - dummy_offset = L2_CAPACITY; - - /* align the address to page boundaries */ - addr &= ~(PAGE_SIZE-1); - - /* disable iterrupts due to pseudo LRU behavior of L2 cache*/ - flags = irq_nested_disable(); - - /* for exact one page */ - for( line = 0; line < PAGE_SIZE; line += L2_LINESIZE ) - svm_purge_set( ( ( addr + line ) % L2_WBSTRIDE ) + dummy ); - - irq_nested_enable(flags); -} - /* * This array describes the owner of a specific page. * Only the owner of a page is able to change the possession. @@ -191,7 +161,9 @@ int svm_access_request(size_t addr) return change_page_permissions(addr, addr+PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE); } +#if 0 static atomic_int32_t size_counter = ATOMIC_INIT(0); +#endif void* svmmalloc(size_t size, uint32_t consistency) { @@ -347,7 +319,7 @@ int svm_emit_page(size_t phyaddr, int ue) } else { size_t viraddr; - svm_flush(); + svm_flush(phyaddr); page_owner[pageid] = ue; emit[ue]++; @@ -358,7 +330,7 @@ int svm_emit_page(size_t phyaddr, int ue) return 0; } -#ifdef SVM_WB +#if 0 void svm_flush(void) { int z, tmp; @@ -382,6 +354,97 @@ void svm_flush(void) } #endif +/* + * Function to flush one page or entire cache. + */ + +#ifdef SVM_WB +void svm_flush( size_t phyaddr ) +{ + task_t* task = per_core(current_task); + page_dir_t* pgd = task->pgd; + page_table_t* pgt = NULL; + + size_t step = 0; + size_t stride = L2_LINESIZE; + size_t range; + + size_t dummy; + + size_t viraddr; + + uint32_t index1, index2; + + uint32_t flags; + + /* flush entire Cache if phyaddr == 0 */ + if(!phyaddr) { + if( task->flags & TASK_L2 ){ + range = L2_WBSTRIDE; + goto flush_l2; + } else { + goto flush_l1; + } + /* flush one page */ + } else { + /* align the address to page boundaries */ + phyaddr &= ~(PAGE_SIZE-1); + + /* lookup pgt to check if L2 is enabled */ + viraddr = phys2virt[(phyaddr - shmbegin) >> PAGE_SHIFT]; + index1 = viraddr >> 22; + index2 = (viraddr >> 12) & 0x3FF; + + /* check if pgt is present */ + if (!pgd || !(pgd->entries[index1] & 0xFFFFF000)) + goto wrong_addr; + + pgt = (page_table_t*)((KERNEL_SPACE - 1024 * PAGE_SIZE + index1 * PAGE_SIZE) & 0xFFFFF000); + + if( pgt->entries[index2] & PG_MPE ) { + goto flush_l1; + } else { + range = PAGE_SIZE; + goto flush_l2; + } + } + + /* + * FLUSH L1 CACHE: + */ + +flush_l1: + + *(int *)RCCE_fool_write_combine_buffer = 1; + flush_cache(); + return; + +flush_l2: + /* + * FLUSH L2 CACHE: + * disable iterrupts due to pseudo LRU behavior of L2 cache + */ + + /* toggle between dummy areas */ + dummy = dummy_base + dummy_offset; + if(dummy_offset) + dummy_offset = 0; + else + dummy_offset = L2_CAPACITY; + + flags = irq_nested_disable(); + for( step = 0; step < range; step += stride ) + svm_purge_set( ( ( phyaddr + step ) % L2_WBSTRIDE ) + dummy ); + irq_nested_enable(flags); + return; + +wrong_addr: + kputs("svm flush error: address not valid!\n"); + return; + +} +#endif + int svm_statistics(void) { uint32_t i; diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index 857e9d52..938aa053 100644 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -59,6 +59,7 @@ extern "C" { #define TASK_FPU_INIT (1 << 0) #define TASK_FPU_USED (1 << 1) #define TASK_TIMER (1 << 2) +#define TASK_L2 (1 << 3) typedef int (*entry_point_t)(void*); typedef int (STDCALL *internal_entry_point_t)(void*); From 774388526a56944cb537148e2ded344e289b2964 Mon Sep 17 00:00:00 2001 From: Pablo Reble Date: Wed, 9 Nov 2011 07:48:16 -0800 Subject: [PATCH 2/2] - set correct task flag - cosmetical changes --- apps/tests.c | 11 +++++++---- arch/x86/mm/page.c | 2 +- arch/x86/mm/svm.c | 24 ++++++++++++++---------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/apps/tests.c b/apps/tests.c index 4fc876cb..628237c2 100644 --- a/apps/tests.c +++ b/apps/tests.c @@ -17,8 +17,6 @@ * This file is part of MetalSVM. */ -//#define SVM_WB - #include #include #include @@ -114,8 +112,9 @@ static int mail_noise(void*arg) { return 0; } -#define N 1024 -//#define N 514 +//#define N 1024 +//#define N 512 +#define N 128 #define LAZY #define L2_ENABLE @@ -193,9 +192,13 @@ static int svm_test(void *arg) #ifdef LAZY svm_flags = SVM_LAZYRELEASE; + kputs("Use Lazy Release consistency!\n"); +#else + kputs("Use Strong Release consistency!\n"); #endif #ifdef L2_ENABLE + kputs("Use Level 2 Cache!\n"); svm_flags |= SVM_L2; #endif diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 1e86cb53..76936314 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -784,7 +784,7 @@ int arch_paging_init(void) kprintf("Map configuration registers at 0x%x\n", viraddr); // map SCC's message passing buffers - viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_MPE); + viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+64*1024*1024) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_MPE); kprintf("Map message passing buffers at 0x%x\n", viraddr); // map the FPGA registers diff --git a/arch/x86/mm/svm.c b/arch/x86/mm/svm.c index b719fa39..7fa890b5 100644 --- a/arch/x86/mm/svm.c +++ b/arch/x86/mm/svm.c @@ -167,12 +167,15 @@ static atomic_int32_t size_counter = ATOMIC_INIT(0); void* svmmalloc(size_t size, uint32_t consistency) { + task_t* task = per_core(current_task); size_t phyaddr, viraddr, i; uint32_t flags; uint32_t map_flags = MAP_KERNEL_SPACE; if( !(consistency & SVM_L2) ) map_flags |= MAP_MPE; + else + task->flags |= TASK_L2; if (consistency & SVM_STRONG) map_flags |= MAP_SVM_STRONG; @@ -319,7 +322,8 @@ int svm_emit_page(size_t phyaddr, int ue) } else { size_t viraddr; - svm_flush(phyaddr); + svm_flush(0); + //svm_flush(phyaddr); page_owner[pageid] = ue; emit[ue]++; @@ -367,10 +371,8 @@ void svm_flush( size_t phyaddr ) size_t step = 0; size_t stride = L2_LINESIZE; - size_t range; + size_t range = L2_WBSTRIDE; - size_t dummy; - size_t viraddr; uint32_t index1, index2; @@ -380,7 +382,6 @@ void svm_flush( size_t phyaddr ) /* flush entire Cache if phyaddr == 0 */ if(!phyaddr) { if( task->flags & TASK_L2 ){ - range = L2_WBSTRIDE; goto flush_l2; } else { goto flush_l1; @@ -404,6 +405,7 @@ void svm_flush( size_t phyaddr ) if( pgt->entries[index2] & PG_MPE ) { goto flush_l1; } else { + phyaddr = phyaddr % L2_WBSTRIDE; range = PAGE_SIZE; goto flush_l2; } @@ -414,8 +416,9 @@ void svm_flush( size_t phyaddr ) */ flush_l1: - + kputs("flush L1\n"); *(int *)RCCE_fool_write_combine_buffer = 1; + //__asm__ volatile ( "wbinvd;\n\t" ); flush_cache(); return; @@ -424,17 +427,18 @@ flush_l2: * FLUSH L2 CACHE: * disable iterrupts due to pseudo LRU behavior of L2 cache */ - + flags = irq_nested_disable(); /* toggle between dummy areas */ - dummy = dummy_base + dummy_offset; + phyaddr += dummy_base + dummy_offset; + kprintf("flush-l2: phyaddr 0x%x\n", phyaddr); if(dummy_offset) dummy_offset = 0; else dummy_offset = L2_CAPACITY; - flags = irq_nested_disable(); + flush_cache(); for( step = 0; step < range; step += stride ) - svm_purge_set( ( ( phyaddr + step ) % L2_WBSTRIDE ) + dummy ); + svm_purge_set( phyaddr + step ); irq_nested_enable(flags); return;