Path: blob/master/arch/x86/platform/intel-quark/imr_selftest.c
26481 views
// SPDX-License-Identifier: GPL-2.01/*2* imr_selftest.c -- Intel Isolated Memory Region self-test driver3*4* Copyright(c) 2013 Intel Corporation.5* Copyright(c) 2015 Bryan O'Donoghue <[email protected]>6*7* IMR self test. The purpose of this module is to run a set of tests on the8* IMR API to validate its sanity. We check for overlapping, reserved9* addresses and setup/teardown sanity.10*11*/1213#include <asm-generic/sections.h>14#include <asm/cpu_device_id.h>15#include <asm/imr.h>16#include <asm/io.h>1718#include <linux/init.h>19#include <linux/mm.h>20#include <linux/types.h>2122#define SELFTEST KBUILD_MODNAME ": "23/**24* imr_self_test_result - Print result string for self test.25*26* @res: result code - true if test passed false otherwise.27* @fmt: format string.28* ... variadic argument list.29*/30static __printf(2, 3)31void __init imr_self_test_result(int res, const char *fmt, ...)32{33va_list vlist;3435/* Print pass/fail. */36if (res)37pr_info(SELFTEST "pass ");38else39pr_info(SELFTEST "fail ");4041/* Print variable string. */42va_start(vlist, fmt);43vprintk(fmt, vlist);44va_end(vlist);4546/* Optional warning. */47WARN(res == 0, "test failed");48}49#undef SELFTEST5051/**52* imr_self_test53*54* Verify IMR self_test with some simple tests to verify overlap,55* zero sized allocations and 1 KiB sized areas.56*57*/58static void __init imr_self_test(void)59{60phys_addr_t base = virt_to_phys(&_text);61size_t size = virt_to_phys(&__end_rodata) - base;62const char *fmt_over = "overlapped IMR @ (0x%08lx - 0x%08lx)\n";63int ret;6465/* Test zero zero. */66ret = imr_add_range(0, 0, 0, 0);67imr_self_test_result(ret < 0, "zero sized IMR\n");6869/* Test exact overlap. */70ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);71imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));7273/* Test overlap with base inside of existing. */74base += size - IMR_ALIGN;75ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);76imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));7778/* Test overlap with end inside of existing. */79base -= size + IMR_ALIGN * 2;80ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);81imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));8283/* Test that a 1 KiB IMR @ zero with read/write all will bomb out. */84ret = imr_add_range(0, IMR_ALIGN, IMR_READ_ACCESS_ALL,85IMR_WRITE_ACCESS_ALL);86imr_self_test_result(ret < 0, "1KiB IMR @ 0x00000000 - access-all\n");8788/* Test that a 1 KiB IMR @ zero with CPU only will work. */89ret = imr_add_range(0, IMR_ALIGN, IMR_CPU, IMR_CPU);90imr_self_test_result(ret >= 0, "1KiB IMR @ 0x00000000 - cpu-access\n");91if (ret >= 0) {92ret = imr_remove_range(0, IMR_ALIGN);93imr_self_test_result(ret == 0, "teardown - cpu-access\n");94}9596/* Test 2 KiB works. */97size = IMR_ALIGN * 2;98ret = imr_add_range(0, size, IMR_READ_ACCESS_ALL, IMR_WRITE_ACCESS_ALL);99imr_self_test_result(ret >= 0, "2KiB IMR @ 0x00000000\n");100if (ret >= 0) {101ret = imr_remove_range(0, size);102imr_self_test_result(ret == 0, "teardown 2KiB\n");103}104}105106static const struct x86_cpu_id imr_ids[] __initconst = {107X86_MATCH_VFM(INTEL_QUARK_X1000, NULL),108{}109};110111/**112* imr_self_test_init - entry point for IMR driver.113*114* return: -ENODEV for no IMR support 0 if good to go.115*/116static int __init imr_self_test_init(void)117{118if (x86_match_cpu(imr_ids))119imr_self_test();120return 0;121}122123/**124* imr_self_test_exit - exit point for IMR code.125*126* return:127*/128device_initcall(imr_self_test_init);129130131