| 188 | } |
| 189 | |
| 190 | static void |
| 191 | dmar_fault_task(void *arg, int pending __unused) |
| 192 | { |
| 193 | struct dmar_unit *unit; |
| 194 | struct dmar_ctx *ctx; |
| 195 | uint64_t fault_rec[2]; |
| 196 | int sid, bus, slot, func, faultp; |
| 197 | |
| 198 | unit = arg; |
| 199 | DMAR_FAULT_LOCK(unit); |
| 200 | for (;;) { |
| 201 | faultp = unit->fault_log_tail; |
| 202 | if (faultp == unit->fault_log_head) |
| 203 | break; |
| 204 | |
| 205 | fault_rec[0] = unit->fault_log[faultp]; |
| 206 | fault_rec[1] = unit->fault_log[faultp + 1]; |
| 207 | unit->fault_log_tail = dmar_fault_next(unit, faultp); |
| 208 | DMAR_FAULT_UNLOCK(unit); |
| 209 | |
| 210 | sid = DMAR_FRCD2_SID(fault_rec[1]); |
| 211 | printf("DMAR%d: ", unit->iommu.unit); |
| 212 | DMAR_LOCK(unit); |
| 213 | ctx = dmar_find_ctx_locked(unit, sid); |
| 214 | if (ctx == NULL) { |
| 215 | printf("<unknown dev>:"); |
| 216 | |
| 217 | /* |
| 218 | * Note that the slot and function will not be correct |
| 219 | * if ARI is in use, but without a ctx entry we have |
| 220 | * no way of knowing whether ARI is in use or not. |
| 221 | */ |
| 222 | bus = PCI_RID2BUS(sid); |
| 223 | slot = PCI_RID2SLOT(sid); |
| 224 | func = PCI_RID2FUNC(sid); |
| 225 | } else { |
| 226 | ctx->context.flags |= IOMMU_CTX_FAULTED; |
| 227 | ctx->last_fault_rec[0] = fault_rec[0]; |
| 228 | ctx->last_fault_rec[1] = fault_rec[1]; |
| 229 | device_print_prettyname(ctx->context.tag->owner); |
| 230 | bus = pci_get_bus(ctx->context.tag->owner); |
| 231 | slot = pci_get_slot(ctx->context.tag->owner); |
| 232 | func = pci_get_function(ctx->context.tag->owner); |
| 233 | } |
| 234 | DMAR_UNLOCK(unit); |
| 235 | printf( |
| 236 | "pci%d:%d:%d sid %x fault acc %x adt 0x%x reason 0x%x " |
| 237 | "addr %jx\n", |
| 238 | bus, slot, func, sid, DMAR_FRCD2_T(fault_rec[1]), |
| 239 | DMAR_FRCD2_AT(fault_rec[1]), DMAR_FRCD2_FR(fault_rec[1]), |
| 240 | (uintmax_t)fault_rec[0]); |
| 241 | DMAR_FAULT_LOCK(unit); |
| 242 | } |
| 243 | DMAR_FAULT_UNLOCK(unit); |
| 244 | } |
| 245 | |
| 246 | static void |
| 247 | dmar_clear_faults(struct dmar_unit *unit) |
nothing calls this directly
no test coverage detected