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