From 149c341ec639d7599e05687d68d3b8b43c3cb8e3 Mon Sep 17 00:00:00 2001 From: Akhilesh Kumar Upadhyay Date: Wed, 30 Aug 2017 00:49:10 +0530 Subject: [PATCH] tests: kernel: x86 : App to validate x86 specific boot time page table Testcase developed to validate x86 specific boot time page table faults. Signed-off-by: Akhilesh Kumar Upadhyay --- tests/kernel/boot_page_table/CMakeLists.txt | 5 + tests/kernel/boot_page_table/README.txt | 44 ++++++ tests/kernel/boot_page_table/prj.conf | 1 + .../boot_page_table/src/boot_page_table.c | 146 ++++++++++++++++++ .../boot_page_table/src/boot_page_table.h | 43 ++++++ tests/kernel/boot_page_table/src/main.c | 15 ++ tests/kernel/boot_page_table/testcase.yaml | 5 + 7 files changed, 259 insertions(+) create mode 100644 tests/kernel/boot_page_table/CMakeLists.txt create mode 100644 tests/kernel/boot_page_table/README.txt create mode 100644 tests/kernel/boot_page_table/prj.conf create mode 100644 tests/kernel/boot_page_table/src/boot_page_table.c create mode 100644 tests/kernel/boot_page_table/src/boot_page_table.h create mode 100644 tests/kernel/boot_page_table/src/main.c create mode 100644 tests/kernel/boot_page_table/testcase.yaml diff --git a/tests/kernel/boot_page_table/CMakeLists.txt b/tests/kernel/boot_page_table/CMakeLists.txt new file mode 100644 index 00000000000000..92a4288bc1d854 --- /dev/null +++ b/tests/kernel/boot_page_table/CMakeLists.txt @@ -0,0 +1,5 @@ +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(NONE) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/kernel/boot_page_table/README.txt b/tests/kernel/boot_page_table/README.txt new file mode 100644 index 00000000000000..fd91c3e2af637e --- /dev/null +++ b/tests/kernel/boot_page_table/README.txt @@ -0,0 +1,44 @@ +Title: x86 boot time page table validation + +Description: + +This test is for x86 to validate boot time page table faults. +Testcase outputs to console, for corresponding result, on validating +boot page table. + +The checks are for param of the interested memory region +that are value->p, value->us and value->rw. These are permissoin associated +with the interested memory regions. + +-------------------------------------------------------------------------------- + +Build and Run: + +This testcase will output to console. It can be built and executed +on QEMU as follows: + + mkdir build && cd build + cmake -DBOARD=qemu_x86 .. + make run + +-------------------------------------------------------------------------------- + +Troubleshooting/Problem Solving: + +Issues will occur if the object files and other related files generated from +previous build are not discarded. In that scenario below step can be followed + + make pristine # remove old outdir directory + # discard results/files generated from previous build + +-------------------------------------------------------------------------------- + +Sample Output: + +Running test suite boot_page_table_validate +=================================================================== +starting test - test_boot_page_table +PASS - test_boot_page_table. +=================================================================== +=================================================================== +PROJECT EXECUTION SUCCESSFUL diff --git a/tests/kernel/boot_page_table/prj.conf b/tests/kernel/boot_page_table/prj.conf new file mode 100644 index 00000000000000..9467c2926896dd --- /dev/null +++ b/tests/kernel/boot_page_table/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/tests/kernel/boot_page_table/src/boot_page_table.c b/tests/kernel/boot_page_table/src/boot_page_table.c new file mode 100644 index 00000000000000..cb5223ace3ef58 --- /dev/null +++ b/tests/kernel/boot_page_table/src/boot_page_table.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "boot_page_table.h" + +#define MEMORY_REG_NUM 4 + +MMU_BOOT_REGION(START_ADDR_RANGE1, ADDR_SIZE, REGION_PERM); +MMU_BOOT_REGION(START_ADDR_RANGE2, ADDR_SIZE, REGION_PERM); +MMU_BOOT_REGION(START_ADDR_RANGE3, ADDR_SIZE, REGION_PERM); +MMU_BOOT_REGION(START_ADDR_RANGE4, ADDR_SIZE, REGION_PERM); + +static int check_param(union x86_mmu_pae_pte *value, uint32_t perm) +{ + u32_t status = (value->rw == ((perm & MMU_PTE_RW_MASK) >> 0x1)); + + status &= (value->us == ((perm & MMU_PTE_US_MASK) >> 0x2)); + status &= value->p; + return status; +} + +static int check_param_nonset_region(union x86_mmu_pae_pte *value, + uint32_t perm) +{ + u32_t status = (value->rw == 0); + + status &= (value->us == 0); + status &= (value->p == 0); + return status; +} + +static int starting_addr_range(u32_t start_addr_range) +{ + + u32_t addr_range, status = true; + union x86_mmu_pae_pte *value; + + for (addr_range = start_addr_range; addr_range <= + (start_addr_range + STARTING_ADDR_RANGE_LMT); + addr_range += 0x1000) { + value = X86_MMU_GET_PTE(addr_range); + status &= check_param(value, REGION_PERM); + if (status == 0) { + printk("error at %d permissions %d\n", + addr_range, REGION_PERM); + TC_PRINT("%s failed\n", __func__); + return TC_FAIL; + } + } + return TC_PASS; +} + +static int before_start_addr_range(u32_t start_addr_range) +{ + u32_t addr_range, status = true; + union x86_mmu_pae_pte *value; + + for (addr_range = start_addr_range - 0x7000; + addr_range < (start_addr_range); addr_range += 0x1000) { + + value = X86_MMU_GET_PTE(addr_range); + status &= check_param_nonset_region(value, + REGION_PERM); + if (status == 0) { + TC_PRINT("%s failed\n", __func__); + printk("error at %d permissions %d\n", + addr_range, REGION_PERM); + return TC_FAIL; + + } + } + return TC_PASS; +} + +static int ending_start_addr_range(u32_t start_addr_range) +{ + u32_t addr_range, status = true; + union x86_mmu_pae_pte *value; + + for (addr_range = start_addr_range + ADDR_SIZE; addr_range < + (start_addr_range + ADDR_SIZE + 0x10000); + addr_range += 0x1000) { + value = X86_MMU_GET_PTE(addr_range); + status &= check_param_nonset_region(value, REGION_PERM); + if (status == 0) { + TC_PRINT("%s failed\n", __func__); + printk("error at %d permissions %d\n", + addr_range, REGION_PERM); + return TC_FAIL; + + } + } + return TC_PASS; +} + +int boot_page_table(void) +{ + u32_t start_addr_range; + int iterator = 0, check = 0; + + for (iterator = 0; iterator < MEMORY_REG_NUM; iterator++) { + switch (iterator) { + + case 0: + start_addr_range = START_ADDR_RANGE1; + break; + + case 1: + start_addr_range = START_ADDR_RANGE2; + break; + + case 2: + start_addr_range = START_ADDR_RANGE3; + break; + + case 3: + start_addr_range = START_ADDR_RANGE4; + break; + default: + break; + } + check = starting_addr_range(start_addr_range); + if (check == TC_FAIL) + return TC_FAIL; + check = before_start_addr_range(start_addr_range); + if (check == TC_FAIL) + return TC_FAIL; + check = ending_start_addr_range(start_addr_range); + if (check == TC_FAIL) + return TC_FAIL; + + } + return TC_PASS; +} + +void test_boot_page_table(void) +{ + zassert_true(boot_page_table() == TC_PASS, NULL); +} diff --git a/tests/kernel/boot_page_table/src/boot_page_table.h b/tests/kernel/boot_page_table/src/boot_page_table.h new file mode 100644 index 00000000000000..a918d66311953b --- /dev/null +++ b/tests/kernel/boot_page_table/src/boot_page_table.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __BOOT_PAGE_TABLE_H__ +#define __BOOT_PAGE_TABLE_H__ + +#ifndef X86_MMU_GET_PT_ADDR + +/* Helper macros to ease the usage of the MMU page table structures. + * Returns the Page table address for the particular address. + * Page Table address(returned value) is always 4KBytes aligned. + */ +#define X86_MMU_GET_PT_ADDR(addr) \ + ((struct x86_mmu_page_table *)\ + (X86_MMU_GET_PDE(addr)->page_table << MMU_PAGE_SHIFT)) + +#endif + +#ifndef X86_MMU_GET_PTE +/* Returns the page table entry for the addr + * use the union to extract page entry related information. + */ + +#define X86_MMU_GET_PTE(addr)\ + ((union x86_mmu_pae_pte *)\ + (&X86_MMU_GET_PT_ADDR(addr)->entry[MMU_PAGE_NUM(addr)])) +#endif + +#define MMU_READ 0x00 +#define MMU_WRITE 0x01 +#define MMU_READ_WRITE (MMU_READ | MMU_WRITE) +#define MMU_PAGE_USER 0x02 +#define START_ADDR_RANGE1 0x12300000 +#define START_ADDR_RANGE2 0x12340000 +#define START_ADDR_RANGE3 0x12400000 +#define START_ADDR_RANGE4 0x12460000 +#define ADDR_SIZE 0x1000 +#define STARTING_ADDR_RANGE_LMT 0x0009ff +#define START_ADR_RANGE_OVRLP_LMT 0x001000 +#define REGION_PERM (MMU_READ_WRITE | MMU_PAGE_USER) +#endif diff --git a/tests/kernel/boot_page_table/src/main.c b/tests/kernel/boot_page_table/src/main.c new file mode 100644 index 00000000000000..cb201907d5c0fd --- /dev/null +++ b/tests/kernel/boot_page_table/src/main.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +extern void test_boot_page_table(void); + +void test_main(void) +{ + ztest_test_suite(boot_page_table_validate, + ztest_unit_test(test_boot_page_table)); + ztest_run_test_suite(boot_page_table_validate); +} diff --git a/tests/kernel/boot_page_table/testcase.yaml b/tests/kernel/boot_page_table/testcase.yaml new file mode 100644 index 00000000000000..b79888f2f5aeb1 --- /dev/null +++ b/tests/kernel/boot_page_table/testcase.yaml @@ -0,0 +1,5 @@ +tests: +- test: + platform_whitelist: qemu_x86 + platform_exclude: qemu_x86_nommu + tags: kernel