kernel: remove gdb_server

This is unmaintained and currently has no known users. It was
added to support a Wind River project. If in the future we need it
again, we should re-introduce it with an exception-based mechanism
for catching out-of-bounds memory queries from the debugger.

The mem_safe subsystem is also removed, it is only used by the
GDB server. If its functionality is needed in the future, it
shoudl be replaced with an exception-based mechanism.

The _image_{ram, rom, text}_{start, end} linker variables have
been left in place, they will be re-purposed and expanded to
support memory protection.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-06-14 14:19:41 -07:00 committed by Anas Nashif
commit 0f669132a0
16 changed files with 1 additions and 3562 deletions

View file

@ -180,8 +180,6 @@ SECTIONS
{
_image_ram_start = .;
__data_ram_start = .;
*(.top_of_image_ram)
*(.top_of_image_ram.*)
*(.data)
*(".data.*")
@ -222,8 +220,6 @@ SECTIONS
*/
*(.noinit)
*(".noinit.*")
*(.bottom_of_image_ram)
*(.bottom_of_image_ram.*)
} GROUP_LINK_IN(RAMABLE_REGION)
/* Define linker symbols */

View file

@ -130,8 +130,6 @@ SECTIONS
KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE)
_image_ram_start = .;
__data_ram_start = .;
*(.top_of_image_ram)
*(.top_of_image_ram.*)
*(.data)
*(".data.*")
@ -193,9 +191,6 @@ SECTIONS
*/
*(.noinit)
*(".noinit.*")
*(.bottom_of_image_ram)
*(.bottom_of_image_ram.*)
} GROUP_LINK_IN(RAMABLE_REGION)

View file

