0001
0002
0003 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0004
0005 #include <linux/init.h>
0006 #include <linux/sched.h>
0007 #include <linux/kthread.h>
0008 #include <linux/workqueue.h>
0009 #include <linux/memblock.h>
0010
0011 #include <asm/proto.h>
0012 #include <asm/setup.h>
0013
0014
0015
0016
0017
0018
0019
0020 #define MAX_SCAN_AREAS 8
0021
0022 static int __read_mostly memory_corruption_check = -1;
0023
0024 static unsigned __read_mostly corruption_check_size = 64*1024;
0025 static unsigned __read_mostly corruption_check_period = 60;
0026
0027 static struct scan_area {
0028 u64 addr;
0029 u64 size;
0030 } scan_areas[MAX_SCAN_AREAS];
0031 static int num_scan_areas;
0032
0033 static __init int set_corruption_check(char *arg)
0034 {
0035 ssize_t ret;
0036 unsigned long val;
0037
0038 if (!arg) {
0039 pr_err("memory_corruption_check config string not provided\n");
0040 return -EINVAL;
0041 }
0042
0043 ret = kstrtoul(arg, 10, &val);
0044 if (ret)
0045 return ret;
0046
0047 memory_corruption_check = val;
0048
0049 return 0;
0050 }
0051 early_param("memory_corruption_check", set_corruption_check);
0052
0053 static __init int set_corruption_check_period(char *arg)
0054 {
0055 ssize_t ret;
0056 unsigned long val;
0057
0058 if (!arg) {
0059 pr_err("memory_corruption_check_period config string not provided\n");
0060 return -EINVAL;
0061 }
0062
0063 ret = kstrtoul(arg, 10, &val);
0064 if (ret)
0065 return ret;
0066
0067 corruption_check_period = val;
0068 return 0;
0069 }
0070 early_param("memory_corruption_check_period", set_corruption_check_period);
0071
0072 static __init int set_corruption_check_size(char *arg)
0073 {
0074 char *end;
0075 unsigned size;
0076
0077 if (!arg) {
0078 pr_err("memory_corruption_check_size config string not provided\n");
0079 return -EINVAL;
0080 }
0081
0082 size = memparse(arg, &end);
0083
0084 if (*end == '\0')
0085 corruption_check_size = size;
0086
0087 return (size == corruption_check_size) ? 0 : -EINVAL;
0088 }
0089 early_param("memory_corruption_check_size", set_corruption_check_size);
0090
0091
0092 void __init setup_bios_corruption_check(void)
0093 {
0094 phys_addr_t start, end;
0095 u64 i;
0096
0097 if (memory_corruption_check == -1) {
0098 memory_corruption_check =
0099 #ifdef CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK
0100 1
0101 #else
0102 0
0103 #endif
0104 ;
0105 }
0106
0107 if (corruption_check_size == 0)
0108 memory_corruption_check = 0;
0109
0110 if (!memory_corruption_check)
0111 return;
0112
0113 corruption_check_size = round_up(corruption_check_size, PAGE_SIZE);
0114
0115 for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
0116 NULL) {
0117 start = clamp_t(phys_addr_t, round_up(start, PAGE_SIZE),
0118 PAGE_SIZE, corruption_check_size);
0119 end = clamp_t(phys_addr_t, round_down(end, PAGE_SIZE),
0120 PAGE_SIZE, corruption_check_size);
0121 if (start >= end)
0122 continue;
0123
0124 memblock_reserve(start, end - start);
0125 scan_areas[num_scan_areas].addr = start;
0126 scan_areas[num_scan_areas].size = end - start;
0127
0128
0129 memset(__va(start), 0, end - start);
0130
0131 if (++num_scan_areas >= MAX_SCAN_AREAS)
0132 break;
0133 }
0134
0135 if (num_scan_areas)
0136 pr_info("Scanning %d areas for low memory corruption\n", num_scan_areas);
0137 }
0138
0139
0140 static void check_for_bios_corruption(void)
0141 {
0142 int i;
0143 int corruption = 0;
0144
0145 if (!memory_corruption_check)
0146 return;
0147
0148 for (i = 0; i < num_scan_areas; i++) {
0149 unsigned long *addr = __va(scan_areas[i].addr);
0150 unsigned long size = scan_areas[i].size;
0151
0152 for (; size; addr++, size -= sizeof(unsigned long)) {
0153 if (!*addr)
0154 continue;
0155 pr_err("Corrupted low memory at %p (%lx phys) = %08lx\n", addr, __pa(addr), *addr);
0156 corruption = 1;
0157 *addr = 0;
0158 }
0159 }
0160
0161 WARN_ONCE(corruption, KERN_ERR "Memory corruption detected in low memory\n");
0162 }
0163
0164 static void check_corruption(struct work_struct *dummy);
0165 static DECLARE_DELAYED_WORK(bios_check_work, check_corruption);
0166
0167 static void check_corruption(struct work_struct *dummy)
0168 {
0169 check_for_bios_corruption();
0170 schedule_delayed_work(&bios_check_work,
0171 round_jiffies_relative(corruption_check_period*HZ));
0172 }
0173
0174 static int start_periodic_check_for_corruption(void)
0175 {
0176 if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0)
0177 return 0;
0178
0179 pr_info("Scanning for low memory corruption every %d seconds\n", corruption_check_period);
0180
0181
0182 schedule_delayed_work(&bios_check_work, 0);
0183
0184 return 0;
0185 }
0186 device_initcall(start_periodic_check_for_corruption);
0187