memtest86plus/tests/own_addr.c
Martin Whitaker 16d55b7dad Remove distinction between physical and virtual CPUs.
This is no longer needed, now we can display as many CPUs as we can
physically handle.
2022-01-31 22:59:14 +00:00

151 lines
3.9 KiB
C

// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2022 Martin Whitaker.
//
// 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"
//------------------------------------------------------------------------------
// Private Functions
//------------------------------------------------------------------------------
static int pattern_fill(int my_cpu, testword_t offset)
{
int ticks = 0;
if (my_cpu == master_cpu) {
display_test_pattern_name("own address");
}
// Write each address with it's own address.
for (int i = 0; i < vm_map_size; i++) {
testword_t *start = vm_map[i].start;
testword_t *end = vm_map[i].end;
volatile testword_t *p = start;
volatile testword_t *pe = start;
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++;
if (my_cpu < 0) {
continue;
}
test_addr[my_cpu] = (uintptr_t)p;
do {
write_word(p, (testword_t)p + offset);
} while (p++ < pe); // test before increment in case pointer overflows
do_tick(my_cpu);
BAILOUT;
} while (!at_end && ++pe); // advance pe to next start point
}
flush_caches(my_cpu);
return ticks;
}
static int pattern_check(int my_cpu, testword_t offset)
{
int ticks = 0;
// Check each address has its own address.
for (int i = 0; i < vm_map_size; i++) {
testword_t *start = vm_map[i].start;
testword_t *end = vm_map[i].end;
volatile testword_t *p = start;
volatile testword_t *pe = start;
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++;
if (my_cpu < 0) {
continue;
}
test_addr[my_cpu] = (uintptr_t)p;
do {
testword_t expect = (testword_t)p + offset;
testword_t actual = read_word(p);
if (unlikely(actual != expect)) {
data_error(p, expect, actual, true);
}
} while (p++ < pe); // test before increment in case pointer overflows
do_tick(my_cpu);
BAILOUT;
} while (!at_end && ++pe); // advance pe to next start point
}
return ticks;
}
//------------------------------------------------------------------------------
// Public Functions
//------------------------------------------------------------------------------
int test_own_addr1(int my_cpu)
{
int ticks = 0;
ticks += pattern_fill(my_cpu, 0);
ticks += pattern_check(my_cpu, 0);
return ticks;
}
int test_own_addr2(int my_cpu, int stage)
{
static testword_t offset = 0;
static int last_stage = -1;
int ticks = 0;
offset = (stage == last_stage) ? offset + 1 : 1;
switch (stage) {
case 0:
ticks = pattern_fill(my_cpu, offset);
break;
case 1:
ticks = pattern_check(my_cpu, offset);
break;
default:
break;
}
last_stage = stage;
return ticks;
}