Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/iommu/intel_drv.c
/*- | /*- | ||||
* Copyright (c) 2013 The FreeBSD Foundation | * Copyright (c) 2013-2015 The FreeBSD Foundation | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* This software was developed by Konstantin Belousov <kib@FreeBSD.org> | * This software was developed by Konstantin Belousov <kib@FreeBSD.org> | ||||
* under sponsorship from the FreeBSD Foundation. | * under sponsorship from the FreeBSD Foundation. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
Show All 34 Lines | |||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/memdesc.h> | #include <sys/memdesc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/taskqueue.h> | #include <sys/taskqueue.h> | ||||
#include <sys/tree.h> | #include <sys/tree.h> | ||||
#include <sys/vmem.h> | |||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include <contrib/dev/acpica/include/accommon.h> | #include <contrib/dev/acpica/include/accommon.h> | ||||
#include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
#include <vm/vm_kern.h> | #include <vm/vm_kern.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
#include <vm/vm_map.h> | #include <vm/vm_map.h> | ||||
#include <x86/include/busdma_impl.h> | #include <x86/include/busdma_impl.h> | ||||
#include <x86/iommu/intel_reg.h> | #include <x86/iommu/intel_reg.h> | ||||
#include <x86/iommu/busdma_dmar.h> | #include <x86/iommu/busdma_dmar.h> | ||||
#include <x86/iommu/intel_dmar.h> | #include <x86/iommu/intel_dmar.h> | ||||
#include <dev/pci/pcireg.h> | |||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#ifdef DEV_APIC | #ifdef DEV_APIC | ||||
#include "pcib_if.h" | #include "pcib_if.h" | ||||
#endif | #endif | ||||
#define DMAR_FAULT_IRQ_RID 0 | #define DMAR_FAULT_IRQ_RID 0 | ||||
#define DMAR_QI_IRQ_RID 1 | #define DMAR_QI_IRQ_RID 1 | ||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
dmar_release_resources(device_t dev, struct dmar_unit *unit) | dmar_release_resources(device_t dev, struct dmar_unit *unit) | ||||
{ | { | ||||
int i; | int i; | ||||
dmar_fini_busdma(unit); | dmar_fini_busdma(unit); | ||||
dmar_fini_irt(unit); | |||||
dmar_fini_qi(unit); | dmar_fini_qi(unit); | ||||
dmar_fini_fault_log(unit); | dmar_fini_fault_log(unit); | ||||
for (i = 0; i < DMAR_INTR_TOTAL; i++) | for (i = 0; i < DMAR_INTR_TOTAL; i++) | ||||
dmar_release_intr(dev, unit, i); | dmar_release_intr(dev, unit, i); | ||||
if (unit->regs != NULL) { | if (unit->regs != NULL) { | ||||
bus_deactivate_resource(dev, SYS_RES_MEMORY, unit->reg_rid, | bus_deactivate_resource(dev, SYS_RES_MEMORY, unit->reg_rid, | ||||
unit->regs); | unit->regs); | ||||
bus_release_resource(dev, SYS_RES_MEMORY, unit->reg_rid, | bus_release_resource(dev, SYS_RES_MEMORY, unit->reg_rid, | ||||
▲ Show 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = dmar_init_qi(unit); | error = dmar_init_qi(unit); | ||||
if (error != 0) { | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = dmar_init_irt(unit); | |||||
if (error != 0) { | |||||
dmar_release_resources(dev, unit); | |||||
return (error); | |||||
} | |||||
error = dmar_init_busdma(unit); | error = dmar_init_busdma(unit); | ||||
if (error != 0) { | if (error != 0) { | ||||
dmar_release_resources(dev, unit); | dmar_release_resources(dev, unit); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef NOTYET | #ifdef NOTYET | ||||
DMAR_LOCK(unit); | DMAR_LOCK(unit); | ||||
▲ Show 20 Lines • Show All 236 Lines • ▼ Show 20 Lines | for (;;) { | ||||
dmar_dev = dmar_devs[i]; | dmar_dev = dmar_devs[i]; | ||||
goto found; | goto found; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
found: | found: | ||||
return (device_get_softc(dmar_dev)); | return (device_get_softc(dmar_dev)); | ||||
} | |||||
static struct dmar_unit * | |||||
dmar_find_nonpci(u_int id, u_int entry_type, uint16_t *rid) | |||||
{ | |||||
device_t dmar_dev; | |||||
struct dmar_unit *unit; | |||||
ACPI_DMAR_HARDWARE_UNIT *dmarh; | |||||
ACPI_DMAR_DEVICE_SCOPE *devscope; | |||||
ACPI_DMAR_PCI_PATH *path; | |||||
char *ptr, *ptrend; | |||||
int i; | |||||
for (i = 0; i < dmar_devcnt; i++) { | |||||
dmar_dev = dmar_devs[i]; | |||||
if (dmar_dev == NULL) | |||||
continue; | |||||
unit = (struct dmar_unit *)device_get_softc(dmar_dev); | |||||
dmarh = dmar_find_by_index(i); | |||||
if (dmarh == NULL) | |||||
continue; | |||||
ptr = (char *)dmarh + sizeof(*dmarh); | |||||
ptrend = (char *)dmarh + dmarh->Header.Length; | |||||
for (;;) { | |||||
if (ptr >= ptrend) | |||||
break; | |||||
devscope = (ACPI_DMAR_DEVICE_SCOPE *)ptr; | |||||
ptr += devscope->Length; | |||||
if (devscope->EntryType != entry_type) | |||||
continue; | |||||
if (devscope->EnumerationId != id) | |||||
continue; | |||||
if (devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE) | |||||
== 2) { | |||||
if (rid != NULL) { | |||||
path = (ACPI_DMAR_PCI_PATH *) | |||||
(devscope + 1); | |||||
*rid = PCI_RID(devscope->Bus, | |||||
path->Device, path->Function); | |||||
} | |||||
return (unit); | |||||
} else { | |||||
/* XXXKIB */ | |||||
printf( | |||||
"dmar_find_nonpci: id %d type %d path length != 2\n", | |||||
entry_type, id); | |||||
neel: Switch arguments to match the printf string. | |||||
} | |||||
} | |||||
} | |||||
return (NULL); | |||||
} | |||||
struct dmar_unit * | |||||
dmar_find_hpet(device_t dev, uint16_t *rid) | |||||
{ | |||||
ACPI_HANDLE handle; | |||||
uint32_t hpet_id; | |||||
handle = acpi_get_handle(dev); | |||||
if (ACPI_FAILURE(acpi_GetInteger(handle, "_UID", &hpet_id))) | |||||
return (NULL); | |||||
return (dmar_find_nonpci(hpet_id, ACPI_DMAR_SCOPE_TYPE_HPET, rid)); | |||||
} | |||||
struct dmar_unit * | |||||
dmar_find_ioapic(u_int apic_id, uint16_t *rid) | |||||
{ | |||||
return (dmar_find_nonpci(apic_id, ACPI_DMAR_SCOPE_TYPE_IOAPIC, rid)); | |||||
} | } | ||||
struct rmrr_iter_args { | struct rmrr_iter_args { | ||||
struct dmar_ctx *ctx; | struct dmar_ctx *ctx; | ||||
device_t dev; | device_t dev; | ||||
int dev_domain; | int dev_domain; | ||||
int dev_busno; | int dev_busno; | ||||
ACPI_DMAR_PCI_PATH *dev_path; | ACPI_DMAR_PCI_PATH *dev_path; | ||||
▲ Show 20 Lines • Show All 416 Lines • Show Last 20 Lines |
Switch arguments to match the printf string.