2020-05-24 15:30:55 -05:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2022-01-31 16:59:14 -06:00
|
|
|
// Copyright (C) 2020-2022 Martin Whitaker.
|
2020-05-24 15:30:55 -05:00
|
|
|
//
|
|
|
|
// Derived from an extract of memtest86+ test.c:
|
|
|
|
//
|
|
|
|
// MemTest86+ V5 Specific code (GPL V2.0)
|
|
|
|
// By Samuel DEMEULEMEESTER, sdemeule@memtest.org
|
|
|
|
// http://www.canardpc.com - http://www.memtest.org
|
|
|
|
// Thanks to Passmark for calculate_chunk() and various comments !
|
|
|
|
// ----------------------------------------------------
|
|
|
|
// test.c - MemTest-86 Version 3.4
|
|
|
|
//
|
|
|
|
// Released under version 2 of the Gnu Public License.
|
|
|
|
// By Chris Brady
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "display.h"
|
|
|
|
#include "error.h"
|
|
|
|
#include "test.h"
|
|
|
|
|
|
|
|
#include "test_funcs.h"
|
|
|
|
#include "test_helper.h"
|
|
|
|
|
|
|
|
#define HAND_OPTIMISED 1 // Use hand-optimised assembler code for performance.
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Public Functions
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
2022-01-31 16:59:14 -06:00
|
|
|
int test_mov_inv_fixed(int my_cpu, int iterations, testword_t pattern1, testword_t pattern2)
|
2020-05-24 15:30:55 -05:00
|
|
|
{
|
|
|
|
int ticks = 0;
|
|
|
|
|
2022-01-31 16:59:14 -06:00
|
|
|
if (my_cpu == master_cpu) {
|
2020-05-24 15:30:55 -05:00
|
|
|
display_test_pattern_value(pattern1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize memory with the initial pattern.
|
|
|
|
for (int i = 0; i < vm_map_size; i++) {
|
|
|
|
testword_t *start, *end;
|
2022-01-31 16:59:14 -06:00
|
|
|
calculate_chunk(&start, &end, my_cpu, i, sizeof(testword_t));
|
2020-05-24 15:30:55 -05:00
|
|
|
|
2022-02-19 07:01:42 -06:00
|
|
|
testword_t *p = start;
|
|
|
|
testword_t *pe = start;
|
2020-05-24 15:30:55 -05:00
|
|
|
|
|
|
|
bool at_end = false;
|
|
|
|
do {
|
|
|
|
// take care to avoid pointer overflow
|
|
|
|
if ((end - pe) >= SPIN_SIZE) {
|
|
|
|
pe += SPIN_SIZE - 1;
|
|
|
|
} else {
|
|
|
|
at_end = true;
|
|
|
|
pe = end;
|
|
|
|
}
|
|
|
|
ticks++;
|
2022-01-31 16:59:14 -06:00
|
|
|
if (my_cpu < 0) {
|
2020-05-24 15:30:55 -05:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-31 16:59:14 -06:00
|
|
|
test_addr[my_cpu] = (uintptr_t)p;
|
2020-05-24 15:30:55 -05:00
|
|
|
#if HAND_OPTIMISED
|
|
|
|
#ifdef __x86_64__
|
|
|
|
uint64_t length = pe - p + 1;
|
|
|
|
__asm__ __volatile__ ("\t"
|
|
|
|
"rep \n\t"
|
|
|
|
"stosq \n\t"
|
|
|
|
:
|
|
|
|
: "c" (length), "D" (p), "a" (pattern1)
|
|
|
|
:
|
|
|
|
);
|
|
|
|
p = pe;
|
|
|
|
#else
|
|
|
|
uint32_t length = pe - p + 1;
|
|
|
|
__asm__ __volatile__ ("\t"
|
|
|
|
"rep \n\t"
|
|
|
|
"stosl \n\t"
|
|
|
|
:
|
|
|
|
: "c" (length), "D" (p), "a" (pattern1)
|
|
|
|
:
|
|
|
|
);
|
|
|
|
p = pe;
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
do {
|
2021-12-23 03:46:01 -06:00
|
|
|
write_word(p, pattern1);
|
2020-05-24 15:30:55 -05:00
|
|
|
} while (p++ < pe); // test before increment in case pointer overflows
|
|
|
|
#endif
|
2022-01-31 16:59:14 -06:00
|
|
|
do_tick(my_cpu);
|
2020-05-24 15:30:55 -05:00
|
|
|
BAILOUT;
|
|
|
|
} while (!at_end && ++pe); // advance pe to next start point
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for the current pattern and then write the alternate pattern for
|
|
|
|
// each memory location. Test from the bottom up and then from the top down.
|
|
|
|
for (int i = 0; i < iterations; i++) {
|
2022-01-31 16:59:14 -06:00
|
|
|
flush_caches(my_cpu);
|
2021-12-23 05:00:10 -06:00
|
|
|
|
2020-05-24 15:30:55 -05:00
|
|
|
for (int j = 0; j < vm_map_size; j++) {
|
|
|
|
testword_t *start, *end;
|
2022-01-31 16:59:14 -06:00
|
|
|
calculate_chunk(&start, &end, my_cpu, j, sizeof(testword_t));
|
2020-05-24 15:30:55 -05:00
|
|
|
|
2022-02-19 07:01:42 -06:00
|
|
|
testword_t *p = start;
|
|
|
|
testword_t *pe = start;
|
2020-05-24 15:30:55 -05:00
|
|
|
|
|
|
|
bool at_end = false;
|
|
|
|
do {
|
|
|
|
// take care to avoid pointer overflow
|
|
|
|
if ((end - pe) >= SPIN_SIZE) {
|
|
|
|
pe += SPIN_SIZE - 1;
|
|
|
|
} else {
|
|
|
|
at_end = true;
|
|
|
|
pe = end;
|
|
|
|
}
|
|
|
|
ticks++;
|
2022-01-31 16:59:14 -06:00
|
|
|
if (my_cpu < 0) {
|
2020-05-24 15:30:55 -05:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-31 16:59:14 -06:00
|
|
|
test_addr[my_cpu] = (uintptr_t)p;
|
2020-05-24 15:30:55 -05:00
|
|
|
do {
|
2021-12-23 03:46:01 -06:00
|
|
|
testword_t actual = read_word(p);
|
2020-05-24 15:30:55 -05:00
|
|
|
if (unlikely(actual != pattern1)) {
|
|
|
|
data_error(p, pattern1, actual, true);
|
|
|
|
}
|
2021-12-23 03:46:01 -06:00
|
|
|
write_word(p, pattern2);
|
2020-05-24 15:30:55 -05:00
|
|
|
} while (p++ < pe); // test before increment in case pointer overflows
|
2022-01-31 16:59:14 -06:00
|
|
|
do_tick(my_cpu);
|
2020-05-24 15:30:55 -05:00
|
|
|
BAILOUT;
|
|
|
|
} while (!at_end && ++pe); // advance pe to next start point
|
|
|
|
}
|
|
|
|
|
2022-01-31 16:59:14 -06:00
|
|
|
flush_caches(my_cpu);
|
2021-12-23 05:00:10 -06:00
|
|
|
|
2020-05-24 15:30:55 -05:00
|
|
|
for (int j = vm_map_size - 1; j >= 0; j--) {
|
|
|
|
testword_t *start, *end;
|
2022-01-31 16:59:14 -06:00
|
|
|
calculate_chunk(&start, &end, my_cpu, j, sizeof(testword_t));
|
2020-05-24 15:30:55 -05:00
|
|
|
|
2022-02-19 07:01:42 -06:00
|
|
|
testword_t *p = end;
|
|
|
|
testword_t *ps = end;
|
2020-05-24 15:30:55 -05:00
|
|
|
|
|
|
|
bool at_start = false;
|
|
|
|
do {
|
|
|
|
// take care to avoid pointer underflow
|
|
|
|
if ((ps - start) >= SPIN_SIZE) {
|
|
|
|
ps -= SPIN_SIZE - 1;
|
|
|
|
} else {
|
|
|
|
at_start = true;
|
|
|
|
ps = start;
|
|
|
|
}
|
|
|
|
ticks++;
|
2022-01-31 16:59:14 -06:00
|
|
|
if (my_cpu < 0) {
|
2020-05-24 15:30:55 -05:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-31 16:59:14 -06:00
|
|
|
test_addr[my_cpu] = (uintptr_t)p;
|
2020-05-24 15:30:55 -05:00
|
|
|
do {
|
2021-12-23 03:46:01 -06:00
|
|
|
testword_t actual = read_word(p);
|
2020-05-24 15:30:55 -05:00
|
|
|
if (unlikely(actual != pattern2)) {
|
|
|
|
data_error(p, pattern2, actual, true);
|
|
|
|
}
|
2021-12-23 03:46:01 -06:00
|
|
|
write_word(p, pattern1);
|
2020-05-24 15:30:55 -05:00
|
|
|
} while (p-- > ps); // test before decrement in case pointer overflows
|
2022-01-31 16:59:14 -06:00
|
|
|
do_tick(my_cpu);
|
2020-05-24 15:30:55 -05:00
|
|
|
BAILOUT;
|
|
|
|
} while (!at_start && --ps); // advance ps to next start point
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ticks;
|
|
|
|
}
|