cachetest:Tools for testing cache and uncacheable
Summary: A tool is provided to test the case of data correctness after cache flush. It requires an uncacheable offset to check whether the uncacheable address is consistent with the data in the buffer after calling up_dcache_flush. Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
This commit is contained in:
parent
1d9f045068
commit
09ec04760f
29
testing/cachetest/Kconfig
Normal file
29
testing/cachetest/Kconfig
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config TESTING_CACHETEST
|
||||
tristate "Cache Test"
|
||||
default n
|
||||
---help---
|
||||
Enable a simple Cache test.
|
||||
|
||||
if TESTING_CACHETEST
|
||||
|
||||
config TESTING_CACHETEST_PROGNAME
|
||||
string "Program name"
|
||||
default "cachetest"
|
||||
---help---
|
||||
This is the name of the program that will be used when the NSH ELF
|
||||
program is installed.
|
||||
|
||||
config TESTING_CACHETEST_PRIORITY
|
||||
int "Cache test task priority"
|
||||
default 100
|
||||
|
||||
config TESTING_CACHETEST_STACKSIZE
|
||||
int "Cache test stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
|
||||
endif
|
23
testing/cachetest/Make.defs
Normal file
23
testing/cachetest/Make.defs
Normal file
@ -0,0 +1,23 @@
|
||||
############################################################################
|
||||
# apps/testing/cachetest/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_TESTING_CACHETEST),)
|
||||
CONFIGURED_APPS += $(APPDIR)/testing/cachetest
|
||||
endif
|
32
testing/cachetest/Makefile
Normal file
32
testing/cachetest/Makefile
Normal file
@ -0,0 +1,32 @@
|
||||
############################################################################
|
||||
# apps/testing/cachetest/Makefile
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# Cache test
|
||||
|
||||
PROGNAME = $(CONFIG_TESTING_CACHETEST_PROGNAME)
|
||||
PRIORITY = $(CONFIG_TESTING_CACHETEST_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_TESTING_CACHETEST_STACKSIZE)
|
||||
MODULE = $(CONFIG_TESTING_CACHETEST)
|
||||
|
||||
MAINSRC = cachetest_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
265
testing/cachetest/cachetest_main.c
Normal file
265
testing/cachetest/cachetest_main.c
Normal file
@ -0,0 +1,265 @@
|
||||
/****************************************************************************
|
||||
* apps/testing/cachetest/cachetest_main.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define CACHETEST_PREFIX "CACHE Test: "
|
||||
|
||||
#define OPTARG_TO_VALUE(value, type, base) \
|
||||
do \
|
||||
{ \
|
||||
FAR char *ptr; \
|
||||
value = (type)strtoul(optarg, &ptr, base); \
|
||||
if (*ptr != '\0') \
|
||||
{ \
|
||||
syslog(LOG_ERR, CACHETEST_PREFIX "Parameter error -%c %s\n", ch, \
|
||||
optarg); \
|
||||
cahcetest_show_usage(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct cachetest_s
|
||||
{
|
||||
FAR char *wbuf;
|
||||
FAR char *rbuf;
|
||||
FAR char *waddr;
|
||||
uintptr_t offset;
|
||||
size_t size;
|
||||
int repeat_num;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cahcetest_show_usage
|
||||
****************************************************************************/
|
||||
|
||||
static void cahcetest_show_usage(void)
|
||||
{
|
||||
printf("\nUsage: %s -s [buffer-size] -f [offset] -n [repeat-number]\n",
|
||||
CONFIG_TESTING_CACHETEST_PROGNAME);
|
||||
printf("\nWhere:\n");
|
||||
printf(" -s [buffer-size] number of memory alloc for buffer"
|
||||
"(in bytes). [Default Size: 1MB] \n");
|
||||
printf(" -f [offset] offset to uncacheble address [Default: 0]\n");
|
||||
printf(" -n [repeat-number] number of repetitions"
|
||||
" [default value: unlimited].\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cachetest_parse_commandline
|
||||
****************************************************************************/
|
||||
|
||||
static void cachetest_parse_commandline(int argc, FAR char **argv,
|
||||
FAR struct cachetest_s *info)
|
||||
{
|
||||
int ch;
|
||||
|
||||
/* Default size: 1M */
|
||||
|
||||
memset(info, 0, sizeof(struct cachetest_s));
|
||||
info->size = 1024 * 1024;
|
||||
|
||||
while ((ch = getopt(argc, argv, "s::n::f::i")) != ERROR)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 's':
|
||||
OPTARG_TO_VALUE(info->size, size_t, 10);
|
||||
break;
|
||||
case 'n':
|
||||
OPTARG_TO_VALUE(info->repeat_num, int, 10);
|
||||
break;
|
||||
case 'f':
|
||||
OPTARG_TO_VALUE(info->offset, uintptr_t, 16);
|
||||
break;
|
||||
case '?':
|
||||
cahcetest_show_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
info->wbuf = zalloc(info->size);
|
||||
if (info->wbuf == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, CACHETEST_PREFIX "Alloc memory for info->wbuf"
|
||||
"failed:%d\n",
|
||||
ENOMEM);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
info->rbuf = zalloc(info->size);
|
||||
if (info->rbuf == NULL)
|
||||
{
|
||||
free(info->wbuf);
|
||||
syslog(LOG_ERR, CACHETEST_PREFIX "Alloc memory for info->rbuf"
|
||||
"failed:%d\n",
|
||||
ENOMEM);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
info->waddr = zalloc(info->size);
|
||||
if (info->waddr == NULL)
|
||||
{
|
||||
free(info->wbuf);
|
||||
free(info->rbuf);
|
||||
syslog(LOG_ERR, CACHETEST_PREFIX "Alloc memory for info->waddr"
|
||||
"failed:%d\n",
|
||||
ENOMEM);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, CACHETEST_PREFIX "waddr:%p, uncacheble addr start:%p,"
|
||||
"size:%u\n", info->waddr,
|
||||
(FAR char *)((uintptr_t)info->waddr | info->offset), info->size);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cachetest_teardown
|
||||
****************************************************************************/
|
||||
|
||||
static void cachetest_teardown(FAR struct cachetest_s *info)
|
||||
{
|
||||
free(info->waddr);
|
||||
free(info->rbuf);
|
||||
free(info->wbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cachetest_randchar
|
||||
****************************************************************************/
|
||||
|
||||
static inline char cachetest_randchar(void)
|
||||
{
|
||||
int value = random() % 63;
|
||||
if (value == 0)
|
||||
{
|
||||
return '0';
|
||||
}
|
||||
else if (value <= 10)
|
||||
{
|
||||
return value + '0' - 1;
|
||||
}
|
||||
else if (value <= 36)
|
||||
{
|
||||
return value + 'a' - 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value + 'A' - 37;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cachetest_randcontext
|
||||
****************************************************************************/
|
||||
|
||||
static void cachetest_randcontext(uint32_t size, FAR void *input)
|
||||
{
|
||||
/* Construct a buffer here and fill it with random characters */
|
||||
|
||||
int i;
|
||||
FAR char *tmp;
|
||||
tmp = input;
|
||||
for (i = 0; i < size - 1; i++)
|
||||
{
|
||||
tmp[i] = cachetest_randchar();
|
||||
}
|
||||
|
||||
tmp[i] = '\0';
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cachetest_main
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR char *ptr;
|
||||
struct cachetest_s info;
|
||||
|
||||
/* Prepare parameters */
|
||||
|
||||
cachetest_parse_commandline(argc, argv, &info);
|
||||
|
||||
/* If there is no set number of times to repeat, it will loop continuously
|
||||
* by default.
|
||||
*/
|
||||
|
||||
for (int loop = 1; ((!info.repeat_num) || loop <= info.repeat_num);
|
||||
loop++)
|
||||
{
|
||||
cachetest_randcontext(info.size, info.wbuf);
|
||||
|
||||
/* Get uncacheable address */
|
||||
|
||||
ptr = (FAR char *)((uintptr_t)info.waddr | info.offset);
|
||||
|
||||
memcpy(info.waddr, info.wbuf, info.size);
|
||||
|
||||
up_flush_dcache((uintptr_t)info.waddr, (uintptr_t)info.waddr +
|
||||
info.size);
|
||||
|
||||
for (size_t i = 0; i < info.size; i++)
|
||||
{
|
||||
info.rbuf[i] = *ptr++;
|
||||
}
|
||||
|
||||
if (memcmp(info.wbuf, info.rbuf, info.size) != 0)
|
||||
{
|
||||
syslog(LOG_ERR, CACHETEST_PREFIX "comparison failed!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_INFO, CACHETEST_PREFIX "comparsion success!\n");
|
||||
}
|
||||
|
||||
/* To prevent tasks from being occupied all the time, switch
|
||||
* scheduling through usleep.
|
||||
*/
|
||||
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
cachetest_teardown(&info);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user