DF-5716 / p2_harness.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | /* * DF-5715 / DF-5716 / DF-5717 pass-2 differential harness (rig pattern: * DF-5714). Runs on the DragonFly guest as a plain userland binary. * * Compares the VERBATIM kernel bodies (k_ffsl / k_flsl / k_flsll, compiled * from the guest's own /usr/src/sys/libkern/{ffsl,flsl,flsll}.c with only * the kernel-only #include line stripped and the identifier renamed at the * preprocessor level, cksum-pinned in build.log) against: * * (1) the LIVE kernel inline implementations exactly as defined in * sys/cpu/x86_64/include/cpufunc.h (bsrl/bsrq asm copied verbatim * from cpufunc.h:110-126; ffsl :276-280 -> __builtin_ffsl; * flsl :292-296 -> bsrq+1; flsll :300-304 -> flsl((long)mask)), and * (2) builtin-clz references (64-__builtin_clz{,l,ll} for nonzero). * * Domains per function (structure-complete for this family: the output of * fls* depends only on the MSB position, that of ffs* only on the LSB * position; random words additionally cross-check everything else): * - 0, ~0, and the sign-only words (1<<63), all 64 single-bit words * - exhaustive over all values with bits confined to the low 22 positions * - exhaustive over all values with bits confined to the top 22 positions * - for every MSB position h in 0..63: 1024 random words with highest * set bit exactly h * - 50,000,000 uniform random 64-bit words (splitmix64, fixed seed) */ #include <stdio.h> #include <stdint.h> #include <inttypes.h> typedef unsigned int u_int; typedef unsigned long u_long; /* ---- verbatim kernel bodies, linked from k_*.o (renamed -Dffsl=k_ffsl ...) */ int k_ffsl(long mask); int k_flsl(long mask); int k_flsll(long long mask); /* ---- live inline bodies, copied VERBATIM from cpufunc.h ---- */ /* cpufunc.h:110-117 */ static __inline u_int live_bsrl(u_int mask) { u_int result; __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask)); return (result); } /* cpufunc.h:119-126 */ static __inline u_long live_bsrq(u_long mask) { u_long result; __asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask)); return (result); } /* cpufunc.h:276-280 (HAVE_INLINE_FFSL) */ static __inline int live_ffsl(long mask) { return (__builtin_ffsl(mask)); } /* cpufunc.h:292-296 (HAVE_INLINE_FLSL) */ static __inline int live_flsl(long mask) { return (mask == 0 ? mask : (int)live_bsrq((u_long)mask) + 1); } /* cpufunc.h:300-304 (HAVE_INLINE_FLSLL) */ static __inline int live_flsll(long long mask) { return (live_flsl((long)mask)); } /* ---- builtin-clz references ---- */ static int ref_ffsl(long v) { return (__builtin_ffsl(v)); } static int ref_flsl(long v) { return (v == 0 ? 0 : 64 - __builtin_clzl((unsigned long)v)); } static int ref_flsll(long long v) { return (v == 0 ? 0 : 64 - __builtin_clzll((unsigned long long)v)); } /* ---- volatile trampolines so nothing inlines/DCEs the out-of-line bodies ---- */ static int (*volatile pk_ffsl)(long) = k_ffsl; static int (*volatile pk_flsl)(long) = k_flsl; static int (*volatile pk_flsll)(long long) = k_flsll; /* splitmix64, fixed seed */ static uint64_t sm64_state = 0xDF5715000ULL; static uint64_t sm64(void) { uint64_t z = (sm64_state += 0x9E3779B97F4A7C15ULL); z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL; z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL; return (z ^ (z >> 31)); } static uint64_t cases, bad_vs_live_ffsl, bad_vs_ref_ffsl; static uint64_t bad_vs_live_flsl, bad_vs_ref_flsl; static uint64_t bad_vs_live_flsll, bad_vs_ref_flsll, bad_flsll_vs_flsl; static void chk(uint64_t v) { int a, b, c, d, e, f, g; cases++; /* ffsl family */ a = pk_ffsl((long)v); b = live_ffsl((long)v); c = ref_ffsl((long)v); if (a != b) bad_vs_live_ffsl++; if (a != c) bad_vs_ref_ffsl++; /* flsl family */ d = pk_flsl((long)v); e = live_flsl((long)v); f = ref_flsl((long)v); if (d != e) bad_vs_live_flsl++; if (d != f) bad_vs_ref_flsl++; /* flsll family (kernel body vs live inline vs clzll ref vs flsl twin) */ g = pk_flsll((long long)v); if (g != live_flsll((long long)v)) bad_vs_live_flsll++; if (g != ref_flsll((long long)v)) bad_vs_ref_flsll++; if (g != d) bad_flsll_vs_flsl++; } int main(void) { uint64_t v, x, h, i, n; /* hand-picked edges: 0, ~0, sign-only, single bits */ chk(0); chk(~(uint64_t)0); chk(1ULL << 63); for (h = 0; h < 64; h++) chk(1ULL << h); /* exhaustive: bits confined to low 22 positions (4,194,304 words) */ for (x = 0; x < (1ULL << 22); x++) chk(x); /* exhaustive: bits confined to top 22 positions (4,194,304 words) */ for (x = 0; x < (1ULL << 22); x++) chk(x << 42); /* structure-complete MSB sweep: every MSB position, random below it */ for (h = 0; h < 64; h++) for (i = 0; i < 1024; i++) { v = sm64(); if (h == 0) v = 0; else v = ((v & ((1ULL << h) - 1)) | (1ULL << h)); chk(v); } /* large uniform random sample */ n = 50000000ULL; for (i = 0; i < n; i++) chk(sm64()); printf("T1 ffsl : %10" PRIu64 " cases, %10" PRIu64 " mism vs live-inline, %10" PRIu64 " mism vs clz-ref\n", cases, bad_vs_live_ffsl, bad_vs_ref_ffsl); printf("T2 flsl : %10" PRIu64 " cases, %10" PRIu64 " mism vs live-inline, %10" PRIu64 " mism vs clz-ref\n", cases, bad_vs_live_flsl, bad_vs_ref_flsl); printf("T3 flsll: %10" PRIu64 " cases, %10" PRIu64 " mism vs live-inline, %10" PRIu64 " mism vs clz-ref," " %10" PRIu64 " mism vs kernel-flsl-twin\n", cases, bad_vs_live_flsll, bad_vs_ref_flsll, bad_flsll_vs_flsl); if (bad_vs_live_ffsl || bad_vs_ref_ffsl || bad_vs_live_flsl || bad_vs_ref_flsl || bad_vs_live_flsll || bad_vs_ref_flsll || bad_flsll_vs_flsl) { printf("HARNESS-FAIL: at least one kernel body diverges\n"); return (1); } printf("HARNESS-PASS: all three verbatim kernel bodies are output-" "identical to the live cpufunc.h inlines and clz references on " "every tested input\n"); return (0); } |