version 1.32.2.5, 2018/11/26 01:52:18 |
version 1.33, 2018/04/01 04:35:04 |
Line 43 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 43 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/evcnt.h> |
#include <sys/evcnt.h> |
#include <sys/intr.h> |
#include <sys/intr.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
#include <sys/atomic.h> |
|
|
|
#include <arm/armreg.h> |
#include <arm/armreg.h> |
#include <arm/atomic.h> |
#include <arm/atomic.h> |
Line 76 static void armgic_source_name(struct pi |
|
Line 75 static void armgic_source_name(struct pi |
|
#ifdef MULTIPROCESSOR |
#ifdef MULTIPROCESSOR |
static void armgic_cpu_init(struct pic_softc *, struct cpu_info *); |
static void armgic_cpu_init(struct pic_softc *, struct cpu_info *); |
static void armgic_ipi_send(struct pic_softc *, const kcpuset_t *, u_long); |
static void armgic_ipi_send(struct pic_softc *, const kcpuset_t *, u_long); |
static void armgic_get_affinity(struct pic_softc *, size_t, kcpuset_t *); |
|
static int armgic_set_affinity(struct pic_softc *, size_t, const kcpuset_t *); |
|
#endif |
#endif |
|
|
static const struct pic_ops armgic_picops = { |
static const struct pic_ops armgic_picops = { |
Line 91 static const struct pic_ops armgic_picop |
|
Line 88 static const struct pic_ops armgic_picop |
|
#ifdef MULTIPROCESSOR |
#ifdef MULTIPROCESSOR |
.pic_cpu_init = armgic_cpu_init, |
.pic_cpu_init = armgic_cpu_init, |
.pic_ipi_send = armgic_ipi_send, |
.pic_ipi_send = armgic_ipi_send, |
.pic_get_affinity = armgic_get_affinity, |
|
.pic_set_affinity = armgic_set_affinity, |
|
#endif |
#endif |
}; |
}; |
|
|
Line 109 static struct armgic_softc { |
|
Line 104 static struct armgic_softc { |
|
uint32_t sc_gic_valid_lines[1024/32]; |
uint32_t sc_gic_valid_lines[1024/32]; |
uint32_t sc_enabled_local; |
uint32_t sc_enabled_local; |
#ifdef MULTIPROCESSOR |
#ifdef MULTIPROCESSOR |
uint32_t sc_target[MAXCPUS]; |
|
uint32_t sc_mptargets; |
uint32_t sc_mptargets; |
#endif |
#endif |
uint32_t sc_bptargets; |
uint32_t sc_bptargets; |
Line 228 armgic_set_priority(struct pic_softc *pi |
|
Line 222 armgic_set_priority(struct pic_softc *pi |
|
gicc_write(sc, GICC_PMR, priority); |
gicc_write(sc, GICC_PMR, priority); |
} |
} |
|
|
#ifdef MULTIPROCESSOR |
|
static void |
|
armgic_get_affinity(struct pic_softc *pic, size_t irq, kcpuset_t *affinity) |
|
{ |
|
struct armgic_softc * const sc = PICTOSOFTC(pic); |
|
const size_t group = irq / 32; |
|
int n; |
|
|
|
kcpuset_zero(affinity); |
|
if (group == 0) { |
|
/* All CPUs are targets for group 0 (SGI/PPI) */ |
|
for (n = 0; n < MAXCPUS; n++) { |
|
if (sc->sc_target[n] != 0) |
|
kcpuset_set(affinity, n); |
|
} |
|
} else { |
|
/* Find distributor targets (SPI) */ |
|
const u_int byte_shift = 8 * (irq & 3); |
|
const bus_size_t targets_reg = GICD_ITARGETSRn(irq / 4); |
|
const uint32_t targets = gicd_read(sc, targets_reg); |
|
const uint32_t targets_val = (targets >> byte_shift) & 0xff; |
|
|
|
for (n = 0; n < MAXCPUS; n++) { |
|
if (sc->sc_target[n] & targets_val) |
|
kcpuset_set(affinity, n); |
|
} |
|
} |
|
} |
|
|
|
static int |
|
armgic_set_affinity(struct pic_softc *pic, size_t irq, |
|
const kcpuset_t *affinity) |
|
{ |
|
struct armgic_softc * const sc = PICTOSOFTC(pic); |
|
const size_t group = irq / 32; |
|
if (group == 0) |
|
return EINVAL; |
|
|
|
const u_int byte_shift = 8 * (irq & 3); |
|
const bus_size_t targets_reg = GICD_ITARGETSRn(irq / 4); |
|
uint32_t targets_val = 0; |
|
int n; |
|
|
|
for (n = 0; n < MAXCPUS; n++) { |
|
if (kcpuset_isset(affinity, n)) |
|
targets_val |= sc->sc_target[n]; |
|
} |
|
|
|
uint32_t targets = gicd_read(sc, targets_reg); |
|
targets &= ~(0xff << byte_shift); |
|
targets |= (targets_val << byte_shift); |
|
gicd_write(sc, targets_reg, targets); |
|
|
|
return 0; |
|
} |
|
#endif |
|
|
|
#ifdef __HAVE_PIC_FAST_SOFTINTS |
#ifdef __HAVE_PIC_FAST_SOFTINTS |
void |
void |
softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep_p) |
softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep_p) |
|
|
armgic_cpu_init_priorities(struct armgic_softc *sc) |
armgic_cpu_init_priorities(struct armgic_softc *sc) |
{ |
{ |
/* Set lowest priority, i.e. disable interrupts */ |
/* Set lowest priority, i.e. disable interrupts */ |
for (size_t i = 0; i < sc->sc_pic.pic_maxsources; i += 4) { |
for (size_t i = 0; i < 32; i += 4) { |
const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4); |
const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4); |
gicd_write(sc, priority_reg, ~0); |
gicd_write(sc, priority_reg, ~0); |
} |
} |
|
|
armgic_cpu_update_priorities(struct armgic_softc *sc) |
armgic_cpu_update_priorities(struct armgic_softc *sc) |
{ |
{ |
uint32_t enabled = sc->sc_enabled_local; |
uint32_t enabled = sc->sc_enabled_local; |
for (size_t i = 0; i < sc->sc_pic.pic_maxsources; i += 4, enabled >>= 4) { |
for (size_t i = 0; i < 32; i += 4, enabled >>= 4) { |
const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4); |
const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4); |
uint32_t priority = gicd_read(sc, priority_reg); |
uint32_t priority = gicd_read(sc, priority_reg); |
uint32_t byte_mask = 0xff; |
uint32_t byte_mask = 0xff; |
|
|
armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci) |
armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci) |
{ |
{ |
struct armgic_softc * const sc = PICTOSOFTC(pic); |
struct armgic_softc * const sc = PICTOSOFTC(pic); |
sc->sc_target[cpu_index(ci)] = gicd_find_targets(sc); |
sc->sc_mptargets |= gicd_find_targets(sc); |
atomic_or_32(&sc->sc_mptargets, sc->sc_target[cpu_index(ci)]); |
|
KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); |
KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); |
armgic_cpu_init_priorities(sc); |
armgic_cpu_init_priorities(sc); |
if (!CPU_IS_PRIMARY(ci)) { |
if (!CPU_IS_PRIMARY(ci)) { |
Line 547 armgic_ipi_send(struct pic_softc *pic, c |
|
Line 483 armgic_ipi_send(struct pic_softc *pic, c |
|
|
|
uint32_t sgir = __SHIFTIN(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID); |
uint32_t sgir = __SHIFTIN(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID); |
if (kcp != NULL) { |
if (kcp != NULL) { |
uint32_t targets_val = 0; |
uint32_t targets; |
for (int n = 0; n < MAXCPUS; n++) { |
kcpuset_export_u32(kcp, &targets, sizeof(targets)); |
if (kcpuset_isset(kcp, n)) |
sgir |= __SHIFTIN(targets, GICD_SGIR_TargetList); |
targets_val |= sc->sc_target[n]; |
|
} |
|
sgir |= __SHIFTIN(targets_val, GICD_SGIR_TargetList); |
|
sgir |= GICD_SGIR_TargetListFilter_List; |
sgir |= GICD_SGIR_TargetListFilter_List; |
} else { |
} else { |
if (ncpu == 1) |
if (ncpu == 1) |
Line 677 armgic_attach(device_t parent, device_t |
|
Line 610 armgic_attach(device_t parent, device_t |
|
} |
} |
} |
} |
#ifdef __HAVE_PIC_FAST_SOFTINTS |
#ifdef __HAVE_PIC_FAST_SOFTINTS |
intr_establish_xname(SOFTINT_BIO, IPL_SOFTBIO, IST_MPSAFE | IST_EDGE, |
intr_establish(SOFTINT_BIO, IPL_SOFTBIO, IST_MPSAFE | IST_EDGE, |
pic_handle_softint, (void *)SOFTINT_BIO, "softint bio"); |
pic_handle_softint, (void *)SOFTINT_BIO); |
intr_establish_xname(SOFTINT_CLOCK, IPL_SOFTCLOCK, IST_MPSAFE | IST_EDGE, |
intr_establish(SOFTINT_CLOCK, IPL_SOFTCLOCK, IST_MPSAFE | IST_EDGE, |
pic_handle_softint, (void *)SOFTINT_CLOCK, "softint clock"); |
pic_handle_softint, (void *)SOFTINT_CLOCK); |
intr_establish_xname(SOFTINT_NET, IPL_SOFTNET, IST_MPSAFE | IST_EDGE, |
intr_establish(SOFTINT_NET, IPL_SOFTNET, IST_MPSAFE | IST_EDGE, |
pic_handle_softint, (void *)SOFTINT_NET, "softint net"); |
pic_handle_softint, (void *)SOFTINT_NET); |
intr_establish_xname(SOFTINT_SERIAL, IPL_SOFTSERIAL, IST_MPSAFE | IST_EDGE, |
intr_establish(SOFTINT_SERIAL, IPL_SOFTSERIAL, IST_MPSAFE | IST_EDGE, |
pic_handle_softint, (void *)SOFTINT_SERIAL, "softint serial"); |
pic_handle_softint, (void *)SOFTINT_SERIAL); |
#endif |
#endif |
#ifdef MULTIPROCESSOR |
#ifdef MULTIPROCESSOR |
armgic_cpu_init(&sc->sc_pic, curcpu()); |
armgic_cpu_init(&sc->sc_pic, curcpu()); |
|
|
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_AST, IPL_VM, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_AST, IPL_VM, |
IST_MPSAFE | IST_EDGE, pic_ipi_ast, (void *)-1, "IPI ast"); |
IST_MPSAFE | IST_EDGE, pic_ipi_ast, (void *)-1); |
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_XCALL, IPL_HIGH, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_XCALL, IPL_HIGH, |
IST_MPSAFE | IST_EDGE, pic_ipi_xcall, (void *)-1, "IPI xcall"); |
IST_MPSAFE | IST_EDGE, pic_ipi_xcall, (void *)-1); |
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_GENERIC, IPL_HIGH, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_GENERIC, IPL_HIGH, |
IST_MPSAFE | IST_EDGE, pic_ipi_generic, (void *)-1, "IPI generic"); |
IST_MPSAFE | IST_EDGE, pic_ipi_generic, (void *)-1); |
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_NOP, IPL_VM, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_NOP, IPL_VM, |
IST_MPSAFE | IST_EDGE, pic_ipi_nop, (void *)-1, "IPI nop"); |
IST_MPSAFE | IST_EDGE, pic_ipi_nop, (void *)-1); |
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_SHOOTDOWN, IPL_SCHED, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_SHOOTDOWN, IPL_SCHED, |
IST_MPSAFE | IST_EDGE, pic_ipi_shootdown, (void *)-1, "IPI shootdown"); |
IST_MPSAFE | IST_EDGE, pic_ipi_shootdown, (void *)-1); |
#ifdef DDB |
#ifdef DDB |
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_DDB, IPL_HIGH, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_DDB, IPL_HIGH, |
IST_MPSAFE | IST_EDGE, pic_ipi_ddb, NULL, "IPI ddb"); |
IST_MPSAFE | IST_EDGE, pic_ipi_ddb, NULL); |
#endif |
#endif |
#ifdef __HAVE_PREEMPTION |
#ifdef __HAVE_PREEMPTION |
intr_establish_xname(ARMGIC_SGI_IPIBASE + IPI_KPREEMPT, IPL_VM, |
intr_establish(ARMGIC_SGI_IPIBASE + IPI_KPREEMPT, IPL_VM, |
IST_MPSAFE | IST_EDGE, pic_ipi_kpreempt, (void *)-1, "IPI kpreempt"); |
IST_MPSAFE | IST_EDGE, pic_ipi_kpreempt, (void *)-1); |
#endif |
#endif |
#endif |
#endif |
|
|