]> rtime.felk.cvut.cz Git - hercules2020/jailhouse-build.git/commitdiff
Rework memguard test
authorMichal Sojka <michal.sojka@cvut.cz>
Wed, 31 Oct 2018 23:57:31 +0000 (00:57 +0100)
committerMichal Sojka <michal.sojka@cvut.cz>
Wed, 31 Oct 2018 23:57:31 +0000 (00:57 +0100)
test/memguard-test.c

index 535aa44e1b4e7ca80287869e11677936cc1f910f..426e71bfc47e669d2f6b7fd23e256e30b17f0309 100644 (file)
@@ -10,6 +10,7 @@
 #include <time.h>
 #include <inttypes.h>
 #include <sys/mman.h>
+#include <stdbool.h>
 
 #ifndef SYS_prem_memguard_check
 #define SYS_prem_memguard_check 793
 #define MGRET_OVER_MEM_MASK    0x1lu
 #define MGRET_OVER_TIM_MASK    0x1lu
 
-#define RANDOM_ARRAY_SIZE 16777216 // 16M * 8 = 128 MB array
+char memory[128*10204*1024];
 
-uint64_t random_values[RANDOM_ARRAY_SIZE];
-
-
-enum prem_phase {
-       PREM_COMPATIBLE = 0,
-       PREM_MEMORY     = 1,
-       PREM_COMPUTE    = 2,
-};
-
-struct test_case{
-       uint64_t budget_time;
-       uint64_t budget_memory;
-       uint8_t flags;
-       uint64_t measured_time;
-       uint64_t measured_memory;
-       uint8_t status;
+struct mg_ret {
+       uint32_t time;
+       uint32_t mem;
+       bool time_ovf;
+       bool mem_ovf;
 };
 
-
-
-static inline void decode_retval(uint64_t retval, uint64_t * timval, uint64_t * cntval){
-       *timval = (retval >> MGRET_TIM_POS) & MGRET_TIM_MASK;
-       *cntval = (retval >> MGRET_MEM_POS) & MGRET_MEM_MASK;
+static struct mg_ret mgret(uint64_t retval)
+{
+       struct mg_ret mgr = {};
+       mgr.time = (retval >> MGRET_TIM_POS) & MGRET_TIM_MASK;
+       mgr.mem = (retval >> MGRET_MEM_POS) & MGRET_MEM_MASK;
+       mgr.time_ovf = (retval >> MGRET_OVER_TIM_POS) & 1;
+       mgr.mem_ovf = (retval >> MGRET_OVER_MEM_POS) & 1;
+       return mgr;
 }
 
-void compute_kernel(int time_ms){
-    struct timespec ts;
-    uint64_t current_us, end_us;
-    clock_gettime(CLOCK_MONOTONIC, &ts);
-    end_us = ts.tv_sec * 1000000 + ts.tv_nsec / 1000 + time_ms * 1000;
-    do {
+void compute_kernel(int time_us)
+{
+       struct timespec ts;
+       uint64_t current_us, end_us;
        clock_gettime(CLOCK_MONOTONIC, &ts);
-       current_us = ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
-    } while (current_us < end_us);
+       end_us = ts.tv_sec * 1000000 + ts.tv_nsec / 1000 + time_us;
+       do {
+               clock_gettime(CLOCK_MONOTONIC, &ts);
+               current_us = ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+       } while (current_us < end_us);
 }
 
-long memory_kernel(long lines){
-   uint64_t sum = 0;
-
-    for(int i = 0; i < lines; i++){
-        sum += random_values[(i*8) % RANDOM_ARRAY_SIZE];
-    }
-    return sum;
+void read_memory(long lines)
+{
+       uint64_t sum = 0;
+
+       for (uint64_t i = 0; i < lines; i++) {
+               sum += memory[(i * 64) % sizeof(memory)];
+       }
+       /* Do not optimize this function out */
+       volatile uint64_t x = sum;
+       (void)x;
 }
 
-void random_memory_kernel(long lines) {
-    uint32_t index;
-    uint64_t sum = 0;
+void write_memory(long lines)
+{
+       uint64_t *ptr;
+       for (uint64_t i = 0; i < lines; i++) {
+               ptr = (void*)&memory[(i * 64) % sizeof(memory)];
+               *ptr = i;
+       }
+}
 
-    for(long i=0; i<lines; i++) {
-        index = (uint32_t)rand();
-        index = index % RANDOM_ARRAY_SIZE;
-        sum += random_values[index];
-    }
+void read_memory_rnd(long lines)
+{
+       static unsigned rnd;
+       uint64_t sum = 0;
+
+       for (long i = 0; i < lines; i++) {
+               rnd = (rnd + 523) * 253573;
+               sum += memory[rnd % sizeof(memory)];
+       }
+       /* Do not optimize this function out */
+       volatile uint64_t x = sum;
+       (void)x;
 }
 
 /* Memguard flags */
-#define MGF_PERIODIC  (1 << 0) /* Chooses between periodic or one-shot budget replenishment */
-#define MGF_MASK_INT  (1 << 1) /* Mask (disable) low priority interrupts until next memguard call */
+#define MGF_PERIODIC                                                           \
+       (1 << 0) /* Chooses between periodic or one-shot budget replenishment */
+#define MGF_MASK_INT                                                           \
+       (1                                                                     \
+        << 1) /* Mask (disable) low priority interrupts until next memguard call */
+
+long prem_memguard_check(unsigned long timeout, unsigned long memory_budget,
+                        unsigned long flags)
+{
+       return syscall(SYS_prem_memguard_check, timeout, memory_budget, flags);
+}
 
-long prem_memguard_check(unsigned long timeout,
-                   unsigned long memory_budget,
-                   unsigned long flags)
+static void print_test_info(uint64_t timeout_us, uint64_t mem_budget, uint64_t flags,
+                           int64_t retval, const char *code)
 {
-    return syscall(SYS_prem_memguard_check, timeout, memory_budget, flags);
+       char call[80];
+       snprintf(call, sizeof(call), "memguard(%luus, %lumiss, %c%c):",
+                timeout_us, mem_budget,
+                flags & MGF_PERIODIC ? 'P' : '-',
+                flags & MGF_MASK_INT ? 'I' : '-'
+               );
+       struct mg_ret r = mgret(retval);
+       printf("%-40s %-25s ⇒ time:%8u%c mem:%8u%c\n",
+              call, code,
+              r.time, r.time_ovf ? '!' : ' ',
+              r.mem, r.mem_ovf ? '!' : ' ');
 }
 
-#define MGTEST(timeout_us, mem_budget, flags, code)                    \
-    do {                                                               \
-       long retval = prem_memguard_check(timeout_us, mem_budget, flags); \
-       code;                                                           \
-       retval = prem_memguard_check(0, 0, 0);                          \
-       printf("%-31s flags:%d m_ovr:%ld t_ovr:%ld mem:%d->%ld time:%d->%ld\n", \
-              #code, flags,                                            \
-              (retval >> MGRET_OVER_MEM_POS) & 1,                      \
-              (retval >> MGRET_OVER_TIM_POS) & 1,                      \
-              mem_budget, (retval >> MGRET_MEM_POS) & MGRET_MEM_MASK,  \
-              timeout_us, (retval >> MGRET_TIM_POS) & MGRET_TIM_MASK); \
-    } while (0)
+#define MGTEST(timeout_us, mem_budget, flags, code)                            \
+       ({                                                                     \
+               long retval;                                                   \
+               retval = prem_memguard_check(timeout_us, mem_budget, flags);   \
+               code;                                                          \
+               retval = prem_memguard_check(0, 0, 0);                         \
+               print_test_info(timeout_us, mem_budget, flags, retval, #code); \
+               mgret(retval);                                                 \
+       })
 
 int main(int argc, char *argv[])
 {
-    cpu_set_t set;
-    int cpu = 0;
-
-    char bla[1];
-
-    for (int i = 0; i < RANDOM_ARRAY_SIZE; i++)
-       random_values[i] = i;
-
-    if (argc > 1)
-       cpu = atoi(argv[1]);
-
-    /* Ensure that memory phase starts and ends on the same CPU */
-    CPU_ZERO(&set);
-    CPU_SET(cpu, &set);
-    if (sched_setaffinity(getpid(), sizeof(set), &set) < 0)
-       err(1, "sched_setaffinity");
-    printf("Pinned to CPU %d\n", cpu);
-
-    volatile long x;
-    MGTEST(100000, 1000, MGF_PERIODIC | MGF_MASK_INT, compute_kernel(1000));
-    MGTEST(1050000, 2136960000, 0,                   compute_kernel(1000));
-    MGTEST(100000, 500, MGF_PERIODIC, memory_kernel(100000000));
-
-    for (int i = 1; i <= 10; i++)
-       MGTEST(1000000, 500, 0, x=memory_kernel(1000000));
-
-    MGTEST(1000000, 500, 0, x=memory_kernel(100000000));
-    MGTEST(1000000, 100000, 0,                               random_memory_kernel(100000000));
-    MGTEST(1000000, 100000000, 0,                    random_memory_kernel(100000000));
-
-    return 0;
+       cpu_set_t set;
+       int cpu = 0;
+
+       for (int i = 0; i < sizeof(memory); i += 64)
+               memory[i] = 1;
+
+       if (argc > 1)
+               cpu = atoi(argv[1]);
+
+       /* Ensure that memory phase starts and ends on the same CPU */
+       CPU_ZERO(&set);
+       CPU_SET(cpu, &set);
+       if (sched_setaffinity(getpid(), sizeof(set), &set) < 0)
+               err(1, "sched_setaffinity");
+       printf("Pinned to CPU %d\n", cpu);
+
+       for (uint64_t flags = 0; flags < 4; flags++) {
+               compute_kernel(1); /* warm up */
+               MGTEST(5000, 10000, flags, compute_kernel(1000));
+               MGTEST(500, 10000, flags, compute_kernel(1000));
+               MGTEST(5000, 10000, flags, compute_kernel(2000));
+               MGTEST(500, 10000, flags, compute_kernel(2000));
+
+               MGTEST(100000, 500000, flags, read_memory(100000));
+               MGTEST(100000, 50000,  flags, read_memory(100000));
+               MGTEST(100000, 500000, flags, read_memory_rnd(100000));
+               MGTEST(100000, 50000,  flags, read_memory_rnd(100000));
+               MGTEST(100000, 500000, flags, write_memory(100000));
+               MGTEST(100000, 50000,  flags, write_memory(100000));
+
+               MGTEST(100000, 5000000, flags, read_memory(1000000));
+               MGTEST(100000, 500000,  flags, read_memory(1000000));
+               MGTEST(100000, 5000000, flags, read_memory_rnd(1000000));
+               MGTEST(100000, 500000,  flags, read_memory_rnd(1000000));
+               MGTEST(100000, 5000000, flags, write_memory(1000000));
+               MGTEST(100000, 500000,  flags, write_memory(1000000));
+
+               printf("\n");
+       }
+       return 0;
 }