Skip to content

Commit

Permalink
tests: kernel: x86 : App to validate x86 specific boot time page table
Browse files Browse the repository at this point in the history
Testcase developed to validate x86 specific boot time page table faults.

Signed-off-by: Akhilesh Kumar Upadhyay <[email protected]>
  • Loading branch information
Akhilesh Kumar Upadhyay authored and Anas Nashif committed Dec 5, 2017
1 parent 22f3d36 commit 149c341
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 0 deletions.
5 changes: 5 additions & 0 deletions tests/kernel/boot_page_table/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
44 changes: 44 additions & 0 deletions tests/kernel/boot_page_table/README.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions tests/kernel/boot_page_table/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_ZTEST=y
146 changes: 146 additions & 0 deletions tests/kernel/boot_page_table/src/boot_page_table.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr.h>
#include <misc/printk.h>
#include <mmustructs.h>
#include <ztest.h>
#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);
}
43 changes: 43 additions & 0 deletions tests/kernel/boot_page_table/src/boot_page_table.h
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions tests/kernel/boot_page_table/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <ztest.h>
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);
}
5 changes: 5 additions & 0 deletions tests/kernel/boot_page_table/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tests:
- test:
platform_whitelist: qemu_x86
platform_exclude: qemu_x86_nommu
tags: kernel

0 comments on commit 149c341

Please sign in to comment.