Hi Daniel,
Have you noticed this on any platform yet with this test?
Regards, Amit
On Tue, Apr 8, 2014 at 4:05 PM, Daniel Lezcano daniel.lezcano@linaro.orgwrote:
As pointed by Lorenzo, when a cpu powers down, the L1 cache must be flushed before, otherwise:
- data cachelines are not empty and the other cpu may fetch data
- cpu will lost some data leading to a memory corruption
Note this bug is very difficult to reproduce and this test will not spot the issue everytime.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org
cpuidle/cpuidle-l1.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ cpuidle/cpuidle_05.sh | 42 ++++++++++++++++++++++++++++ cpuidle/cpuidle_05.txt | 1 + 3 files changed, 115 insertions(+) create mode 100644 cpuidle/cpuidle-l1.c create mode 100755 cpuidle/cpuidle_05.sh create mode 100644 cpuidle/cpuidle_05.txt
diff --git a/cpuidle/cpuidle-l1.c b/cpuidle/cpuidle-l1.c new file mode 100644 index 0000000..bbcde28 --- /dev/null +++ b/cpuidle/cpuidle-l1.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <pthread.h> +#define BUFSIZE (4*1024) +#define DEADBEEF 0xDEADBEEF +static int buffer[BUFSIZE];
+static pthread_t threads[64];
+void *thread_routine(void *arg) +{
int i, display = *(int *)arg;
int dummy;
for (i = 0; i < 100; i++) {
int j;
for (j = 0; j < BUFSIZE * 1000; j++) {
dummy = buffer[j % BUFSIZE];
dummy++;
}
usleep(200000);
if (buffer[i] != DEADBEEF) {
fprintf(stderr, "memory corruption\n");
return (void *)-1;
}
if (display == 0)
printf("%d%%%s", i, i < 10 ? "\b\b" : "\b\b\b");
}
if (display == 0)
printf(" \b\b\b\b");
return NULL;
+}
+int main(int argc, char *argv[]) +{
int i, ret = 0;
int nrcpus = sysconf(_SC_NPROCESSORS_ONLN);
for (i = 0; i < BUFSIZE; i++)
buffer[i] = DEADBEEF;
setbuf(stdout, NULL);
for(i = 0; i < nrcpus; i++) {
if (pthread_create(&threads[i], NULL, thread_routine, &i))
{
perror("pthread_create");
return 1;
}
}
for (i = 0; i < nrcpus; i++) {
void *result;
pthread_join(threads[i], &result);
if (result == (void *)-1)
ret = 1;
}
return ret;
+} diff --git a/cpuidle/cpuidle_05.sh b/cpuidle/cpuidle_05.sh new file mode 100755 index 0000000..679439d --- /dev/null +++ b/cpuidle/cpuidle_05.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# +# PM-QA validation test suite for the power management on Linux +# +# Copyright (C) 2011, Linaro Limited. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Contributors: +# Daniel Lezcano daniel.lezcano@linaro.org (IBM Corporation) +# - initial API and implementation +#
+# URL : https://wiki.linaro.org/WorkingGroups/PowerManagement/Resources/TestSuite/Pm...
+source ../include/functions.sh
+CPUIDLE_L1=./cpuidle-l1
+if [ $(id -u) -ne 0 ]; then
- log_skip "run as non-root"
- exit 0
+fi
+check_cpuidle_l1() {
- check "Fill L1 cache and sleep" "./$CPUIDLE_L1"
+}
+check_cpuidle_l1 +test_status_show diff --git a/cpuidle/cpuidle_05.txt b/cpuidle/cpuidle_05.txt new file mode 100644 index 0000000..1f80e36 --- /dev/null +++ b/cpuidle/cpuidle_05.txt @@ -0,0 +1 @@
+Run cpuidle L1 test program to catch L1 flush missing vs cpu power down
1.7.9.5