feat(system): esp32p4: support panic tests

pull/13473/head
Alexey Lapshin 2024-01-19 11:51:57 +04:00
rodzic 13b55386bf
commit cb82161dae
8 zmienionych plików z 107 dodań i 31 usunięć

Wyświetl plik

@ -208,10 +208,8 @@ tools/test_apps/system/no_embedded_paths:
reason: the other targets are not tested yet
tools/test_apps/system/panic:
disable:
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: target(s) not supported yet # TODO: IDF-7511
enable:
- if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["esp32p4"] # preview targets
tools/test_apps/system/ram_loadable_app:
disable_test:

Wyświetl plik

@ -0,0 +1 @@
CONFIG_ESP_SYSTEM_HW_STACK_GUARD=n

Wyświetl plik

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
# Introduction

Wyświetl plik

@ -24,7 +24,12 @@ void test_int_wdt(void);
void test_task_wdt_cpu0(void);
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
void test_hw_stack_guard_cpu0(void);
#if !CONFIG_FREERTOS_UNICORE
void test_hw_stack_guard_cpu1(void);
#endif // CONFIG_FREERTOS_UNICORE
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
void test_panic_extram_stack(void);

Wyświetl plik

@ -31,9 +31,7 @@
static const char* get_test_name(void)
{
static char test_name_str[BOOT_CMD_MAX_LEN] = {0};
printf("Enter test name: ");
fflush(stdout);
bool print_prompt = true;
/* Not using blocking fgets(stdin) here, as QEMU doesn't yet implement RX timeout interrupt,
* which is required for the UART driver and blocking stdio to work.
@ -42,16 +40,24 @@ static const char* get_test_name(void)
char *p = test_name_str;
const char *end = test_name_str + sizeof(test_name_str) - 1;
while (p < end) {
if (print_prompt) {
printf("Enter test name: ");
fflush(stdout);
print_prompt = false;
}
c = getchar();
if (c == EOF) {
vTaskDelay(pdMS_TO_TICKS(10));
} else if ((c == '\r' || c == '\n') && p != test_name_str) {
} else if (c == '\r' || c == '\n') {
/* terminate the line */
puts("\n\r");
fflush(stdout);
*p = '\0';
break;
} else {
print_prompt = true;
if (p != test_name_str) {
*p = '\0';
break;
}
} else if (c >= '0' && c <= 'z') {
/* echo the received character */
putchar(c);
fflush(stdout);
@ -83,7 +89,12 @@ void app_main(void)
HANDLE_TEST(test_name, test_abort_cache_disabled);
HANDLE_TEST(test_name, test_int_wdt);
HANDLE_TEST(test_name, test_task_wdt_cpu0);
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
HANDLE_TEST(test_name, test_hw_stack_guard_cpu0);
#if !CONFIG_FREERTOS_UNICORE
HANDLE_TEST(test_name, test_hw_stack_guard_cpu1);
#endif // CONFIG_FREERTOS_UNICORE
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
HANDLE_TEST(test_name, test_panic_extram_stack);
#endif

Wyświetl plik

@ -63,6 +63,8 @@ void test_task_wdt_cpu0(void)
}
}
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
__attribute__((optimize("-O0")))
static void test_hw_stack_guard_cpu(void* arg)
{
@ -78,6 +80,18 @@ void test_hw_stack_guard_cpu0(void)
}
}
#if !CONFIG_FREERTOS_UNICORE
void test_hw_stack_guard_cpu1(void)
{
xTaskCreatePinnedToCore(test_hw_stack_guard_cpu, "HWSG1", 512, NULL, 1, NULL, 1);
while (true) {
vTaskDelay(100);
}
}
#endif // CONFIG_FREERTOS_UNICORE
#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
static void stack_in_extram(void* arg) {

Wyświetl plik

@ -17,7 +17,8 @@ TARGETS_TESTED = [
pytest.mark.esp32s3,
pytest.mark.esp32c2,
pytest.mark.esp32c6,
pytest.mark.esp32h2
pytest.mark.esp32h2,
pytest.mark.esp32p4,
]
# Most tests run on all targets and with all configs.
@ -34,7 +35,11 @@ CONFIGS = [
]
# Some tests only run on dual-core targets, they use the config below.
TARGETS_DUAL_CORE = [pytest.mark.esp32, pytest.mark.esp32s3]
TARGETS_DUAL_CORE = [
pytest.mark.esp32,
pytest.mark.esp32s3,
pytest.mark.esp32p4,
]
CONFIGS_DUAL_CORE = [
pytest.param('coredump_flash_bin_crc', marks=TARGETS_DUAL_CORE),
pytest.param('coredump_flash_elf_sha', marks=TARGETS_DUAL_CORE),
@ -58,6 +63,7 @@ TARGETS_HW_STACK_GUARD = [
pytest.mark.esp32c3,
pytest.mark.esp32c6,
pytest.mark.esp32h2,
pytest.mark.esp32p4,
]
CONFIGS_HW_STACK_GUARD = [
@ -68,6 +74,14 @@ CONFIGS_HW_STACK_GUARD = [
pytest.param('panic', marks=TARGETS_HW_STACK_GUARD),
]
CONFIGS_HW_STACK_GUARD_DUAL_CORE = [
pytest.param('coredump_flash_bin_crc', marks=[pytest.mark.esp32p4]),
pytest.param('coredump_uart_bin_crc', marks=[pytest.mark.esp32p4]),
pytest.param('coredump_uart_elf_crc', marks=[pytest.mark.esp32p4]),
pytest.param('gdbstub', marks=[pytest.mark.esp32p4]),
pytest.param('panic', marks=[pytest.mark.esp32p4]),
]
# Panic abort information will start with this string.
PANIC_ABORT_PREFIX = 'Panic reason: '
@ -148,15 +162,16 @@ def test_task_wdt_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> N
'Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:'
)
dut.expect_exact('CPU 1: Infinite loop')
expected_backtrace = ['infinite_loop', 'vPortTaskWrapper']
if dut.is_xtensa:
# see comment in test_task_wdt_cpu0
dut.expect_none('register dump:')
dut.expect_exact('Print CPU 1 backtrace')
dut.expect_backtrace()
# On Xtensa, we get incorrect backtrace from GDB in this test
expected_backtrace = ['infinite_loop', 'vPortTaskWrapper']
else:
assert False, 'No dual-core RISC-V chips yet, check this test case later'
# on RISC-V, need to dump both registers and stack memory to reconstruct the backtrace
dut.expect_reg_dump(core=1)
dut.expect_stack_dump()
dut.expect_elf_sha256()
dut.expect_none('Guru Meditation')
@ -204,9 +219,9 @@ def test_int_wdt(
dut.expect_stack_dump()
if target in TARGETS_DUAL_CORE_NAMES:
assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case'
dut.expect_reg_dump(1)
dut.expect_backtrace()
if dut.is_xtensa:
dut.expect_backtrace()
dut.expect_elf_sha256()
dut.expect_none('Guru Meditation')
@ -228,9 +243,9 @@ def test_int_wdt_cache_disabled(
dut.expect_stack_dump()
if target in TARGETS_DUAL_CORE_NAMES:
assert dut.is_xtensa, 'No dual-core RISC-V chips yet, check the test case'
dut.expect_reg_dump(1)
dut.expect_backtrace()
if dut.is_xtensa:
dut.expect_backtrace()
dut.expect_elf_sha256()
dut.expect_none('Guru Meditation')
@ -251,6 +266,8 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non
elif dut.target in ['esp32s2']:
# Cache error interrupt is not enabled, IDF-1558
dut.expect_gme('IllegalInstruction')
elif dut.target in ['esp32p4']: # TODO IDF-7515
dut.expect_gme('Instruction access fault')
else:
dut.expect_gme('Cache disabled but cached memory region accessed')
dut.expect_reg_dump(0)
@ -832,15 +849,36 @@ def test_gdbstub_coredump(dut: PanicTestDut) -> None:
return # don't expect "Rebooting" output below
def test_hw_stack_guard_cpu(dut: PanicTestDut, cpu: int) -> None:
dut.expect_exact(f'Guru Meditation Error: Core {cpu} panic\'ed (Stack protection fault).')
dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!')
dut.expect_exact(f'Detected in task "HWSG{cpu}"')
addr = dut.expect('at 0x([0-9a-fA-F]{8})')
assert addr.group(1) != b'00000000'
addr = dut.expect('Stack pointer: 0x([0-9a-fA-F]{8})')
assert addr.group(1) != b'00000000'
addr = dut.expect(r'Stack bounds: 0x([0-9a-fA-F]{8})')
assert addr.group(1) != b'00000000'
start_addr = int(addr.group(1), 16)
addr = dut.expect(r' - 0x([0-9a-fA-F]{8})')
assert addr.group(1) != b'00000000'
end_addr = int(addr.group(1), 16)
assert end_addr > start_addr
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD, indirect=True)
@pytest.mark.generic
def test_hw_stack_guard_cpu0(dut: PanicTestDut, config: str, test_func_name: str) -> None:
dut.run_test_func(test_func_name)
dut.expect_exact('Guru Meditation Error: Core 0 panic\'ed (Stack protection fault).')
dut.expect_none('ASSIST_DEBUG is not triggered BUT interrupt occured!')
dut.expect(r'Detected in task(.*)at 0x')
dut.expect_exact('Stack pointer: 0x')
dut.expect(r'Stack bounds: 0x(.*) - 0x')
test_hw_stack_guard_cpu(dut, 0)
common_test(dut, config)
@pytest.mark.parametrize('config', CONFIGS_HW_STACK_GUARD_DUAL_CORE, indirect=True)
@pytest.mark.generic
def test_hw_stack_guard_cpu1(dut: PanicTestDut, config: str, test_func_name: str) -> None:
dut.run_test_func(test_func_name)
test_hw_stack_guard_cpu(dut, 1)
common_test(dut, config)

Wyświetl plik

@ -1,14 +1,23 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import logging
import os
import re
import subprocess
import sys
from typing import Any, Dict, List, Optional, TextIO, Union
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import TextIO
from typing import Union
import pexpect
from panic_utils import NoGdbProcessError, attach_logger, quote_string, sha256, verify_valid_gdb_subprocess
from panic_utils import attach_logger
from panic_utils import NoGdbProcessError
from panic_utils import quote_string
from panic_utils import sha256
from panic_utils import verify_valid_gdb_subprocess
from pygdbmi.gdbcontroller import GdbController
from pytest_embedded_idf.app import IdfApp
from pytest_embedded_idf.dut import IdfDut
@ -53,7 +62,7 @@ class PanicTestDut(IdfDut):
@property
def is_multi_core(self) -> bool:
return self.target in ['esp32', 'esp32s3']
return self.target in ['esp32', 'esp32s3', 'esp32p4']
def run_test_func(self, test_func_name: str) -> None:
self.expect_exact('Enter test name:')