From 62e7ead997b4bcbd9bafe212ea08a12e80999447 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 15 Aug 2011 07:16:12 -0700 Subject: [PATCH] add SVM demo example and redesign of the SVM system --- arch/x86/include/asm/svm.h | 6 ++- arch/x86/mm/page.c | 7 ++++ arch/x86/mm/svm.c | 52 ++++++++++++++++++++++--- include/metalsvm/stdlib.h | 3 ++ kernel/tests.c | 80 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 138 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 090d1072..6c1e2d61 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -26,6 +26,8 @@ extern "C" { #endif +#ifdef CONFIG_ROCKCREEK + /** @brief Memory allocator of the SVM subsystem. * * Like RCCE function, belongs svmmalloc to the synchronous @@ -39,7 +41,9 @@ void* svmmalloc(size_t size); * * Like RCCE function, belongs svmfree to the synchronous function. */ -void svmfree(void* addr); +void svmfree(void* addr, size_t size); + +#endif #ifdef __cplusplus } diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index 6eadd3d1..353f0626 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -354,6 +354,10 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag if (flags & MAP_MPE) pgt->entries[index] |= PG_MPE; #endif + if (flags & MAP_SVM) + pgt->entries[index] |= PG_SVM; + if (flags & MAP_NO_ACCESS) + pgt->entries[index] &= ~(PG_PRESENT|PG_RW); if (flags & MAP_USER_SPACE) atomic_int32_inc(&task->user_usage); @@ -395,6 +399,9 @@ int change_page_permissions(size_t start, size_t end, uint32_t flags) phyaddr = pgt->entries[index2] & 0xFFFFF000; newflags = pgt->entries[index2] & 0xFFF; // get old flags + if ((newflags & PG_SVM) && !(newflags & PG_PRESENT) && (flags & (VMA_WRITE|VMA_READ))) + newflags |= PG_PRESENT; + // update flags if (!(flags & VMA_WRITE)) newflags &= ~PG_RW; diff --git a/arch/x86/mm/svm.c b/arch/x86/mm/svm.c index 06e4d3d4..2fecbba7 100644 --- a/arch/x86/mm/svm.c +++ b/arch/x86/mm/svm.c @@ -20,19 +20,61 @@ #include #include #include -#include +#include +#include +#include #ifdef CONFIG_ROCKCREEK #include #include #include -#endif +#include void* svmmalloc(size_t size) { - return (void*) RCCE_shmalloc(size); + size_t phyaddr; + size_t viraddr; + uint32_t flags; + uint32_t map_flags = MAP_KERNEL_SPACE|MAP_MPE|MAP_SVM; + + // currently, we allocate memory in page size granulation + size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + phyaddr = (size_t) RCCE_shmalloc(size); + + if (RCCE_ue()) + map_flags |= MAP_NO_ACCESS; + irq_nested_enable(flags); + + viraddr = map_region(0, phyaddr, size >> PAGE_SHIFT, map_flags); + + //kprintf("shmmalloc: phyaddr 0x%x, viraddr 0x%x, size 0x%x\n", phyaddr, viraddr, size); + + return (void*) viraddr; } -void svmfree(void* addr) +void svmfree(void* addr, size_t size) { - RCCE_free((t_vcharp) addr); + size_t phyaddr; + uint32_t flags; + + if (BUILTIN_EXPECT(!addr || !size, 0)) + return; + + phyaddr = virt_to_phys((size_t) addr); + + // currently, we allocate memory in page size granulation + size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + //kprintf("shmmalloc: phyaddr 0x%x, viraddr 0x%x, size 0x%x\n", phyaddr, addr, size); + + unmap_region((size_t) addr, size >> PAGE_SHIFT); + + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + RCCE_shfree((t_vcharp) phyaddr); + irq_nested_enable(flags); } + +#endif diff --git a/include/metalsvm/stdlib.h b/include/metalsvm/stdlib.h index ad1cecdb..3849745e 100644 --- a/include/metalsvm/stdlib.h +++ b/include/metalsvm/stdlib.h @@ -48,6 +48,9 @@ extern "C" { #ifdef CONFIG_ROCKCREEK #define MAP_MPE (1 << 8) #endif +#define MAP_SVM (1 << 9) +#define MAP_NO_ACCESS (1 << 10) + void NORETURN abort(void); /** @brief Kernel's memory allocator function. diff --git a/kernel/tests.c b/kernel/tests.c index 5b67a06d..a5113c09 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -24,12 +24,14 @@ #include #include #include +#include #ifdef CONFIG_ROCKCREEK #include #include #include #include #include +#include #include #include @@ -111,6 +113,75 @@ int mail_ping(void* arg) { return 0; } + +static inline void cache_invalidate(void) +{ + asm volatile ( ".byte 0x0f; .byte 0x0a;\n" ); // CL1FLUSHMB +} + +#define N 1024 + +volatile static int* A[N]; +volatile static int* B[N]; +volatile static int* C[N]; + +static int svm_test(void *arg) +{ + uint32_t i, j, k, flags; + int my_ue, num_ues; + + // iRCCE is not thread save => disable interrupts + flags = irq_nested_disable(); + RCCE_barrier(&RCCE_COMM_WORLD); + my_ue = RCCE_ue(); + num_ues = RCCE_num_ues(); + irq_nested_enable(flags); + + // allocate and initialize SVM region + A[0] = (int*) svmmalloc(3*N*N*sizeof(int)); + if (!my_ue) + memset((void*) A[0], 0x00, 3*N*N*sizeof(int)); + + // initialize matrices + for(i=0; i disable interrupts + flags = irq_nested_disable(); + RCCE_barrier(&RCCE_COMM_WORLD); + irq_nested_enable(flags); + + // start calculation + for(i=my_ue*(N/num_ues); i<(my_ue+1)*(N/num_ues); i++) + for(j=0; j disable interrupts + flags = irq_nested_disable(); + RCCE_barrier(&RCCE_COMM_WORLD); + irq_nested_enable(flags); + + svmfree(A[0], 3*N*sizeof(int)); + + return 0; +} #endif static int join_test(void* arg) @@ -273,16 +344,17 @@ int test_init(void) // create_kernel_task(NULL,client_task,NULL); #endif - create_kernel_task(NULL, foo, "Hello from foo1"); - create_kernel_task(NULL, join_test, NULL); + //create_kernel_task(NULL, foo, "Hello from foo1"); + //create_kernel_task(NULL, join_test, NULL); //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_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/jacobi", argv); - create_user_task(NULL, "/bin/server", server_argv); + //create_user_task(NULL, "/bin/server", server_argv); //sleep(5); //create_user_task(NULL, "/bin/client", client_argv);