| 142 | } |
| 143 | |
| 144 | static inline void |
| 145 | kcsan_access(uintptr_t addr, size_t size, bool write, bool atomic, uintptr_t pc) |
| 146 | { |
| 147 | csan_cell_t old, new; |
| 148 | csan_cpu_t *cpu; |
| 149 | uint64_t intr; |
| 150 | size_t i; |
| 151 | |
| 152 | if (__predict_false(!kcsan_enabled)) |
| 153 | return; |
| 154 | if (__predict_false(kcsan_md_unsupported((vm_offset_t)addr))) |
| 155 | return; |
| 156 | if (KERNEL_PANICKED()) |
| 157 | return; |
| 158 | |
| 159 | new.addr = addr; |
| 160 | new.size = size; |
| 161 | new.write = write; |
| 162 | new.atomic = atomic; |
| 163 | new.pc = pc; |
| 164 | |
| 165 | CPU_FOREACH(i) { |
| 166 | __builtin_memcpy(&old, &kcsan_cpus[i].cell, sizeof(old)); |
| 167 | |
| 168 | if (old.addr + old.size <= new.addr) |
| 169 | continue; |
| 170 | if (new.addr + new.size <= old.addr) |
| 171 | continue; |
| 172 | if (__predict_true(!old.write && !new.write)) |
| 173 | continue; |
| 174 | if (__predict_true(kcsan_access_is_atomic(&new, &old))) |
| 175 | continue; |
| 176 | |
| 177 | kcsan_report(&new, PCPU_GET(cpuid), &old, i); |
| 178 | break; |
| 179 | } |
| 180 | |
| 181 | if (__predict_false(!kcsan_md_is_avail())) |
| 182 | return; |
| 183 | |
| 184 | kcsan_md_disable_intrs(&intr); |
| 185 | |
| 186 | cpu = &kcsan_cpus[PCPU_GET(cpuid)]; |
| 187 | if (__predict_false(!cpu->inited)) |
| 188 | goto out; |
| 189 | cpu->cnt = (cpu->cnt + 1) % KCSAN_NACCESSES; |
| 190 | if (__predict_true(cpu->cnt != 0)) |
| 191 | goto out; |
| 192 | |
| 193 | __builtin_memcpy(&cpu->cell, &new, sizeof(new)); |
| 194 | kcsan_md_delay(KCSAN_DELAY); |
| 195 | __builtin_memset(&cpu->cell, 0, sizeof(new)); |
| 196 | |
| 197 | out: |
| 198 | kcsan_md_enable_intrs(&intr); |
| 199 | } |
| 200 | |
| 201 | #define CSAN_READ(size) \ |
no test coverage detected