Module Name: src Committed By: jmcneill Date: Sat Nov 10 11:46:31 UTC 2018
Modified Files: src/sys/arch/arm/cortex: gicv3.c gicv3.h gicv3_its.c gicv3_its.h Log Message: Implement pic_get_affinity/pic_set_affinity for LPIs via ITS To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/cortex/gicv3.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/cortex/gicv3.h cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/cortex/gicv3_its.c \ src/sys/arch/arm/cortex/gicv3_its.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/cortex/gicv3.c diff -u src/sys/arch/arm/cortex/gicv3.c:1.6 src/sys/arch/arm/cortex/gicv3.c:1.7 --- src/sys/arch/arm/cortex/gicv3.c:1.6 Sat Nov 10 01:56:28 2018 +++ src/sys/arch/arm/cortex/gicv3.c Sat Nov 10 11:46:31 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.c,v 1.6 2018/11/10 01:56:28 jmcneill Exp $ */ +/* $NetBSD: gicv3.c,v 1.7 2018/11/10 11:46:31 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.6 2018/11/10 01:56:28 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.7 2018/11/10 11:46:31 jmcneill Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -556,7 +556,7 @@ static void gicv3_lpi_cpu_init(struct pic_softc *pic, struct cpu_info *ci) { struct gicv3_softc * const sc = LPITOSOFTC(pic); - struct gicv3_cpu_init *cpu_init; + struct gicv3_lpi_callback *cb; uint32_t ctlr; /* If physical LPIs are not supported on this redistributor, just return. */ @@ -594,16 +594,46 @@ gicv3_lpi_cpu_init(struct pic_softc *pic arm_dsb(); /* Setup ITS if present */ - LIST_FOREACH(cpu_init, &sc->sc_cpu_init, list) - cpu_init->func(cpu_init->arg, ci); + LIST_FOREACH(cb, &sc->sc_lpi_callbacks, list) + cb->cpu_init(cb->priv, ci); } +#ifdef MULTIPROCESSOR +static void +gicv3_lpi_get_affinity(struct pic_softc *pic, size_t irq, kcpuset_t *affinity) +{ + struct gicv3_softc * const sc = LPITOSOFTC(pic); + struct gicv3_lpi_callback *cb; + + LIST_FOREACH(cb, &sc->sc_lpi_callbacks, list) + cb->get_affinity(cb->priv, irq, affinity); +} + +static int +gicv3_lpi_set_affinity(struct pic_softc *pic, size_t irq, const kcpuset_t *affinity) +{ + struct gicv3_softc * const sc = LPITOSOFTC(pic); + struct gicv3_lpi_callback *cb; + int error = EINVAL; + + LIST_FOREACH(cb, &sc->sc_lpi_callbacks, list) { + error = cb->set_affinity(cb->priv, irq, affinity); + if (error) + return error; + } + + return error; +} +#endif + static const struct pic_ops gicv3_lpiops = { .pic_unblock_irqs = gicv3_lpi_unblock_irqs, .pic_block_irqs = gicv3_lpi_block_irqs, .pic_establish_irq = gicv3_lpi_establish_irq, #ifdef MULTIPROCESSOR .pic_cpu_init = gicv3_lpi_cpu_init, + .pic_get_affinity = gicv3_lpi_get_affinity, + .pic_set_affinity = gicv3_lpi_set_affinity, #endif }; @@ -695,7 +725,7 @@ gicv3_init(struct gicv3_softc *sc) KASSERT(CPU_IS_PRIMARY(curcpu())); - LIST_INIT(&sc->sc_cpu_init); + LIST_INIT(&sc->sc_lpi_callbacks); for (n = 0; n < MAXCPUS; n++) sc->sc_irouter[n] = UINT64_MAX; Index: src/sys/arch/arm/cortex/gicv3.h diff -u src/sys/arch/arm/cortex/gicv3.h:1.3 src/sys/arch/arm/cortex/gicv3.h:1.4 --- src/sys/arch/arm/cortex/gicv3.h:1.3 Sat Nov 10 01:56:28 2018 +++ src/sys/arch/arm/cortex/gicv3.h Sat Nov 10 11:46:31 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.h,v 1.3 2018/11/10 01:56:28 jmcneill Exp $ */ +/* $NetBSD: gicv3.h,v 1.4 2018/11/10 11:46:31 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -38,11 +38,14 @@ struct gicv3_dma { bus_size_t len; }; -struct gicv3_cpu_init { - void (*func)(void *, struct cpu_info *ci); - void *arg; +struct gicv3_lpi_callback { + void (*cpu_init)(void *, struct cpu_info *); + void (*get_affinity)(void *, size_t, kcpuset_t *); + int (*set_affinity)(void *, size_t, const kcpuset_t *); - LIST_ENTRY(gicv3_cpu_init) list; + void *priv; + + LIST_ENTRY(gicv3_lpi_callback) list; }; struct gicv3_softc { @@ -69,8 +72,8 @@ struct gicv3_softc { /* Unique identifier for PEs */ u_int sc_processor_id[MAXCPUS]; - /* CPU init callbacks */ - LIST_HEAD(, gicv3_cpu_init) sc_cpu_init; + /* Callbacks */ + LIST_HEAD(, gicv3_lpi_callback) sc_lpi_callbacks; }; int gicv3_init(struct gicv3_softc *); Index: src/sys/arch/arm/cortex/gicv3_its.c diff -u src/sys/arch/arm/cortex/gicv3_its.c:1.1 src/sys/arch/arm/cortex/gicv3_its.c:1.2 --- src/sys/arch/arm/cortex/gicv3_its.c:1.1 Fri Nov 9 23:36:24 2018 +++ src/sys/arch/arm/cortex/gicv3_its.c Sat Nov 10 11:46:31 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3_its.c,v 1.1 2018/11/09 23:36:24 jmcneill Exp $ */ +/* $NetBSD: gicv3_its.c,v 1.2 2018/11/10 11:46:31 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.1 2018/11/09 23:36:24 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.2 2018/11/10 11:46:31 jmcneill Exp $"); #include <sys/param.h> #include <sys/kmem.h> @@ -156,6 +156,23 @@ gits_command_mapi(struct gicv3_its *its, } static inline void +gits_command_movi(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid, uint16_t icid) +{ + struct gicv3_its_command cmd; + + /* + * Update the ICID field in the ITT entry for the event defined by DeviceID and + * EventID. + */ + memset(&cmd, 0, sizeof(cmd)); + cmd.dw[0] = GITS_CMD_MOVI | ((uint64_t)deviceid << 32); + cmd.dw[1] = eventid; + cmd.dw[2] = icid; + + gits_command(its, &cmd); +} + +static inline void gits_command_inv(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid) { struct gicv3_its_command cmd; @@ -379,8 +396,8 @@ gicv3_its_msi_alloc(struct arm_pci_msi * const struct pci_attach_args *pa, bool exact) { struct gicv3_its * const its = msi->msi_priv; + struct cpu_info * const ci = cpu_lookup(0); struct gicv3_its_device *dev; - struct cpu_info *ci = curcpu(); /* XXX */ pci_intr_handle_t *vectors; int n, off; @@ -412,6 +429,11 @@ gicv3_its_msi_alloc(struct arm_pci_msi * gicv3_its_msi_enable(its, lpi); /* + * Record target PE + */ + its->its_targets[lpi - its->its_pic->pic_irqbase] = ci; + + /* * Map event */ gits_command_mapi(its, devid, lpi, cpu_index(ci)); @@ -427,8 +449,8 @@ gicv3_its_msix_alloc(struct arm_pci_msi const struct pci_attach_args *pa, bool exact) { struct gicv3_its * const its = msi->msi_priv; + struct cpu_info *ci = cpu_lookup(0); struct gicv3_its_device *dev; - struct cpu_info *ci = curcpu(); /* XXX */ pci_intr_handle_t *vectors; bus_space_tag_t bst; bus_space_handle_t bsh; @@ -479,6 +501,11 @@ gicv3_its_msix_alloc(struct arm_pci_msi gicv3_its_msix_enable(its, lpi, msix_vec, bst, bsh); /* + * Record target PE + */ + its->its_targets[lpi - its->its_pic->pic_irqbase] = ci; + + /* * Map event */ gits_command_mapi(its, devid, lpi, cpu_index(ci)); @@ -531,6 +558,7 @@ gicv3_its_msi_intr_release(struct arm_pc if (pih[n] & ARM_PCI_INTR_MSI) gicv3_its_msi_disable(its, lpi); gicv3_its_msi_free_lpi(its, lpi); + its->its_targets[lpi - its->its_pic->pic_irqbase] = NULL; struct intrsource * const is = its->its_pic->pic_sources[lpi - its->its_pic->pic_irqbase]; if (is != NULL) @@ -658,6 +686,44 @@ gicv3_its_cpu_init(void *priv, struct cp gits_wait(its); } +static void +gicv3_its_get_affinity(void *priv, size_t irq, kcpuset_t *affinity) +{ + struct gicv3_its * const its = priv; + struct cpu_info *ci; + + kcpuset_zero(affinity); + ci = its->its_targets[irq - its->its_pic->pic_irqbase]; + if (ci) + kcpuset_set(affinity, cpu_index(ci)); +} + +static int +gicv3_its_set_affinity(void *priv, size_t irq, const kcpuset_t *affinity) +{ + struct gicv3_its * const its = priv; + const struct pci_attach_args *pa; + struct cpu_info *ci; + + const int set = kcpuset_countset(affinity); + if (set != 1) + return EINVAL; + + pa = its->its_pa[irq - its->its_pic->pic_irqbase]; + if (pa == NULL) + return EINVAL; + + ci = cpu_lookup(kcpuset_ffs(affinity)); + + const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); + gits_command_movi(its, devid, devid, cpu_index(ci)); + gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); + + its->its_targets[irq - its->its_pic->pic_irqbase] = ci; + + return 0; +} + int gicv3_its_init(struct gicv3_softc *sc, bus_space_handle_t bsh, uint64_t its_base, uint32_t its_id) @@ -678,11 +744,14 @@ gicv3_its_init(struct gicv3_softc *sc, b its->its_pic = &sc->sc_lpi; KASSERT(its->its_pic->pic_maxsources > 0); its->its_pa = kmem_zalloc(sizeof(struct pci_attach_args *) * its->its_pic->pic_maxsources, KM_SLEEP); + its->its_targets = kmem_zalloc(sizeof(struct cpu_info *) * its->its_pic->pic_maxsources, KM_SLEEP); its->its_gic = sc; - its->its_init.func = gicv3_its_cpu_init; - its->its_init.arg = its; + its->its_cb.cpu_init = gicv3_its_cpu_init; + its->its_cb.get_affinity = gicv3_its_get_affinity; + its->its_cb.set_affinity = gicv3_its_set_affinity; + its->its_cb.priv = its; LIST_INIT(&its->its_devices); - LIST_INSERT_HEAD(&sc->sc_cpu_init, &its->its_init, list); + LIST_INSERT_HEAD(&sc->sc_lpi_callbacks, &its->its_cb, list); gicv3_its_command_init(sc, its); gicv3_its_table_init(sc, its); Index: src/sys/arch/arm/cortex/gicv3_its.h diff -u src/sys/arch/arm/cortex/gicv3_its.h:1.1 src/sys/arch/arm/cortex/gicv3_its.h:1.2 --- src/sys/arch/arm/cortex/gicv3_its.h:1.1 Fri Nov 9 23:36:24 2018 +++ src/sys/arch/arm/cortex/gicv3_its.h Sat Nov 10 11:46:31 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3_its.h,v 1.1 2018/11/09 23:36:24 jmcneill Exp $ */ +/* $NetBSD: gicv3_its.h,v 1.2 2018/11/10 11:46:31 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -52,10 +52,11 @@ struct gicv3_its { uint64_t its_rdbase[MAXCPUS]; struct gicv3_softc *its_gic; - struct gicv3_cpu_init its_init; + struct gicv3_lpi_callback its_cb; struct pic_softc *its_pic; const struct pci_attach_args **its_pa; + struct cpu_info **its_targets; LIST_HEAD(, gicv3_its_device) its_devices;