Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: kernel: App to validate boot time page table #1286

Merged
merged 1 commit into from
Dec 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing copyright/license header

#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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing copyright/license header

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need a header guard here


/* 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move line 37 (#endif )to line 27

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#endif moved to line 27

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>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing copyright/license header

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