Re: git: 65b133e5d292 - main - x86: allow to have more than one kind of IOMMU
Date: Wed, 04 Sep 2024 23:52:04 UTC
In message <202409042150.484LoeAq031493@gitrepo.freebsd.org>, Konstantin Belous ov writes: > The branch main has been updated by kib: > > URL: https://cgit.FreeBSD.org/src/commit/?id=65b133e5d292686fe20f11dd39b53812 > 226a8684 > > commit 65b133e5d292686fe20f11dd39b53812226a8684 > Author: Konstantin Belousov <kib@FreeBSD.org> > AuthorDate: 2024-05-29 14:38:14 +0000 > Commit: Konstantin Belousov <kib@FreeBSD.org> > CommitDate: 2024-09-04 21:50:18 +0000 > > x86: allow to have more than one kind of IOMMU > > Sponsored by: Advanced Micro Devices (AMD) > Sponsored by: The FreeBSD Foundation > MFC after: 1 week > --- > sys/x86/iommu/intel_ctx.c | 22 +++++------ > sys/x86/iommu/intel_dmar.h | 18 ++++++++- > sys/x86/iommu/intel_drv.c | 30 ++++++++++++-- > sys/x86/iommu/intel_intrmap.c | 10 ++--- > sys/x86/iommu/iommu_utils.c | 91 +++++++++++++++++++++++++++++++++++++++++ > +- > sys/x86/iommu/x86_iommu.h | 25 +++++++++++- > 6 files changed, 173 insertions(+), 23 deletions(-) > > diff --git a/sys/x86/iommu/intel_ctx.c b/sys/x86/iommu/intel_ctx.c > index baee0109e5a9..a3ff35dc527e 100644 > --- a/sys/x86/iommu/intel_ctx.c > +++ b/sys/x86/iommu/intel_ctx.c > @@ -75,6 +75,9 @@ static void dmar_unref_domain_locked(struct dmar_unit *dmar > , > struct dmar_domain *domain); > static void dmar_domain_destroy(struct dmar_domain *domain); > > +static void dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ctx *ct > x); > +static void dmar_free_ctx(struct dmar_ctx *ctx); > + > static void > dmar_ensure_ctx_page(struct dmar_unit *dmar, int bus) > { > @@ -745,7 +748,7 @@ dmar_unref_domain_locked(struct dmar_unit *dmar, struct d > mar_domain *domain) > dmar_domain_destroy(domain); > } > > -void > +static void > dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ctx *ctx) > { > struct sf_buf *sf; > @@ -819,7 +822,7 @@ dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ > ctx *ctx) > TD_PINNED_ASSERT; > } > > -void > +static void > dmar_free_ctx(struct dmar_ctx *ctx) > { > struct dmar_unit *dmar; > @@ -867,7 +870,7 @@ dmar_domain_free_entry(struct iommu_map_entry *entry, boo > l free) > * the entry's dmamap_link field. > */ > void > -iommu_domain_unload_entry(struct iommu_map_entry *entry, bool free, > +dmar_domain_unload_entry(struct iommu_map_entry *entry, bool free, > bool cansleep) > { > struct dmar_domain *domain; > @@ -909,7 +912,7 @@ dmar_domain_unload_emit_wait(struct dmar_domain *domain, > } > > void > -iommu_domain_unload(struct iommu_domain *iodom, > +dmar_domain_unload(struct iommu_domain *iodom, > struct iommu_map_entries_tailq *entries, bool cansleep) > { > struct dmar_domain *domain; > @@ -947,37 +950,34 @@ iommu_domain_unload(struct iommu_domain *iodom, > } > > struct iommu_ctx * > -iommu_get_ctx(struct iommu_unit *iommu, device_t dev, uint16_t rid, > +dmar_get_ctx(struct iommu_unit *iommu, device_t dev, uint16_t rid, > bool id_mapped, bool rmrr_init) > { > struct dmar_unit *dmar; > struct dmar_ctx *ret; > > dmar = IOMMU2DMAR(iommu); > - > ret = dmar_get_ctx_for_dev(dmar, dev, rid, id_mapped, rmrr_init); > - > return (CTX2IOCTX(ret)); > } > > void > -iommu_free_ctx_locked(struct iommu_unit *iommu, struct iommu_ctx *context) > +dmar_free_ctx_locked_method(struct iommu_unit *iommu, > + struct iommu_ctx *context) > { > struct dmar_unit *dmar; > struct dmar_ctx *ctx; > > dmar = IOMMU2DMAR(iommu); > ctx = IOCTX2CTX(context); > - > dmar_free_ctx_locked(dmar, ctx); > } > > void > -iommu_free_ctx(struct iommu_ctx *context) > +dmar_free_ctx_method(struct iommu_ctx *context) > { > struct dmar_ctx *ctx; > > ctx = IOCTX2CTX(context); > - > dmar_free_ctx(ctx); > } > diff --git a/sys/x86/iommu/intel_dmar.h b/sys/x86/iommu/intel_dmar.h > index 4ae005238074..0ede955e12b9 100644 > --- a/sys/x86/iommu/intel_dmar.h > +++ b/sys/x86/iommu/intel_dmar.h > @@ -293,10 +293,17 @@ struct dmar_ctx *dmar_get_ctx_for_devpath(struct dmar_u > nit *dmar, uint16_t rid, > int dev_domain, int dev_busno, const void *dev_path, int dev_path_len, > bool id_mapped, bool rmrr_init); > int dmar_move_ctx_to_domain(struct dmar_domain *domain, struct dmar_ctx *ctx > ); > -void dmar_free_ctx_locked(struct dmar_unit *dmar, struct dmar_ctx *ctx); > -void dmar_free_ctx(struct dmar_ctx *ctx); > +void dmar_free_ctx_locked_method(struct iommu_unit *dmar, > + struct iommu_ctx *ctx); > +void dmar_free_ctx_method(struct iommu_ctx *ctx); > struct dmar_ctx *dmar_find_ctx_locked(struct dmar_unit *dmar, uint16_t rid); > +struct iommu_ctx *dmar_get_ctx(struct iommu_unit *iommu, device_t dev, > + uint16_t rid, bool id_mapped, bool rmrr_init); > void dmar_domain_free_entry(struct iommu_map_entry *entry, bool free); > +void dmar_domain_unload_entry(struct iommu_map_entry *entry, bool free, > + bool cansleep); > +void dmar_domain_unload(struct iommu_domain *iodom, > + struct iommu_map_entries_tailq *entries, bool cansleep); > > void dmar_dev_parse_rmrr(struct dmar_domain *domain, int dev_domain, > int dev_busno, const void *dev_path, int dev_path_len, > @@ -308,6 +315,13 @@ void dmar_quirks_pre_use(struct iommu_unit *dmar); > > int dmar_init_irt(struct dmar_unit *unit); > void dmar_fini_irt(struct dmar_unit *unit); > +int dmar_alloc_msi_intr(device_t src, u_int *cookies, u_int count); > +int dmar_map_msi_intr(device_t src, u_int cpu, u_int vector, u_int cookie, > + uint64_t *addr, uint32_t *data); > +int dmar_unmap_msi_intr(device_t src, u_int cookie); > +int dmar_map_ioapic_intr(u_int ioapic_id, u_int cpu, u_int vector, bool edge > , > + bool activehi, int irq, u_int *cookie, uint32_t *hi, uint32_t *lo); > +int dmar_unmap_ioapic_intr(u_int ioapic_id, u_int *cookie); > > extern int haw; > extern int dmar_batch_coalesce; > diff --git a/sys/x86/iommu/intel_drv.c b/sys/x86/iommu/intel_drv.c > index 636534173715..79350358cced 100644 > --- a/sys/x86/iommu/intel_drv.c > +++ b/sys/x86/iommu/intel_drv.c > @@ -64,6 +64,8 @@ > #include <dev/pci/pcivar.h> > #include <machine/bus.h> > #include <machine/pci_cfgreg.h> > +#include <machine/md_var.h> > +#include <machine/cputypes.h> > #include <x86/include/busdma_impl.h> > #include <dev/iommu/busdma_iommu.h> > #include <x86/iommu/intel_reg.h> > @@ -1357,12 +1359,34 @@ DB_SHOW_ALL_COMMAND(dmars, db_show_all_dmars) > } > #endif > > -struct iommu_unit * > -iommu_find(device_t dev, bool verbose) > +static struct iommu_unit * > +dmar_find_method(device_t dev, bool verbose) > { > struct dmar_unit *dmar; > > dmar = dmar_find(dev, verbose); > - > return (&dmar->iommu); > } > + > +static struct x86_iommu dmar_x86_iommu = { > + .domain_unload_entry = dmar_domain_unload_entry, > + .domain_unload = dmar_domain_unload, > + .get_ctx = dmar_get_ctx, > + .free_ctx_locked = dmar_free_ctx_locked_method, > + .free_ctx = dmar_free_ctx_method, > + .find = dmar_find_method, > + .alloc_msi_intr = dmar_alloc_msi_intr, > + .map_msi_intr = dmar_map_msi_intr, > + .unmap_msi_intr = dmar_unmap_msi_intr, > + .map_ioapic_intr = dmar_map_ioapic_intr, > + .unmap_ioapic_intr = dmar_unmap_ioapic_intr, > +}; > + > +static void > +x86_iommu_set_intel(void *arg __unused) > +{ > + if (cpu_vendor_id == CPU_VENDOR_INTEL) > + set_x86_iommu(&dmar_x86_iommu); > +} > + > +SYSINIT(x86_iommu, SI_SUB_TUNABLES, SI_ORDER_ANY, x86_iommu_set_intel, NULL) > ; > diff --git a/sys/x86/iommu/intel_intrmap.c b/sys/x86/iommu/intel_intrmap.c > index 22fd51bc8be9..a6979a9d2501 100644 > --- a/sys/x86/iommu/intel_intrmap.c > +++ b/sys/x86/iommu/intel_intrmap.c > @@ -65,7 +65,7 @@ static void dmar_ir_program_irte(struct dmar_unit *unit, u_ > int idx, > static int dmar_ir_free_irte(struct dmar_unit *unit, u_int cookie); > > int > -iommu_alloc_msi_intr(device_t src, u_int *cookies, u_int count) > +dmar_alloc_msi_intr(device_t src, u_int *cookies, u_int count) > { > struct dmar_unit *unit; > vmem_addr_t vmem_res; > @@ -93,7 +93,7 @@ iommu_alloc_msi_intr(device_t src, u_int *cookies, u_int co > unt) > } > > int > -iommu_map_msi_intr(device_t src, u_int cpu, u_int vector, u_int cookie, > +dmar_map_msi_intr(device_t src, u_int cpu, u_int vector, u_int cookie, > uint64_t *addr, uint32_t *data) > { > struct dmar_unit *unit; > @@ -139,7 +139,7 @@ iommu_map_msi_intr(device_t src, u_int cpu, u_int vector, > u_int cookie, > } > > int > -iommu_unmap_msi_intr(device_t src, u_int cookie) > +dmar_unmap_msi_intr(device_t src, u_int cookie) > { > struct dmar_unit *unit; > > @@ -150,7 +150,7 @@ iommu_unmap_msi_intr(device_t src, u_int cookie) > } > > int > -iommu_map_ioapic_intr(u_int ioapic_id, u_int cpu, u_int vector, bool edge, > +dmar_map_ioapic_intr(u_int ioapic_id, u_int cpu, u_int vector, bool edge, > bool activehi, int irq, u_int *cookie, uint32_t *hi, uint32_t *lo) > { > struct dmar_unit *unit; > @@ -213,7 +213,7 @@ iommu_map_ioapic_intr(u_int ioapic_id, u_int cpu, u_int v > ector, bool edge, > } > > int > -iommu_unmap_ioapic_intr(u_int ioapic_id, u_int *cookie) > +dmar_unmap_ioapic_intr(u_int ioapic_id, u_int *cookie) > { > struct dmar_unit *unit; > u_int idx; > diff --git a/sys/x86/iommu/iommu_utils.c b/sys/x86/iommu/iommu_utils.c > index ffea1cc1a190..ea2c0358e072 100644 > --- a/sys/x86/iommu/iommu_utils.c > +++ b/sys/x86/iommu/iommu_utils.c > @@ -1,7 +1,7 @@ > /*- > * SPDX-License-Identifier: BSD-2-Clause > * > - * Copyright (c) 2013, 2014 The FreeBSD Foundation > + * Copyright (c) 2013, 2014, 2024 The FreeBSD Foundation > * > * This software was developed by Konstantin Belousov <kib@FreeBSD.org> > * under sponsorship from the FreeBSD Foundation. > @@ -50,6 +50,7 @@ > #include <dev/iommu/busdma_iommu.h> > #include <dev/iommu/iommu.h> > #include <x86/iommu/x86_iommu.h> > +#include <x86/iommu/iommu_intrmap.h> > > vm_page_t > iommu_pgalloc(vm_object_t obj, vm_pindex_t idx, int flags) > @@ -162,3 +163,91 @@ SYSCTL_NODE(_hw_iommu, OID_AUTO, dmar, CTLFLAG_RD | CTLF > LAG_MPSAFE, > SYSCTL_INT(_hw_iommu_dmar, OID_AUTO, tbl_pagecnt, CTLFLAG_RD, > &iommu_tbl_pagecnt, 0, > "Count of pages used for DMAR pagetables"); > + > +static struct x86_iommu *x86_iommu; > + > +void > +set_x86_iommu(struct x86_iommu *x) > +{ > + MPASS(x86_iommu == NULL); > + x86_iommu = x; > +} > + > +struct x86_iommu * > +get_x86_iommu(void) > +{ > + return (x86_iommu); > +} > + > +void > +iommu_domain_unload_entry(struct iommu_map_entry *entry, bool free, > + bool cansleep) > +{ > + x86_iommu->domain_unload_entry(entry, free, cansleep); > +} > + > +void > +iommu_domain_unload(struct iommu_domain *iodom, > + struct iommu_map_entries_tailq *entries, bool cansleep) > +{ > + x86_iommu->domain_unload(iodom, entries, cansleep); > +} > + > +struct iommu_ctx * > +iommu_get_ctx(struct iommu_unit *iommu, device_t dev, uint16_t rid, > + bool id_mapped, bool rmrr_init) > +{ > + return (x86_iommu->get_ctx(iommu, dev, rid, id_mapped, rmrr_init)); > +} > + > +void > +iommu_free_ctx_locked(struct iommu_unit *iommu, struct iommu_ctx *context) > +{ > + x86_iommu->free_ctx_locked(iommu, context); > +} > + > +void > +iommu_free_ctx(struct iommu_ctx *context) > +{ > + x86_iommu->free_ctx(context); > +} > + > +struct iommu_unit * > +iommu_find(device_t dev, bool verbose) > +{ > + return (x86_iommu->find(dev, verbose)); > +} > + > +int > +iommu_alloc_msi_intr(device_t src, u_int *cookies, u_int count) > +{ > + return (x86_iommu->alloc_msi_intr(src, cookies, count)); > +} > + > +int > +iommu_map_msi_intr(device_t src, u_int cpu, u_int vector, u_int cookie, > + uint64_t *addr, uint32_t *data) > +{ > + return (x86_iommu->map_msi_intr(src, cpu, vector, cookie, > + addr, data)); > +} > + > +int > +iommu_unmap_msi_intr(device_t src, u_int cookie) > +{ > + return (x86_iommu->unmap_msi_intr(src, cookie)); > +} > + > +int > +iommu_map_ioapic_intr(u_int ioapic_id, u_int cpu, u_int vector, bool edge, > + bool activehi, int irq, u_int *cookie, uint32_t *hi, uint32_t *lo) > +{ > + return (x86_iommu->map_ioapic_intr(ioapic_id, cpu, vector, edge, > + activehi, irq, cookie, hi, lo)); > +} > + > +int > +iommu_unmap_ioapic_intr(u_int ioapic_id, u_int *cookie) > +{ > + return (x86_iommu->unmap_ioapic_intr(ioapic_id, cookie)); > +} > diff --git a/sys/x86/iommu/x86_iommu.h b/sys/x86/iommu/x86_iommu.h > index 3789586f1eaf..8c908964acd0 100644 > --- a/sys/x86/iommu/x86_iommu.h > +++ b/sys/x86/iommu/x86_iommu.h > @@ -1,7 +1,7 @@ > /*- > * SPDX-License-Identifier: BSD-2-Clause > * > - * Copyright (c) 2013-2015 The FreeBSD Foundation > + * Copyright (c) 2013-2015, 2024 The FreeBSD Foundation > * > * This software was developed by Konstantin Belousov <kib@FreeBSD.org> > * under sponsorship from the FreeBSD Foundation. > @@ -59,4 +59,27 @@ extern int iommu_tbl_pagecnt; > SYSCTL_DECL(_hw_iommu); > SYSCTL_DECL(_hw_iommu_dmar); > > +struct x86_iommu { > + void (*domain_unload_entry)(struct iommu_map_entry *entry, bool free, > + bool cansleep); > + void (*domain_unload)(struct iommu_domain *iodom, > + struct iommu_map_entries_tailq *entries, bool cansleep); > + struct iommu_ctx *(*get_ctx)(struct iommu_unit *iommu, > + device_t dev, uint16_t rid, bool id_mapped, bool rmrr_init); > + void (*free_ctx_locked)(struct iommu_unit *iommu, > + struct iommu_ctx *context); > + void (*free_ctx)(struct iommu_ctx *context); > + struct iommu_unit *(*find)(device_t dev, bool verbose); > + int (*alloc_msi_intr)(device_t src, u_int *cookies, u_int count); > + int (*map_msi_intr)(device_t src, u_int cpu, u_int vector, > + u_int cookie, uint64_t *addr, uint32_t *data); > + int (*unmap_msi_intr)(device_t src, u_int cookie); > + int (*map_ioapic_intr)(u_int ioapic_id, u_int cpu, u_int vector, > + bool edge, bool activehi, int irq, u_int *cookie, uint32_t *hi, > + uint32_t *lo); > + int (*unmap_ioapic_intr)(u_int ioapic_id, u_int *cookie); > +}; > +void set_x86_iommu(struct x86_iommu *); > +struct x86_iommu *get_x86_iommu(void); > + > #endif > I suspect this commit but could be one of the others that caused this panic during intialization. From a serial console log: Hit [Enter] to boot immediately, or any other key for command prompt. Booting [/boot/kernel/kernel] in 10 seconds... ^MBooting [/boot/kernel/kernel] in 9 seconds... ^MBooting [/boot/kernel/kernel]... ^M \^HGDB: no debug ports present KDB: debugger backends: ddb KDB: current backend: ddb ---<<BOOT>>--- Copyright (c) 1992-2024 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 15.0-CURRENT #60 komquats-n272059-e28ee29d2d13: Wed Sep 4 15:07:36 PDT 2024 root@cwsys:/export/obj/opt/src/git-src/amd64.amd64/sys/BREAK amd64 FreeBSD clang version 18.1.6 (https://github.com/llvm/llvm-project.git llvmorg-18.1.6-0-g1118c2e05e67) VT(vga): text 80x25 CPU: AMD Processor model unknown (3000.06-MHz K8-class CPU) Origin="AuthenticAMD" Id=0x100f43 Family=0x10 Model=0x4 Stepping=3 Features=0x178bfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,M CA,CMOV,PAT,PSE36,CLFLUSH,MMX,FXSR,SSE,SSE2,HTT> Features2=0x802009<SSE3,MON,CX16,POPCNT> AMD Features=0xee500800<SYSCALL,NX,MMX+,FFXSR,Page1GB,RDTSCP,LM,3DNow!+,3D Now!> AMD Features2=0x37ff<LAHF,CMP,SVM,ExtAPIC,CR8,ABM,SSE4A,MAS,Prefetch,OSVW, IBS,SKINIT,WDT> SVM: NP,NRIP,NAsids=64 TSC: P-state invariant real memory = 8589934592 (8192 MB) avail memory = 8145883136 (7768 MB) Event timer "LAPIC" quality 100 ACPI APIC Table: <ATI ASUSACPI> FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs FreeBSD/SMP: 1 package(s) x 4 core(s) random: unblocking device. Firmware Warning (ACPI): 32/64X length mismatch in FADT/Pm1aEventBlock: 32/8 (20230628/tbfadt-748) Firmware Warning (ACPI): 32/64X length mismatch in FADT/Pm1aControlBlock: 16/8 (20230628/tbfadt-748) Firmware Warning (ACPI): 32/64X length mismatch in FADT/PmTimerBlock: 32/8 (20230628/tbfadt-748) Firmware Warning (ACPI): 32/64X length mismatch in FADT/Gpe0Block: 64/8 (20230628/tbfadt-748) Firmware Warning (ACPI): Invalid length for FADT/Pm1aEventBlock: 8, using default 32 (20230628/tbfadt-850) Firmware Warning (ACPI): Invalid length for FADT/Pm1aControlBlock: 8, using default 16 (20230628/tbfadt-850) Firmware Warning (ACPI): Invalid length for FADT/PmTimerBlock: 8, using default 32 (20230628/tbfadt-850) ioapic0: MADT APIC ID 4 != hw id 0 kernel trap 12 with interrupts disabled Fatal trap 12: page fault while in kernel mode cpuid = 0; apic id = 00 fault virtual address = 0x78 fault code = supervisor read data, page not present instruction pointer = 0x20:0xffffffff80a2c48b stack pointer = 0x28:0xffffffff81f05e90 frame pointer = 0x28:0xffffffff81f05e90 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = resume, IOPL = 0 current process = 0 (swapper) rdi: 0000000000000004 rsi: 0000000000000000 rdx: 0000000000000000 rcx: 0000000000000001 r8: 0000000000000001 r9: 00000000ffffffff rax: 0000000000000000 rbx: fffff800fec00000 rbp: ffffffff81f05e90 r10: 0000000000000000 r11: 00000000fff5cfdf r12: 0000000000000010 r13: fffff800033aa8ec r14: fffff800033aa8e4 r15: 0000000000000000 trap number = 12 panic: page fault cpuid = 0 time = 1 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xffffffff81f05b80 vpanic() at vpanic+0x13f/frame 0xffffffff81f05cb0 panic() at panic+0x43/frame 0xffffffff81f05d10 trap_fatal() at trap_fatal+0x40b/frame 0xffffffff81f05d70 trap_pfault() at trap_pfault+0x46/frame 0xffffffff81f05dc0 calltrap() at calltrap+0x8/frame 0xffffffff81f05dc0 --- trap 0xc, rip = 0xffffffff80a2c48b, rsp = 0xffffffff81f05e90, rbp = 0xffffffff81f05e90 --- iommu_map_ioapic_intr() at iommu_map_ioapic_intr+0xb/frame 0xffffffff81f05e90 ioapic_create() at ioapic_create+0x460/frame 0xffffffff81f05f20 madt_parse_apics() at madt_parse_apics+0x51/frame 0xffffffff81f05f40 acpi_walk_subtables() at acpi_walk_subtables+0x31/frame 0xffffffff81f05f70 madt_setup_io() at madt_setup_io+0x62/frame 0xffffffff81f05f90 apic_setup_io() at apic_setup_io+0x24/frame 0xffffffff81f05fa0 mi_startup() at mi_startup+0x1c8/frame 0xffffffff81f05ff0 Uptime: 1s Automatic reboot in 15 seconds - press a key on the console to abort --> Press a key on the console to reboot, --> or switch off the system now. Rebooting... -- Cheers, Cy Schubert <Cy.Schubert@cschubert.com> FreeBSD UNIX: <cy@FreeBSD.org> Web: https://FreeBSD.org NTP: <cy@nwtime.org> Web: https://nwtime.org e^(i*pi)+1=0