0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <asm-generic/sections.h>
0015 #include <asm/cpu_device_id.h>
0016 #include <asm/imr.h>
0017 #include <asm/io.h>
0018
0019 #include <linux/init.h>
0020 #include <linux/mm.h>
0021 #include <linux/types.h>
0022
0023 #define SELFTEST KBUILD_MODNAME ": "
0024
0025
0026
0027
0028
0029
0030
0031 static __printf(2, 3)
0032 void __init imr_self_test_result(int res, const char *fmt, ...)
0033 {
0034 va_list vlist;
0035
0036
0037 if (res)
0038 pr_info(SELFTEST "pass ");
0039 else
0040 pr_info(SELFTEST "fail ");
0041
0042
0043 va_start(vlist, fmt);
0044 vprintk(fmt, vlist);
0045 va_end(vlist);
0046
0047
0048 WARN(res == 0, "test failed");
0049 }
0050 #undef SELFTEST
0051
0052
0053
0054
0055
0056
0057
0058
0059 static void __init imr_self_test(void)
0060 {
0061 phys_addr_t base = virt_to_phys(&_text);
0062 size_t size = virt_to_phys(&__end_rodata) - base;
0063 const char *fmt_over = "overlapped IMR @ (0x%08lx - 0x%08lx)\n";
0064 int ret;
0065
0066
0067 ret = imr_add_range(0, 0, 0, 0);
0068 imr_self_test_result(ret < 0, "zero sized IMR\n");
0069
0070
0071 ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
0072 imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
0073
0074
0075 base += size - IMR_ALIGN;
0076 ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
0077 imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
0078
0079
0080 base -= size + IMR_ALIGN * 2;
0081 ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
0082 imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
0083
0084
0085 ret = imr_add_range(0, IMR_ALIGN, IMR_READ_ACCESS_ALL,
0086 IMR_WRITE_ACCESS_ALL);
0087 imr_self_test_result(ret < 0, "1KiB IMR @ 0x00000000 - access-all\n");
0088
0089
0090 ret = imr_add_range(0, IMR_ALIGN, IMR_CPU, IMR_CPU);
0091 imr_self_test_result(ret >= 0, "1KiB IMR @ 0x00000000 - cpu-access\n");
0092 if (ret >= 0) {
0093 ret = imr_remove_range(0, IMR_ALIGN);
0094 imr_self_test_result(ret == 0, "teardown - cpu-access\n");
0095 }
0096
0097
0098 size = IMR_ALIGN * 2;
0099 ret = imr_add_range(0, size, IMR_READ_ACCESS_ALL, IMR_WRITE_ACCESS_ALL);
0100 imr_self_test_result(ret >= 0, "2KiB IMR @ 0x00000000\n");
0101 if (ret >= 0) {
0102 ret = imr_remove_range(0, size);
0103 imr_self_test_result(ret == 0, "teardown 2KiB\n");
0104 }
0105 }
0106
0107 static const struct x86_cpu_id imr_ids[] __initconst = {
0108 X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL),
0109 {}
0110 };
0111
0112
0113
0114
0115
0116
0117 static int __init imr_self_test_init(void)
0118 {
0119 if (x86_match_cpu(imr_ids))
0120 imr_self_test();
0121 return 0;
0122 }
0123
0124
0125
0126
0127
0128
0129 device_initcall(imr_self_test_init);