@ -1,154 +0,0 @@
/*
* Copyright (c) 2015 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _debug__mem_safe__h_
#define _debug__mem_safe__h_
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* @brief Safe memory access routines
*
* This module provides functions for safely writing to and reading from
* memory, as well as probing if a memory address is accessible. For the
* latter, permissions can be specified (read/write).
*/
#define SYS_MEM_SAFE_READ 0
#define SYS_MEM_SAFE_WRITE 1
/**
* @brief verify memory at an address is accessible
*
* Probe memory for read or write access by specifying the @a perm, either
* SYS_MEM_SAFE_WRITE or SYS_MEM_SAFE_READ. A size @a num_bytes specifying
* the number of bytes to access must also be specified: for a 32-bit system,
* it can only take the values 1,2 or 4 (8/16/32 bits). Both @a p and @a buf
* must be naturally aligned to @a num_bytes.
*
* On a read, the value read from the memory location @a p is returned through
* @a buf; on a write, the value contained in @a buf is written to memory at
* memory location @a p.
*
* @param p The pointer (address) to the location to probe
* @param perm Either SYS_MEM_PROBE_READ or SYS_MEM_PROBE_WRITE
* @param num_bytes The number of bytes to probe, must be either 1, 2 or 4
* @param buf On reads, will contain the value read; on writes, contains the
* value to write
*
* @retval 0 OK
* @retval -EINVAL If an invalid parameter is passed
* @retval -EFAULT If the address is not accessible.
*/
extern int _mem_probe(void *p, int perm, size_t num_bytes, void *buf);
/**
* @brief safely read memory
*
* @details Read @a num_bytes bytes at address @a src from buffer pointed to
* by @a buf. The @a width parameter specifies bus width of each memory access
* in bytes. If @a width is 0 a target optimal access width is used. All other
* values of access width are target dependent and optional. When @a width is
* non-zero, the both @a num_bytes and @a src must be a multiple of @a width.
*
* @param src The address to read from
* @param buf The destination buffer to receive the data read
* @param num_bytes The number of bytes to read
* @param width The access width
*
* @retval 0 OK
* @retval -EFAULT If there was an error reading memory
* @retval -EINVAL If access width, num_bytes and addresses are not compatible.
*/
extern int _mem_safe_read(void *src, char *buf, size_t num_bytes,
int width);
/**
* @brief safely write memory
*
* @details Write @a num_bytes bytes to address @a dest from buffer pointed to
* by @a buf. The @a width parameter specifies bus width of each memory access
* in bytes. If @a width is 0 a target optimal access width is used. All other
* values of access width are target dependent and optional. When @a width is
* non-zero, the both @a num_bytes and @a dest must be a multiple of @a width.
*
* @param dest The address to write to
* @param buf The source buffer to write in memory
* @param num_bytes The number of bytes to write
* @param width The access width
*
* @retval 0 OK
* @retval -EFAULT If there was an error writing memory
* @retval -EINVAL If access width, num_bytes and addresses are not compatible.
*/
extern int _mem_safe_write(void *dest, char *buf, size_t num_bytes,
int width);
/**
* @brief write to text section
*
* @details Write @a num_bytes bytes to address @a dest from buffer pointed to
* by @a buf.
*
* @param dest The address to write to
* @param buf The source buffer to write in memory
* @param num_bytes The number of bytes to write
*
* @retval 0 Success
* @retval -EFAULT If there was an error writing memory
*/
extern int _mem_safe_write_to_text_section(void *dest, char *buf,
size_t num_bytes);
/**
* @brief add to the table of valid regions
*
* @details Add a new region that is considered valid to read from or both
* read from and write to. The region starts at @a addr and its size is @a
* num_bytes. The read/write permissions are specified via @a perm and can
* take the values either SYS_MEM_SAFE_READ or SYS_MEM_SAFE_WRITE.
*
* The table size is specified via the CONFIG_MEM_SAFE_NUM_EXTRA_REGIONS kconfig
* option.
*
* If the implementation of safe memory access chosen does not need this API,
* it is still available, but results in a no-op and always returns success
* (0).
*
* @param addr The address to write to
* @param num_bytes The size of the region in bytes
* @param perm The access permissions, either SYS_MEM_SAFE_WRITE or
* SYS_MEM_SAFE_READ
*
* @retval 0 OK
* @retval -ENOMEM If there there is no space left in the table of regions
* @retval -EINVAL If passing invalid permissions
*/
#ifdef CONFIG_MEM_SAFE_CHECK_BOUNDARIES
extern int _mem_safe_region_add(void *addr, size_t num_bytes, int perm);
#else
static inline int _mem_safe_region_add(void *addr, size_t num_bytes,
int perm)
{
return 0;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* _debug__mem_safe__h_ */

View file

@ -151,53 +151,6 @@ config OMIT_FRAME_POINTER
If unsure, disable OVERRIDE_FRAME_POINTER_DEFAULT to allow the compiler
to adopt sensible defaults for your architecture.
menu "Safe memory access"
config MEM_SAFE
bool
prompt "Enable safe memory access"
default n
help
Add the routines available in mem_safe.h to the system. This is added
as a kconfig option instead of simply linking against the library
because some implementations might require initialization.
choice
prompt "Safe memory access implementation"
depends on MEM_SAFE
default MEM_SAFE_CHECK_BOUNDARIES
config MEM_SAFE_CHECK_BOUNDARIES
bool
prompt "Software validation of memory access within memory regions"
help
This implementation checks the application image's text/rodata
boundaries for its read-only region and the data/bss/noinit boundaries
for its read-write region, in software.
Other regions can be added as needed by using the
sys_mem_safe_region_add() API. The number of regions that can be added
is controlled via the MEM_SAFE_NUM_EXTRA_REGIONS kconfig option.
This implementation requires initialization and thus consumes some boot
time.
endchoice
config MEM_SAFE_NUM_EXTRA_REGIONS
int
prompt "Number of safe memory access regions to be added at runtime"
depends on MEM_SAFE_CHECK_BOUNDARIES
default 0
help
The functions available in mem_safe.h check if memory is within
read-only or read-write regions before accessing it instead of crashing.
The kernel image is added as a valid region automatically, but other
regions can be added if the application makes access to additional
memory outside of the image's boundaries.
endmenu
#
# Generic Debugging Options
#
@ -211,55 +164,6 @@ config DEBUG_INFO
NOTE: Does not currently work with the x86 IAMCU ABI.
#
# GDB Server options
#
config GDB_SERVER
bool
prompt "Enable GDB Server [EXPERIMENTAL]"
default n
select CACHE_FLUSHING
select REBOOT
select MEM_SAFE
select DEBUG_INFO
select UART_CONSOLE_DEBUG_SERVER_HOOKS
help
This option enables the GDB Server support.
config GDB_SERVER_MAX_SW_BP
int "Maximum number of GDB Server Software breakpoints"
default 100
depends on GDB_SERVER
help
This option specifies the maximum number of Software breakpoints
config GDB_SERVER_INTERRUPT_DRIVEN
bool
prompt "Enable GDB interrupt mode"
default y
depends on GDB_SERVER
select CONSOLE_HANDLER
help
This option enables interrupt support for GDB Server.
config GDB_REMOTE_SERIAL_EXT_NOTIF_PREFIX_STR
string
prompt "Trigger string for remote serial ext. via notifi. packets"
default "WrCons"
depends on GDB_SERVER
help
The value of this option depends on the string the GDB client use to
prefix the notification packets.
config GDB_SERVER_BOOTLOADER
bool
prompt "Enable the bootloader mode"
default n
depends on GDB_SERVER
help
This option enables the bootloader mode of the GDB Server.
#
# Miscellaneous debugging options
#

View file

@ -1,9 +1,6 @@
ccflags-y +=-I$(srctree)/include/debug
CFLAGS_gdb_server.o =-I$(srctree)/include/drivers
obj-y =
obj-$(CONFIG_MEM_SAFE_CHECK_BOUNDARIES) += mem_safe_check_boundaries.o
obj-$(CONFIG_GDB_SERVER) += gdb_server.o
obj- = dummy.o
ifeq ($(CONFIG_OPENOCD_SUPPORT),y)
lib-y += openocd.o

File diff suppressed because it is too large Load diff

View file

@ -1,283 +0,0 @@
/*
* Copyright (c) 2015 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file safe memory access routines, software implementation that verifies
* accesses are within memory region boundaries.
*
* @details See debug/Kconfig and the "Safe memory access" help for details.
*/
#include <kernel.h>
#include <init.h>
#include <errno.h>
#include <toolchain.h>
#include <linker/linker-defs.h>
#include <misc/util.h>
#include <debug/mem_safe.h>
#include <string.h>
#define NUM_REGIONS (CONFIG_MEM_SAFE_NUM_EXTRA_REGIONS + 2)
/*
* The table of regions has the RO regions at the bottom and the RW regions at
* the top, and regions are added by moving the ro_end/rw_end pointers towards
* each other. The table is full when the pointers cross, i.e. when ro_end >
* rw_end.
*/
struct {
vaddr_t addr;
vaddr_t last_byte;
} mem_regions[NUM_REGIONS];
#define ro_base 0
#define rw_base (NUM_REGIONS - 1)
static int ro_end = ro_base;
static int rw_end = rw_base;
#define IMAGE_ROM_START ((vaddr_t)&_image_rom_start)
#define IMAGE_ROM_END ((vaddr_t)&_image_rom_end)
#define IMAGE_RAM_START ((vaddr_t)&_image_ram_start)
#define IMAGE_RAM_END ((vaddr_t)&_image_ram_end)
#define IMAGE_TEXT_START ((vaddr_t)&_image_text_start)
#define IMAGE_TEXT_END ((vaddr_t)&_image_text_end)
#define VALID_PERMISSION_MASK 0x00000001 /* permissions use only the lsb */
static inline void write_to_mem(void *dest, void *src, int width)
{
switch (width) {
case 4:
*((vaddr_t *)dest) = *((const vaddr_t *)src);
break;
case 2:
*((u16_t *)dest) = *((const u16_t *)src);
break;
case 1:
*((char *)dest) = *((const char *)src);
break;
}
}
static inline int is_in_region(int slot, vaddr_t addr, vaddr_t end_addr)
{
vaddr_t region_start = mem_regions[slot].addr;
vaddr_t region_last_byte = mem_regions[slot].last_byte;
return addr >= region_start && end_addr <= region_last_byte;
}
static inline int is_in_a_ro_region(vaddr_t addr, vaddr_t end_addr)
{
int slot = ro_base;
while (slot < ro_end && slot <= rw_end) {
if (is_in_region(slot, addr, end_addr)) {
return 1;
}
++slot;
}
return 0;
}
static inline int is_in_a_rw_region(vaddr_t addr, vaddr_t end_addr)
{
int slot = rw_base;
while (slot > rw_end && slot >= ro_end) {
if (is_in_region(slot, addr, end_addr)) {
return 1;
}
--slot;
}
return 0;
}
static inline int mem_probe_no_check(void *p, int perm, size_t num_bytes,
void *buf)
{
vaddr_t addr = (vaddr_t)p;
vaddr_t end_addr = addr + num_bytes - 1;
int is_in_rw = is_in_a_rw_region(addr, end_addr);
int is_in_ro = is_in_a_ro_region(addr, end_addr);
int valid_mem;
void *src, *dest;
if (perm == SYS_MEM_SAFE_READ) {
dest = buf; src = p;
valid_mem = is_in_rw || is_in_ro;
} else {
dest = p; src = buf;
valid_mem = is_in_rw;
}
if (likely(valid_mem)) {
write_to_mem(dest, src, num_bytes);
return 0;
}
return -EFAULT;
}
static inline int is_perm_valid(int perm)
{
return !(perm & ~VALID_PERMISSION_MASK);
}
static inline int is_num_bytes_valid(size_t num_bytes)
{
return is_power_of_two(num_bytes) && num_bytes <= sizeof(vaddr_t);
}
int _mem_probe(void *p, int perm, size_t num_bytes, void *buf)
{
if (unlikely(!is_perm_valid(perm))) {
return -EINVAL;
}
if (unlikely(!is_num_bytes_valid(num_bytes))) {
return -EINVAL;
}
return mem_probe_no_check(p, perm, num_bytes, buf);
}
static inline int mem_access(void *p, void *buf, size_t num_bytes,
int len, int perm)
{
char *p_char = p, *buf_char = buf, *p_end = ((char *)p + len);
while (p_char < p_end) {
int error = mem_probe_no_check(p_char, perm, num_bytes, buf_char);
if (unlikely(error < 0)) {
return error;
}
p_char += num_bytes;
buf_char += num_bytes;
}
return 0;
}
static inline int get_align(const u32_t value)
{
return (value & 1) ? 1 : (value & 2) ? 2 : 4;
}
static inline int get_width(const void *p1, const void *p2,
size_t num_bytes, int width)
{
vaddr_t p1_addr = (vaddr_t)p1, p2_addr = (vaddr_t)p2;
if (width == 0) {
u32_t align_check = num_bytes | p1_addr | p2_addr;
return get_align(align_check);
}
if (unlikely(p1_addr & (width - 1) || num_bytes & (width - 1))) {
return -EINVAL;
}
return width;
}
int _mem_safe_read(void *src, char *buf, size_t num_bytes, int width)
{
width = get_width(src, buf, num_bytes, width);
return unlikely(width < 0) ? -EINVAL :
mem_access(src, buf, width, num_bytes, SYS_MEM_SAFE_READ);
}
int _mem_safe_write(void *dest, char *buf, size_t num_bytes, int width)
{
width = get_width(dest, buf, num_bytes, width);
return unlikely(width < 0) ? -EINVAL :
mem_access(dest, buf, width, num_bytes, SYS_MEM_SAFE_WRITE);
}
#if defined(CONFIG_XIP)
int _mem_safe_write_to_text_section(void *dest, char *buf, size_t num_bytes)
{
ARG_UNUSED(dest);
ARG_UNUSED(buf);
ARG_UNUSED(num_bytes);
/* cannot write to text section when it's in ROM */
return -EFAULT;
}
#else
int _mem_safe_write_to_text_section(void *dest, char *buf, size_t num_bytes)
{
vaddr_t v = (vaddr_t)dest;
int is_in_text = ((v >= IMAGE_TEXT_START) &&
((v + num_bytes) <= IMAGE_TEXT_END));
if (unlikely(!is_in_text)) {
return -EFAULT;
}
memcpy(dest, buf, num_bytes);
return 0;
}
#endif /* CONFIG_XIP */
int _mem_safe_region_add(void *addr, size_t num_bytes, int perm)
{
if (unlikely(!is_perm_valid(perm))) {
return -EINVAL;
}
int slot;
int key = irq_lock();
if (unlikely(ro_end > rw_end)) {
irq_unlock(key);
return -ENOMEM;
}
if (perm == SYS_MEM_SAFE_WRITE) {
slot = rw_end;
--rw_end;
} else {
slot = ro_end;
++ro_end;
}
mem_regions[slot].addr = (vaddr_t)addr;
mem_regions[slot].last_byte = mem_regions[slot].addr + num_bytes - 1;
irq_unlock(key);
return 0;
}
static int init(struct device *unused)
{
void *addr;
size_t num_bytes;
ARG_UNUSED(unused);
addr = (void *)IMAGE_ROM_START;
num_bytes = (int)(IMAGE_ROM_END - IMAGE_ROM_START);
(void)_mem_safe_region_add(addr, num_bytes, SYS_MEM_SAFE_READ);
addr = (void *)IMAGE_RAM_START;
num_bytes = (int)(IMAGE_RAM_END - IMAGE_RAM_START);
(void)_mem_safe_region_add(addr, num_bytes, SYS_MEM_SAFE_WRITE);
return 0;
}
SYS_INIT(init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -1,13 +0,0 @@
BOARD ?= qemu_x86
CONF_FILE = prj_$(BOARD).conf
# This testcase requires a special linker script, from the testcase itself.
# The only boards that have one are the ones listed below.
valid_board_qemu_x86 = y
valid_board_qemu_cortex_m3 = y
ifneq ($(valid_board_$(BOARD)),y)
$(error not a supported board for this testcase)
endif
include $(ZEPHYR_BASE)/Makefile.test

View file

@ -1,96 +0,0 @@
Title: Safe Memory Access
Description:
This test verifies that the safe memory access (_mem_safe) functions as
intended.
---------------------------------------------------------------------------
Building and Running Project:
This project outputs to the console. It can be built and executed
on QEMU as follows:
make run
---------------------------------------------------------------------------
Troubleshooting:
Problems caused by out-dated project information can be addressed by
issuing one of the following commands then rebuilding the project:
make clean # discard results of previous builds
# but keep existing configuration info
or
make pristine # discard results of previous builds
# and restore pre-defined configuration info
---------------------------------------------------------------------------
Sample Output:
testing SUCCESS of READ on RO memory with width 1.......PASS
testing SUCCESS of READ on RO memory with width 2.......PASS
testing SUCCESS of READ on RO memory with width 4.......PASS
testing FAILURE of WRITE on RO memory with width 1.......PASS
testing FAILURE of WRITE on RO memory with width 2.......PASS
testing FAILURE of WRITE on RO memory with width 4.......PASS
testing SUCCESS of READ on RW memory with width 1.......PASS
testing SUCCESS of READ on RW memory with width 2.......PASS
testing SUCCESS of READ on RW memory with width 4.......PASS
testing SUCCESS of WRITE on RW memory with width 1.......PASS
testing SUCCESS of WRITE on RW memory with width 2.......PASS
testing SUCCESS of WRITE on RW memory with width 4.......PASS
testing FAILURE of INVALID ACCESS on RW memory with width 4.......PASS
testing FAILURE of READ on RO memory with width 0.......PASS
testing SUCCESS of READ on RO memory with width 1.......PASS
testing SUCCESS of READ on RO memory with width 2.......PASS
testing FAILURE of READ on RO memory with width 3.......PASS
testing SUCCESS of READ on RO memory with width 4.......PASS
testing FAILURE of READ on RO memory with width 5.......PASS
testing FAILURE of READ on RO memory with width 8.......PASS
testing SUCCESS of READ on RO memory with width 1.......PASS
testing SUCCESS of READ on RO memory with width 1.......PASS
testing SUCCESS of READ on RW memory with width 1.......PASS
testing SUCCESS of READ on RW memory with width 1.......PASS
testing FAILURE of WRITE on RO memory with width 1.......PASS
testing FAILURE of WRITE on RO memory with width 1.......PASS
testing SUCCESS of WRITE on RW memory with width 1.......PASS
testing SUCCESS of WRITE on RW memory with width 1.......PASS
testing FAILURE of READ on out-of-image memory with width 1.......PASS
testing FAILURE of READ on out-of-image memory with width 1.......PASS
testing SUCCESS of adding extra RO region.......PASS
testing SUCCESS of adding extra RW region.......PASS
testing FAILURE of adding extra region that won't fit.......PASS
testing SUCCESS of READ on out-of-image memory with width 1.......PASS
testing SUCCESS of READ on out-of-image memory with width 1.......PASS
testing SUCCESS of READ on out-of-image memory with width 1.......PASS
testing SUCCESS of READ on out-of-image memory with width 1.......PASS
testing FAILURE of WRITE on out-of-image memory with width 1.......PASS
testing FAILURE of WRITE on out-of-image memory with width 1.......PASS
testing SUCCESS of WRITE on out-of-image memory with width 1.......PASS
testing SUCCESS of WRITE on out-of-image memory with width 1.......PASS
testing FAILURE of READ on out-of-image memory with width 1.......PASS
testing FAILURE of READ on out-of-image memory with width 1.......PASS
testing FAILURE of READ on out-of-image memory with width 1.......PASS
testing FAILURE of READ on out-of-image memory with width 1.......PASS
testing FAILURE of WRITE on RO memory with width 1.......PASS
testing SUCCESS of _mem_probe() reading RO values.......PASS
testing SUCCESS of _mem_probe() reading RW values.......PASS
testing SUCCESS of _mem_probe() writing values.......PASS
testing SUCCESS of _mem_safe_read(size: 16, width: 0).......PASS
testing SUCCESS of _mem_safe_read(size: 16, width: 4).......PASS
testing SUCCESS of _mem_safe_read(size: 14, width: 2).......PASS
testing SUCCESS of _mem_safe_read(size: 15, width: 1).......PASS
testing FAILURE of _mem_safe_read() with bad params.......PASS (-22)
testing SUCCESS of _mem_safe_write(size: 16, width: 0).......PASS
testing SUCCESS of _mem_safe_write(size: 16, width: 4).......PASS
testing SUCCESS of _mem_safe_write(size: 14, width: 2).......PASS
testing SUCCESS of _mem_safe_write(size: 15, width: 1).......PASS
testing FAILURE of _mem_safe_write() with bad params.......PASS (-22)
===================================================================
PASS - main.
===================================================================
PROJECT EXECUTION SUCCESSFUL

View file

@ -1,3 +0,0 @@
CONFIG_MEM_SAFE=y
CONFIG_MEM_SAFE_NUM_EXTRA_REGIONS=2
CONFIG_CACHE_FLUSHING=y

View file

@ -1,3 +0,0 @@
CONFIG_MEM_SAFE=y
CONFIG_MEM_SAFE_NUM_EXTRA_REGIONS=2
CONFIG_CACHE_FLUSHING=y

View file

@ -1,6 +0,0 @@
ccflags-y += -I${ZEPHYR_BASE}/tests/include
DQUOTE = "
BUILD_ARCH = $(strip $(subst $(DQUOTE),,$(CONFIG_ARCH)))
obj-y += main.o
obj-y += asm_$(BUILD_ARCH).o

View file

@ -1,19 +0,0 @@
/*
* Copyright (c) 2015 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @ brief architecture specific support for the mem_probe tests
*/
#include <arch/x86/asm.h>
GDATA(foo)
GTEXT(add_ten_to_foo)
SECTION_FUNC(TEXT, add_ten_to_foo)
addl $10, foo
ret

View file

@ -1,410 +0,0 @@
/*
* Copyright (c) 2015 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @ brief tests for the mem_probe functionalities
*/
#include <stdio.h>
#include <misc/util.h>
#include <linker/linker-defs.h>
#include <debug/mem_safe.h>
#include <tc_util.h>
#include <cache.h>
#define MY_DATA_SIZE 16
const char __aligned(4) real_rodata[MY_DATA_SIZE] = "0123456789abcdef";
char *rodata = (char *)real_rodata;
char __aligned(4) rwdata[MY_DATA_SIZE+1];
char __aligned(4) buffer[MY_DATA_SIZE+1];
#if MY_DATA_SIZE != 16
#error never verified with values other than 16!
#endif
#define ROM_START ((u32_t)&_image_rom_start)
#define ROM_END ((u32_t)&_image_rom_end)
#define RAM_START ((u32_t)&_image_ram_start)
#define RAM_END ((u32_t)&_image_ram_end)
char * const p_image_rom_start = (char *)ROM_START;
char * const p_image_rom_end = (char *)ROM_END;
char * const p_image_ram_start = (char *)RAM_START;
char * const p_image_ram_end = (char *)RAM_END;
char *rw_data_after_image = (char *)(RAM_END + KB(1));
char *rw_data_after_image_end;
char *ro_data_after_image = (char *)(RAM_END + KB(3));
char *ro_data_after_image_end;
int foo;
#define PROBE_BUFFER_SIZE 32
char top_of_ram[PROBE_BUFFER_SIZE] __in_section(top_of_image_ram, 0, 0);
char bottom_of_ram[PROBE_BUFFER_SIZE] __in_section(bottom_of_image_ram, 0, 0);
static void update_rv(int *rv, int last_result)
{
*rv = *rv == TC_FAIL ? *rv : last_result;
if (last_result == TC_FAIL) {
TC_PRINT("FAIL\n");
} else {
TC_PRINT("PASS\n");
}
}
#define RO 0
#define RW 1
#define INVALID -1
static int mem_range_check(const void *p)
{
u32_t addr = (u32_t)p;
if (addr >= ROM_START && addr < ROM_END) {
return RO;
} else if (addr >= RAM_START && addr < RAM_END) {
return RW;
} else {
return INVALID;
}
}
static int test_width(char *mem, int perm, int width, int expected)
{
char *rights_str = perm == SYS_MEM_SAFE_READ ? "READ" :
perm == SYS_MEM_SAFE_WRITE ? "WRITE" :
"INVALID ACCESS";
int mem_type = mem_range_check(mem);
char *mem_range_str = mem_type == RO ? "RO" :
mem_type == RW ? "RW" : "out-of-image";
TC_PRINT("testing %s of %s on %s memory with width %d.......",
expected == 0 ? "SUCCESS" : "FAILURE",
rights_str, mem_range_str, width);
int rv = _mem_probe(mem, perm, width, buffer);
return rv == expected ? TC_PASS : TC_FAIL;
}
static int test_width_read(char *mem, int width, int expected)
{
return test_width(mem, SYS_MEM_SAFE_READ, width, expected);
}
static int test_width_write(char *mem, int width, int expected)
{
return test_width(mem, SYS_MEM_SAFE_WRITE, width, expected);
}
typedef int (*access_func)(void *, char *, size_t, int);
static int test_mem_safe_access(void *p, char *buf, int size,
int width, int perm)
{
int rc;
char *func_str = (perm == SYS_MEM_SAFE_WRITE) ? "write" : "read";
access_func func = (perm == SYS_MEM_SAFE_WRITE) ?
_mem_safe_write : _mem_safe_read;
TC_PRINT("testing SUCCESS of _mem_safe_%s(size: %d, width: %d).......",
func_str, size, width);
rc = func(p, buf, size, width);
if (rc < 0) {
TC_PRINT("(%d)", rc);
return TC_FAIL;
}
if (memcmp(p, buf, size) != 0) {
TC_PRINT("(bad data)");
return TC_FAIL;
}
return TC_PASS;
}
void main(void)
{
/* reference symbols so that they get included */
top_of_ram[0] = 'a';
bottom_of_ram[PROBE_BUFFER_SIZE - 1] = 'z';
int rv = TC_PASS;
int rc; /* temporary return code */
buffer[MY_DATA_SIZE] = '\0';
rwdata[MY_DATA_SIZE] = '\0';
TC_START("safe memory access routines\n");
/****
* _mem_probe()
*/
/* test access perm */
update_rv(&rv, test_width_read(rodata, 1, 0));
update_rv(&rv, test_width_read(rodata, 2, 0));
update_rv(&rv, test_width_read(rodata, 4, 0));
update_rv(&rv, test_width_write(rodata, 1, -EFAULT));
update_rv(&rv, test_width_write(rodata, 2, -EFAULT));
update_rv(&rv, test_width_write(rodata, 4, -EFAULT));
update_rv(&rv, test_width_read(rwdata, 1, 0));
update_rv(&rv, test_width_read(rwdata, 2, 0));
update_rv(&rv, test_width_read(rwdata, 4, 0));
update_rv(&rv, test_width_write(rwdata, 1, 0));
update_rv(&rv, test_width_write(rwdata, 2, 0));
update_rv(&rv, test_width_write(rwdata, 4, 0));
const int invalid_access_right = 3;
update_rv(&rv, test_width(rwdata, invalid_access_right, 4, -EINVAL));
/* test alignments constraints */
update_rv(&rv, test_width_read(rodata, 0, -EINVAL));
update_rv(&rv, test_width_read(rodata, 1, 0));
update_rv(&rv, test_width_read(rodata, 2, 0));
update_rv(&rv, test_width_read(rodata, 3, -EINVAL));
update_rv(&rv, test_width_read(rodata, 4, 0));
update_rv(&rv, test_width_read(rodata, 5, -EINVAL));
update_rv(&rv, test_width_read(rodata, 8, -EINVAL));
/* test image limits */
update_rv(&rv, test_width_read(p_image_rom_start, 1, 0));
update_rv(&rv, test_width_read(p_image_rom_end - 1, 1, 0));
update_rv(&rv, test_width_read(p_image_ram_start, 1, 0));
update_rv(&rv, test_width_read(p_image_ram_end - 1, 1, 0));
update_rv(&rv, test_width_write(p_image_rom_start, 1, -EFAULT));
update_rv(&rv, test_width_write(p_image_rom_end - 1, 1, -EFAULT));
update_rv(&rv, test_width_write(p_image_ram_start, 1, 0));
update_rv(&rv, test_width_write(p_image_ram_end - 1, 1, 0));
update_rv(&rv, test_width_read(p_image_rom_start - 1, 1, -EFAULT));
update_rv(&rv, test_width_read(p_image_ram_end, 1, -EFAULT));
/* test out-of-image valid regions */
rw_data_after_image_end = rw_data_after_image + KB(1);
ro_data_after_image_end = ro_data_after_image + KB(1);
TC_PRINT("testing SUCCESS of adding extra RO region.......");
int region_add_rc = _mem_safe_region_add(ro_data_after_image, KB(1),
SYS_MEM_SAFE_READ);
if (region_add_rc < 0) {
update_rv(&rv, TC_FAIL);
TC_PRINT("FAIL (%d)\n", region_add_rc);
} else {
TC_PRINT("PASS\n");
}
TC_PRINT("testing SUCCESS of adding extra RW region.......");
region_add_rc = _mem_safe_region_add(rw_data_after_image, KB(1),
SYS_MEM_SAFE_WRITE);
if (region_add_rc < 0) {
update_rv(&rv, TC_FAIL);
TC_PRINT("FAIL (%d)\n", region_add_rc);
} else {
TC_PRINT("PASS\n");
}
TC_PRINT("testing FAILURE of adding extra region that won't fit.......");
region_add_rc = _mem_safe_region_add(rw_data_after_image, KB(1),
SYS_MEM_SAFE_WRITE);
if (region_add_rc < 0) {
TC_PRINT("PASS\n");
} else {
TC_PRINT("FAIL\n");
}
update_rv(&rv, test_width_read(ro_data_after_image, 1, 0));
update_rv(&rv, test_width_read(ro_data_after_image_end - 1, 1, 0));
update_rv(&rv, test_width_read(rw_data_after_image, 1, 0));
update_rv(&rv, test_width_read(rw_data_after_image_end - 1, 1, 0));
update_rv(&rv, test_width_write(ro_data_after_image, 1, -EFAULT));
update_rv(&rv, test_width_write(ro_data_after_image_end - 1, 1, -EFAULT));
update_rv(&rv, test_width_write(rw_data_after_image, 1, 0));
update_rv(&rv, test_width_write(rw_data_after_image_end - 1, 1, 0));
update_rv(&rv, test_width_read(ro_data_after_image - 1, 1, -EFAULT));
update_rv(&rv, test_width_read(ro_data_after_image_end, 1, -EFAULT));
update_rv(&rv, test_width_read(rw_data_after_image - 1, 1, -EFAULT));
update_rv(&rv, test_width_read(rw_data_after_image_end, 1, -EFAULT));
/*
* Test the dividing line between rom and ram, even in non-xip images:
* it might hit ROM or invalid memory, but never RAM.
*/
update_rv(&rv, test_width_write(p_image_ram_start - 1, 1, -EFAULT));
TC_PRINT("testing SUCCESS of _mem_probe() reading RO values.......");
(void)_mem_probe(rodata, SYS_MEM_SAFE_READ, 4, buffer);
(void)_mem_probe(rodata+4, SYS_MEM_SAFE_READ, 4, buffer+4);
(void)_mem_probe(rodata+8, SYS_MEM_SAFE_READ, 2, buffer+8);
(void)_mem_probe(rodata+10, SYS_MEM_SAFE_READ, 2, buffer+10);
(void)_mem_probe(rodata+12, SYS_MEM_SAFE_READ, 1, buffer+12);
(void)_mem_probe(rodata+13, SYS_MEM_SAFE_READ, 1, buffer+13);
(void)_mem_probe(rodata+14, SYS_MEM_SAFE_READ, 1, buffer+14);
(void)_mem_probe(rodata+15, SYS_MEM_SAFE_READ, 1, buffer+15);
if (memcmp(rodata, buffer, 16) != 0) {
TC_PRINT("FAIL\n");
update_rv(&rv, TC_FAIL);
} else {
TC_PRINT("PASS\n");
}
memcpy(rwdata, rodata, MY_DATA_SIZE);
memset(buffer, '-', MY_DATA_SIZE);
TC_PRINT("testing SUCCESS of _mem_probe() reading RW values.......");
(void)_mem_probe(rwdata, SYS_MEM_SAFE_READ, 4, buffer);
(void)_mem_probe(rwdata+4, SYS_MEM_SAFE_READ, 4, buffer+4);
(void)_mem_probe(rwdata+8, SYS_MEM_SAFE_READ, 2, buffer+8);
(void)_mem_probe(rwdata+10, SYS_MEM_SAFE_READ, 2, buffer+10);
(void)_mem_probe(rwdata+12, SYS_MEM_SAFE_READ, 1, buffer+12);
(void)_mem_probe(rwdata+13, SYS_MEM_SAFE_READ, 1, buffer+13);
(void)_mem_probe(rwdata+14, SYS_MEM_SAFE_READ, 1, buffer+14);
(void)_mem_probe(rwdata+15, SYS_MEM_SAFE_READ, 1, buffer+15);
if (memcmp(rwdata, buffer, 16) != 0) {
TC_PRINT("FAIL\n");
update_rv(&rv, TC_FAIL);
} else {
TC_PRINT("PASS\n");
}
memcpy(buffer, rodata, MY_DATA_SIZE);
memset(rwdata, '-', MY_DATA_SIZE);
TC_PRINT("testing SUCCESS of _mem_probe() writing values.......");
(void)_mem_probe(rwdata, SYS_MEM_SAFE_WRITE, 4, buffer);
(void)_mem_probe(rwdata+4, SYS_MEM_SAFE_WRITE, 4, buffer+4);
(void)_mem_probe(rwdata+8, SYS_MEM_SAFE_WRITE, 2, buffer+8);
(void)_mem_probe(rwdata+10, SYS_MEM_SAFE_WRITE, 2, buffer+10);
(void)_mem_probe(rwdata+12, SYS_MEM_SAFE_WRITE, 1, buffer+12);
(void)_mem_probe(rwdata+13, SYS_MEM_SAFE_WRITE, 1, buffer+13);
(void)_mem_probe(rwdata+14, SYS_MEM_SAFE_WRITE, 1, buffer+14);
(void)_mem_probe(rwdata+15, SYS_MEM_SAFE_WRITE, 1, buffer+15);
if (memcmp(rwdata, buffer, 16) != 0) {
TC_PRINT("FAIL\n");
update_rv(&rv, TC_FAIL);
} else {
TC_PRINT("PASS\n");
}
/*****
* _mem_safe_read()
*/
memset(buffer, '-', MY_DATA_SIZE);
update_rv(&rv, test_mem_safe_access(rodata, buffer, MY_DATA_SIZE,
0, SYS_MEM_SAFE_READ));
update_rv(&rv, test_mem_safe_access(rodata, buffer, MY_DATA_SIZE,
4, SYS_MEM_SAFE_READ));
update_rv(&rv, test_mem_safe_access(rodata, buffer, MY_DATA_SIZE-2,
2, SYS_MEM_SAFE_READ));
update_rv(&rv, test_mem_safe_access(rodata, buffer, MY_DATA_SIZE-1,
1, SYS_MEM_SAFE_READ));
TC_PRINT("testing FAILURE of _mem_safe_read() with bad params.......");
rc = _mem_safe_read(rodata+1, buffer, MY_DATA_SIZE-1, 2);
if (rc == 0) {
TC_PRINT("FAIL\n");
update_rv(&rv, TC_FAIL);
} else {
TC_PRINT("PASS (%d)\n", rc);
}
/*****
* _mem_safe_write()
*/
memcpy(buffer, rodata, MY_DATA_SIZE);
memset(rwdata, '-', MY_DATA_SIZE);
update_rv(&rv, test_mem_safe_access(rwdata, buffer, MY_DATA_SIZE,
0, SYS_MEM_SAFE_WRITE));
memcpy(buffer, rodata, MY_DATA_SIZE);
memset(rwdata, '-', MY_DATA_SIZE);
update_rv(&rv, test_mem_safe_access(rwdata, buffer, MY_DATA_SIZE,
4, SYS_MEM_SAFE_WRITE));
memcpy(buffer, rodata, MY_DATA_SIZE);
memset(rwdata, '-', MY_DATA_SIZE);
update_rv(&rv, test_mem_safe_access(rwdata, buffer, MY_DATA_SIZE - 2,
2, SYS_MEM_SAFE_WRITE));
memcpy(buffer, rodata, MY_DATA_SIZE);
memset(rwdata, '-', MY_DATA_SIZE);
update_rv(&rv, test_mem_safe_access(rwdata, buffer, MY_DATA_SIZE - 1,
1, SYS_MEM_SAFE_WRITE));
memcpy(buffer, rodata, MY_DATA_SIZE);
memset(rwdata, '-', MY_DATA_SIZE);
TC_PRINT("testing FAILURE of _mem_safe_write() with bad params.......");
rc = _mem_safe_write(rwdata+1, buffer, MY_DATA_SIZE-1, 2);
if (rc == 0) {
TC_PRINT("FAIL\n");
update_rv(&rv, TC_FAIL);
} else {
TC_PRINT("PASS (%d)\n", rc);
}
#if !defined(CONFIG_XIP)
/*****
* _mem_safe_write_to_text_section()
*/
extern void add_ten_to_foo(void);
foo = 0;
memset(buffer, 0x90, 7);
TC_PRINT("testing FAILURE of _mem_safe_write_to_text_section(&data).......");
if (_mem_safe_write_to_text_section(&foo, buffer, 1) == 0) {
TC_PRINT("FAIL\n");
} else {
TC_PRINT("PASS\n");
}
TC_PRINT("testing SUCCESS of _mem_safe_write_to_text_section(&text).......");
add_ten_to_foo();
if (foo != 10) {
TC_PRINT("FAIL\n");
} else {
if (_mem_safe_write_to_text_section((void *)add_ten_to_foo,
buffer, 7) < 0) {
TC_PRINT("FAIL\n");
} else {
sys_cache_flush((vaddr_t)add_ten_to_foo, 7);
add_ten_to_foo();
if (foo != 10) {
TC_PRINT("FAIL\n");
} else {
TC_PRINT("PASS\n");
}
}
}
#endif
TC_END_RESULT(rv);
TC_END_REPORT(rv);
}

View file

@ -1,5 +0,0 @@
[test]
tags = kernel core
platform_whitelist = qemu_x86 qemu_cortex_m3
filter = not CONFIG_X86_IAMCU
timeout = 200