| 231 | } |
| 232 | |
| 233 | static int |
| 234 | domain_init_rmrr(struct dmar_domain *domain, device_t dev, int bus, |
| 235 | int slot, int func, int dev_domain, int dev_busno, |
| 236 | const void *dev_path, int dev_path_len) |
| 237 | { |
| 238 | struct iommu_map_entries_tailq rmrr_entries; |
| 239 | struct iommu_map_entry *entry, *entry1; |
| 240 | vm_page_t *ma; |
| 241 | iommu_gaddr_t start, end; |
| 242 | vm_pindex_t size, i; |
| 243 | int error, error1; |
| 244 | |
| 245 | error = 0; |
| 246 | TAILQ_INIT(&rmrr_entries); |
| 247 | dmar_dev_parse_rmrr(domain, dev_domain, dev_busno, dev_path, |
| 248 | dev_path_len, &rmrr_entries); |
| 249 | TAILQ_FOREACH_SAFE(entry, &rmrr_entries, unroll_link, entry1) { |
| 250 | /* |
| 251 | * VT-d specification requires that the start of an |
| 252 | * RMRR entry is 4k-aligned. Buggy BIOSes put |
| 253 | * anything into the start and end fields. Truncate |
| 254 | * and round as neccesary. |
| 255 | * |
| 256 | * We also allow the overlapping RMRR entries, see |
| 257 | * iommu_gas_alloc_region(). |
| 258 | */ |
| 259 | start = entry->start; |
| 260 | end = entry->end; |
| 261 | if (bootverbose) |
| 262 | printf("dmar%d ctx pci%d:%d:%d RMRR [%#jx, %#jx]\n", |
| 263 | domain->iodom.iommu->unit, bus, slot, func, |
| 264 | (uintmax_t)start, (uintmax_t)end); |
| 265 | entry->start = trunc_page(start); |
| 266 | entry->end = round_page(end); |
| 267 | if (entry->start == entry->end) { |
| 268 | /* Workaround for some AMI (?) BIOSes */ |
| 269 | if (bootverbose) { |
| 270 | if (dev != NULL) |
| 271 | device_printf(dev, ""); |
| 272 | printf("pci%d:%d:%d ", bus, slot, func); |
| 273 | printf("BIOS bug: dmar%d RMRR " |
| 274 | "region (%jx, %jx) corrected\n", |
| 275 | domain->iodom.iommu->unit, start, end); |
| 276 | } |
| 277 | entry->end += DMAR_PAGE_SIZE * 0x20; |
| 278 | } |
| 279 | size = OFF_TO_IDX(entry->end - entry->start); |
| 280 | ma = malloc(sizeof(vm_page_t) * size, M_TEMP, M_WAITOK); |
| 281 | for (i = 0; i < size; i++) { |
| 282 | ma[i] = vm_page_getfake(entry->start + PAGE_SIZE * i, |
| 283 | VM_MEMATTR_DEFAULT); |
| 284 | } |
| 285 | error1 = iommu_gas_map_region(DOM2IODOM(domain), entry, |
| 286 | IOMMU_MAP_ENTRY_READ | IOMMU_MAP_ENTRY_WRITE, |
| 287 | IOMMU_MF_CANWAIT | IOMMU_MF_RMRR, ma); |
| 288 | /* |
| 289 | * Non-failed RMRR entries are owned by context rb |
| 290 | * tree. Get rid of the failed entry, but do not stop |
no test coverage detected