11/*
2- * MemForge2 v0.4.64 — UEFI memory tester written from scratch.
2+ * MemForge2 v0.4.65 — UEFI memory tester written from scratch.
33 *
44 * Latest release: https://github.com/Paradoxdov/memforge/releases
55 * For per-version changes see git log / GitHub Releases page.
@@ -891,7 +891,7 @@ static void init_splash(CHAR16 *stage) {
891891 cls();
892892 UINTN cy = g_h / 2;
893893 /* Title — large centered line. */
894- CHAR16 *title = L"MEMFORGE v0.4.64 ";
894+ CHAR16 *title = L"MEMFORGE v0.4.65 ";
895895 UINTN tx = (g_w - StrLen(title) * g_char_w) / 2;
896896 gfx_draw_str_color(tx, cy - g_char_h * 2, title, COL_ACCENT_HI);
897897 /* Stage indicator — what we're doing right now. */
@@ -1295,9 +1295,9 @@ static void render_header(UINT64 elapsed_ms, UINTN done, UINTN total) {
12951295 UINTN cols = g_text_cols;
12961296 if (cols >= 110) {
12971297 SPrint(buf, sizeof(buf),
1298- T(L" MEMFORGE v0.4.64 | %ld.%ld ГБ RAM | %s "
1298+ T(L" MEMFORGE v0.4.65 | %ld.%ld ГБ RAM | %s "
12991299 L"| %s | прошло %02d:%02d | осталось ~%02d:%02d | Тесты %d/%d",
1300- L" MEMFORGE v0.4.64 | %ld.%ld GB RAM | %s "
1300+ L" MEMFORGE v0.4.65 | %ld.%ld GB RAM | %s "
13011301 L"| %s | elapsed %02d:%02d | ETA ~%02d:%02d | Tests %d/%d"),
13021302 ram_gb_x10 / 10, ram_gb_x10 % 10,
13031303 pass_tag,
@@ -1307,25 +1307,25 @@ static void render_header(UINT64 elapsed_ms, UINTN done, UINTN total) {
13071307 (UINT32)done, (UINT32)total);
13081308 } else if (cols >= 90) {
13091309 SPrint(buf, sizeof(buf),
1310- T(L" MEMFORGE v0.4.64 | %ld.%ld ГБ RAM | %s | %s | прошло %02d:%02d | осталось ~%02d:%02d",
1311- L" MEMFORGE v0.4.64 | %ld.%ld GB RAM | %s | %s | elapsed %02d:%02d | ETA ~%02d:%02d"),
1310+ T(L" MEMFORGE v0.4.65 | %ld.%ld ГБ RAM | %s | %s | прошло %02d:%02d | осталось ~%02d:%02d",
1311+ L" MEMFORGE v0.4.65 | %ld.%ld GB RAM | %s | %s | elapsed %02d:%02d | ETA ~%02d:%02d"),
13121312 ram_gb_x10 / 10, ram_gb_x10 % 10,
13131313 pass_tag,
13141314 err_tag,
13151315 secs / 60, secs % 60,
13161316 eta_secs / 60, eta_secs % 60);
13171317 } else if (cols >= 70) {
13181318 SPrint(buf, sizeof(buf),
1319- T(L" MEMFORGE v0.4.64 | %ld.%ld ГБ RAM | %s | %s | прошло %02d:%02d",
1320- L" MEMFORGE v0.4.64 | %ld.%ld GB RAM | %s | %s | elapsed %02d:%02d"),
1319+ T(L" MEMFORGE v0.4.65 | %ld.%ld ГБ RAM | %s | %s | прошло %02d:%02d",
1320+ L" MEMFORGE v0.4.65 | %ld.%ld GB RAM | %s | %s | elapsed %02d:%02d"),
13211321 ram_gb_x10 / 10, ram_gb_x10 % 10,
13221322 pass_tag,
13231323 err_tag,
13241324 secs / 60, secs % 60);
13251325 } else {
13261326 SPrint(buf, sizeof(buf),
1327- T(L" MEMFORGE v0.4.64 | %s | %s | прошло %02d:%02d",
1328- L" MEMFORGE v0.4.64 | %s | %s | elapsed %02d:%02d"),
1327+ T(L" MEMFORGE v0.4.65 | %s | %s | прошло %02d:%02d",
1328+ L" MEMFORGE v0.4.65 | %s | %s | elapsed %02d:%02d"),
13291329 pass_tag,
13301330 err_tag,
13311331 secs / 60, secs % 60);
@@ -1679,7 +1679,7 @@ static volatile UINT32 g_dimm_err_count[MAX_DIMMS] = {0};
16791679 NOT "clean" — the attribution classifier must not treat it as separable. */
16801680static volatile UINT8 g_dimm_tested[MAX_DIMMS] = {0};
16811681
1682- /* v0.4.64 — interleave-aware attribution. The Path-B timing probe recovers AND
1682+ /* v0.4.65 — interleave-aware attribution. The Path-B timing probe recovers AND
16831683 confirms the Haswell DDR3 2ch/2DIMM address map; when valid we attribute an
16841684 error to the EXACT (channel,DIMM) = SPD slot, not the BIOS Type-20 range
16851685 (which is wrong under channel interleave). Validated on OptiPlex 9020:
@@ -1721,7 +1721,7 @@ static void record_error(kernel_id_t test, UINT32 core,
17211721 }
17221722 }
17231723 }
1724- /* v0.4.64 — interleave-aware tally (exact SPD slot), parallel to the
1724+ /* v0.4.65 — interleave-aware tally (exact SPD slot), parallel to the
17251725 Type-20 one above. Only when the probe confirmed the address map. */
17261726 if (g_intl_valid) {
17271727 int sl = addr_to_intl_slot(addr);
@@ -3109,15 +3109,15 @@ static void run_butterfly(ap_arg_t *a) {
31093109 variant runs 30 sec of FMA chain (~10× longer) WITH interleaved memory
31103110 writes, so the test hits VRM + IMC simultaneously. This is the closest
31113111 pre-OS analogue to Prime95 Small FFT thermal stress. */
3112- /* v0.4.64 — DIAG: immediate post-fill check for the AVX2 Sustained kernel (the
3112+ /* v0.4.65 — DIAG: immediate post-fill check for the AVX2 Sustained kernel (the
31133113 one that actually reports the byte-1 errors — earlier diag was wrongly placed
31143114 in run_avx2). Localizes WHEN byte 1 goes wrong: at the AVX2 store itself, or
31153115 during the FMA/verify window after it. */
31163116static volatile UINT64 g_avx_imm_mismatch = 0;
31173117static volatile int g_avx_imm_have_sample = 0;
31183118static UINT64 g_avx_imm_addr = 0, g_avx_imm_exp = 0, g_avx_imm_act = 0;
3119- static UINT64 g_avx_imm_flush = 0; /* v0.4.64 — DRAM re-read of the first post-store mismatch */
3120- static volatile UINT64 g_avx_scalar_mismatch = 0; /* v0.4.64 — scalar-fill control */
3119+ static UINT64 g_avx_imm_flush = 0; /* v0.4.65 — DRAM re-read of the first post-store mismatch */
3120+ static volatile UINT64 g_avx_scalar_mismatch = 0; /* v0.4.65 — scalar-fill control */
31213121
31223122static void run_avx2_sustained(ap_arg_t *a) {
31233123 if (!g_has_avx2) {
@@ -3164,7 +3164,7 @@ static void run_avx2_sustained(ap_arg_t *a) {
31643164 : "ymm0", "memory", "cc");
31653165 a->bytes += (UINT64)n * 8;
31663166
3167- /* v0.4.64 — DIAG: verify the fill IMMEDIATELY, before the FMA burst,
3167+ /* v0.4.65 — DIAG: verify the fill IMMEDIATELY, before the FMA burst,
31683168 on the first iteration only. Mismatch HERE = the AVX2 256-bit store
31693169 itself wrote wrong byte 1; clean here but dirty at the post-FMA
31703170 verify = it goes wrong during the FMA/verify window. */
@@ -3185,7 +3185,7 @@ static void run_avx2_sustained(ap_arg_t *a) {
31853185 g_avx_imm_have_sample = 1;
31863186 }
31873187 }
3188- /* v0.4.64 — CONTROL: same buffer, PLAIN scalar 64-bit stores, then
3188+ /* v0.4.65 — CONTROL: same buffer, PLAIN scalar 64-bit stores, then
31893189 immediate re-verify. AVX2 dirty + scalar clean => the 256-bit
31903190 store path is at fault, not the DRAM cells. */
31913191 for (UINTN iv = 0; iv < n; iv++) a->base[iv] = pat[iv & 3];
@@ -5701,7 +5701,7 @@ static void timing_probe_calibrate(void) {
57015701 uefi_call_wrapper(BS->FreePages, 2, addr, pages);
57025702}
57035703
5704- /* v0.4.64 — Path B step-2: recover DRAM addressing functions from the row-
5704+ /* v0.4.65 — Path B step-2: recover DRAM addressing functions from the row-
57055705 conflict timing channel (DRAMA solver). Groups random addresses into
57065706 "same-bank" sets (mutual row conflict), then brute-forces linear XOR
57075707 functions of address bits that are CONSTANT within every set but VARY across
@@ -5710,7 +5710,7 @@ static void timing_probe_calibrate(void) {
57105710 (which fn = DIMM) come next, anchored by a7=channel + the physical layout. */
57115711#define FN_POOL 512
57125712#define FN_BIT_LO 6
5713- #define FN_BIT_HI 34 /* v0.4.64 — up to a34: block/channel select on a 16 GB box is a32/a33 */
5713+ #define FN_BIT_HI 34 /* v0.4.65 — up to a34: block/channel select on a 16 GB box is a32/a33 */
57145714static UINT64 g_fn_pool[FN_POOL];
57155715static UINT8 g_fn_setid[FN_POOL];
57165716static int g_fn_nsets = 0;
@@ -5732,7 +5732,7 @@ static int fn_is_addr_func(UINT64 m) {
57325732static void timing_probe_recover(void) {
57335733 CHAR16 lb[200];
57345734 if (!g_has_clflush) { log_line(L"[FUNC] no CLFLUSH — skipped"); return; }
5735- /* v0.4.64 — sample across ALL physical RAM (every 4 GB block), not one low
5735+ /* v0.4.65 — sample across ALL physical RAM (every 4 GB block), not one low
57365736 512 MB buffer, so the channel/DIMM-select functions (block boundaries
57375737 a32/a33 on a 16 GB box) become visible — not just intra-DIMM bank bits.
57385738 Read-only: clflush + load timing on free conventional memory. */
@@ -5815,7 +5815,7 @@ static void timing_probe_recover(void) {
58155815 SPrint(lb, sizeof(lb), L"[FUNC] fn: a%d ^ a%d", a, b); log_line(lb); found++;
58165816 }
58175817 if (!found) log_line(L"[FUNC] no constant XOR funcs (1-2 bit) — sets noisy / threshold off");
5818- /* v0.4.64 — test DRAMA Table-2a Haswell DDR3 candidates + block hypotheses
5818+ /* v0.4.65 — test DRAMA Table-2a Haswell DDR3 candidates + block hypotheses
58195819 EXPLICITLY (the channel hash is a 7-bit XOR, invisible to 1-2 bit brute). */
58205820 struct { UINT64 m; const CHAR16 *nm; } cand[] = {
58215821 { (1ULL<<7)|(1ULL<<8)|(1ULL<<9)|(1ULL<<12)|(1ULL<<13)|(1ULL<<18)|(1ULL<<19), L"channel(intl 7b)" },
@@ -5829,17 +5829,31 @@ static void timing_probe_recover(void) {
58295829 fn_is_addr_func(cand[ci].m) ? (CHAR8*)"YES" : (CHAR8*)"no");
58305830 log_line(lb);
58315831 }
5832- /* v0.4.64 — if the published Haswell channel hash AND the a16 DIMM bit both
5833- check out on THIS board, lock them in as the attribution map. */
5834- UINT64 chmask = (1ULL<<7)|(1ULL<<8)|(1ULL<<9)|(1ULL<<12)|(1ULL<<13)|(1ULL<<18)|(1ULL<<19);
5835- if (fn_is_addr_func(chmask) && fn_is_addr_func(1ULL<<16)) {
5836- g_intl_chan_mask = chmask;
5837- g_intl_dimm_bit = 16;
5838- g_intl_valid = 1;
5839- log_line(L"[FUNC] interleave map CONFIRMED -> attribution by (channel,DIMM)=SPD slot");
5840- } else {
5841- log_line(L"[FUNC] interleave map NOT confirmed -> falling back to Type-20 ranges");
5832+ /* v0.4.65 — multi-platform address-map table. Each row is a published
5833+ (channel-hash, DIMM-in-channel-bit) pair; we accept the FIRST row whose
5834+ BOTH functions actually check out on THIS board (fn_is_addr_func tests
5835+ them against the live timing groups). A row that doesn't fit the silicon
5836+ simply won't confirm — so wrong rows never mis-attribute, they're just
5837+ skipped. Add new rows (Skylake/DDR4, AMD, …) once validated on that HW. */
5838+ static const struct { const CHAR16 *nm; UINT64 ch; int dbit; } g_addr_maps[] = {
5839+ { L"Intel DDR3 2ch/2DIMM (IvyBridge/Haswell)",
5840+ (1ULL<<7)|(1ULL<<8)|(1ULL<<9)|(1ULL<<12)|(1ULL<<13)|(1ULL<<18)|(1ULL<<19), 16 },
5841+ { L"Intel DDR3 2ch (SandyBridge)", (1ULL<<6), 16 },
5842+ };
5843+ g_intl_valid = 0;
5844+ for (UINTN mi = 0; mi < sizeof(g_addr_maps)/sizeof(g_addr_maps[0]); mi++) {
5845+ if (fn_is_addr_func(g_addr_maps[mi].ch) &&
5846+ fn_is_addr_func(1ULL << g_addr_maps[mi].dbit)) {
5847+ g_intl_chan_mask = g_addr_maps[mi].ch;
5848+ g_intl_dimm_bit = g_addr_maps[mi].dbit;
5849+ g_intl_valid = 1;
5850+ SPrint(lb, sizeof(lb), L"[FUNC] address map CONFIRMED: %s -> attribution by SPD slot", g_addr_maps[mi].nm);
5851+ log_line(lb);
5852+ break;
5853+ }
58425854 }
5855+ if (!g_intl_valid)
5856+ log_line(L"[FUNC] no known address map fits this platform -> Type-20 fallback");
58435857 for (int s = 0; s < 4 && s < g_fn_nsets; s++) {
58445858 UINT64 amn = ~0ULL, amx = 0; int cnt = 0;
58455859 for (int k = 0; k < FN_POOL; k++) if (g_fn_setid[k] == s) {
@@ -9369,7 +9383,7 @@ static void render_simple_verdict(UINT64 total_ms) {
93699383 }
93709384 } else { /* VERDICT_FAIL */
93719385 int didx = dominant_dimm_idx();
9372- /* v0.4.64 — confirmed interleave map is AUTHORITATIVE: override the
9386+ /* v0.4.65 — confirmed interleave map is AUTHORITATIVE: override the
93739387 Type-20 guess with the exact (channel,DIMM)=SPD-slot attribution. */
93749388 if (g_intl_valid && g_dimm_count >= 4) {
93759389 UINT32 bn = 0; int bs = -1;
@@ -9706,8 +9720,8 @@ static void render_summary(UINT64 total_ms) {
97069720 UINTN hrow = (g_hdr_h / 2 - g_char_h / 2) / g_char_h;
97079721 CHAR16 buf[200];
97089722 SPrint(buf, sizeof(buf),
9709- T(L" MEMFORGE v0.4.64 ИТОГИ | %d сек | Ядра %d/%d",
9710- L" MEMFORGE v0.4.64 SUMMARY | %d sec | Cores %d/%d"),
9723+ T(L" MEMFORGE v0.4.65 ИТОГИ | %d сек | Ядра %d/%d",
9724+ L" MEMFORGE v0.4.65 SUMMARY | %d sec | Cores %d/%d"),
97119725 (UINT32)(total_ms / 1000),
97129726 (UINT32)g_n_enabled, (UINT32)g_n_cores);
97139727 say_at_rc(0, hrow, buf);
@@ -10231,7 +10245,7 @@ static void build_run_basename(CHAR16 *out, UINTN cap_chars) {
1023110245 UINT32 run_seq = g_hist_prev_valid ? (g_hist_prev.run_seq + 1) : 1;
1023210246 int di = (g_run_total_errors > 0) ? dominant_dimm_idx() : -1;
1023310247 if (di < 0 && g_dimm_count == 1) di = 0;
10234- /* v0.4.64 — prefer the confirmed interleave attribution (exact SPD slot),
10248+ /* v0.4.65 — prefer the confirmed interleave attribution (exact SPD slot),
1023510249 same as the on-screen verdict, so the filename names the RIGHT stick. */
1023610250 if (g_intl_valid && g_dimm_count >= 4 && g_run_total_errors > 0) {
1023710251 UINT32 bn = 0; int bs = -1;
@@ -11855,7 +11869,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
1185511869 }
1185611870 }
1185711871
11858- log_line(L"=== MemForge2 v0.4.64 init ===");
11872+ log_line(L"=== MemForge2 v0.4.65 init ===");
1185911873 log_line(L"[WATCHDOG] UEFI 5-min watchdog disabled at app entry");
1186011874 flush_early_log(); /* v0.4.52 — emit lines buffered before the log opened */
1186111875 /* Show splash IMMEDIATELY so the user sees the program is alive while
@@ -11982,7 +11996,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
1198211996 address->slot decode; for now logs MAD topology + cross-checks SMBIOS. */
1198311997 imc_dump();
1198411998 timing_probe_calibrate(); /* v0.4.54 — Path B step-1: validate row-conflict timing channel */
11985- timing_probe_recover(); /* v0.4.64 — Path B step-2: recover DRAM addressing functions */
11999+ timing_probe_recover(); /* v0.4.65 — Path B step-2: recover DRAM addressing functions */
1198612000 /* Once total RAM is known: scale buffer-chunk size for big-RAM systems
1198712001 so the pass count stays reasonable. Skipped if user pinned BufferMB
1198812002 in quantai.ini. */
@@ -12299,7 +12313,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
1229912313 g_pass_durations_count = 0;
1230012314 g_core_stall_count = 0; /* v0.4.47 — clear stall tally for fresh run */
1230112315 g_err_count = 0; /* v0.4.47 — fresh error tally each run */
12302- g_avx_imm_mismatch = 0; g_avx_imm_have_sample = 0; /* v0.4.64 diag */
12316+ g_avx_imm_mismatch = 0; g_avx_imm_have_sample = 0; /* v0.4.65 diag */
1230312317 for (UINTN d = 0; d < MAX_DIMMS; d++) g_dimm_err_count[d] = 0;
1230412318 for (UINTN d = 0; d < MAX_DIMMS; d++) g_dimm_tested[d] = 0; /* v0.4.47 — fresh per-run */
1230512319 for (UINTN i = 0; i < g_n_enabled; i++) {
@@ -12723,7 +12737,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
1272312737 L"corruption appears AFTER the fill (FMA/verify window)");
1272412738 log_line(db);
1272512739 }
12726- /* v0.4.64 — interleave-aware verdict: name the bad stick by SERIAL
12740+ /* v0.4.65 — interleave-aware verdict: name the bad stick by SERIAL
1272712741 via the confirmed (channel,DIMM) map, not the wrong Type-20 range. */
1272812742 if (g_intl_valid && g_dimm_count >= 4) {
1272912743 int bs = -1; UINT32 bn = 0;
0 commit comments