From 01555c0fe019dcc734978f70d604f127b47ff70e Mon Sep 17 00:00:00 2001 From: kettenis Date: Wed, 6 Dec 2017 16:20:53 +0000 Subject: [PATCH] Implement support for using interrupt cookies in vbus(4) and vpci(4) as introduced in version 3.0 of the Interrupt APIs group. This makes it possible boot OpenBSD on SPARC T7/M7 hardware (although there still may be issues with the onboard mpii(4) controller). --- sys/arch/sparc64/dev/vbus.c | 25 +++++++++--- sys/arch/sparc64/dev/vpci.c | 25 ++++++++---- sys/arch/sparc64/include/hypervisor.h | 10 ++++- sys/arch/sparc64/sparc64/autoconf.c | 18 ++++++++- sys/arch/sparc64/sparc64/intr.c | 56 ++++++++++++++++++++++++++- 5 files changed, 117 insertions(+), 17 deletions(-) diff --git a/sys/arch/sparc64/dev/vbus.c b/sys/arch/sparc64/dev/vbus.c index 35f65a96b0a..85260dd4ddd 100644 --- a/sys/arch/sparc64/dev/vbus.c +++ b/sys/arch/sparc64/dev/vbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vbus.c,v 1.8 2015/09/27 11:29:20 kettenis Exp $ */ +/* $OpenBSD: vbus.c,v 1.9 2017/12/06 16:20:53 kettenis Exp $ */ /* * Copyright (c) 2008 Mark Kettenis * @@ -33,6 +33,8 @@ struct vbus_softc { struct device sc_dv; bus_space_tag_t sc_bustag; bus_dma_tag_t sc_dmatag; + + uint64_t sc_devhandle; }; int vbus_cmp_cells(int *, int *, int *, int); @@ -73,6 +75,7 @@ vbus_attach(struct device *parent, struct device *self, void *aux) sc->sc_bustag = vbus_alloc_bus_tag(sc, ma->ma_bustag); sc->sc_dmatag = ma->ma_dmatag; + sc->sc_devhandle = (ma->ma_reg[0].ur_paddr >> 32) & 0x0fffffff; printf("\n"); for (node = OF_child(ma->ma_node); node; node = OF_peer(node)) { @@ -174,7 +177,7 @@ vbus_intr_map(int node, int ino, uint64_t *sysino) getprop(node, "reg", sizeof(*reg), &nreg, (void **)®); devhandle = reg[0] & 0x0fffffff; - err = hv_intr_devino_to_sysino(devhandle, devino, sysino); + err = sun4v_intr_devino_to_sysino(devhandle, devino, sysino); if (err != H_EOK) return (-1); @@ -192,6 +195,8 @@ void * vbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, int level, int flags, int (*handler)(void *), void *arg, const char *what) { + struct vbus_softc *sc = t->cookie; + uint64_t devhandle = sc->sc_devhandle; uint64_t sysino = INTVEC(ihandle); struct intrhand *ih; int err; @@ -204,19 +209,23 @@ vbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, if (flags & BUS_INTR_ESTABLISH_MPSAFE) ih->ih_mpsafe = 1; + err = sun4v_intr_setcookie(devhandle, sysino, (vaddr_t)ih); + if (err != H_EOK) + return (NULL); + intr_establish(ih->ih_pil, ih); ih->ih_ack = vbus_intr_ack; - err = hv_intr_settarget(sysino, ih->ih_cpu->ci_upaid); + err = sun4v_intr_settarget(devhandle, sysino, ih->ih_cpu->ci_upaid); if (err != H_EOK) return (NULL); /* Clear pending interrupts. */ - err = hv_intr_setstate(sysino, INTR_IDLE); + err = sun4v_intr_setstate(devhandle, sysino, INTR_IDLE); if (err != H_EOK) return (NULL); - err = hv_intr_setenabled(sysino, INTR_ENABLED); + err = sun4v_intr_setenabled(devhandle, sysino, INTR_ENABLED); if (err != H_EOK) return (NULL); @@ -226,7 +235,11 @@ vbus_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, void vbus_intr_ack(struct intrhand *ih) { - hv_intr_setstate(ih->ih_number, INTR_IDLE); + bus_space_tag_t t = ih->ih_bus; + struct vbus_softc *sc = t->cookie; + uint64_t devhandle = sc->sc_devhandle; + + sun4v_intr_setstate(devhandle, ih->ih_number, INTR_IDLE); } bus_space_tag_t diff --git a/sys/arch/sparc64/dev/vpci.c b/sys/arch/sparc64/dev/vpci.c index 491b3328b19..3a1a7a00c42 100644 --- a/sys/arch/sparc64/dev/vpci.c +++ b/sys/arch/sparc64/dev/vpci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vpci.c,v 1.22 2017/12/05 21:04:32 kettenis Exp $ */ +/* $OpenBSD: vpci.c,v 1.23 2017/12/06 16:20:53 kettenis Exp $ */ /* * Copyright (c) 2008 Mark Kettenis * @@ -252,12 +252,12 @@ vpci_init_msi(struct vpci_softc *sc, struct vpci_pbm *pbm) OF_getprop(sc->sc_node, "msi-eq-to-devino", msi_eq_devino, sizeof(msi_eq_devino)); - err = hv_intr_devino_to_sysino(pbm->vp_devhandle, + err = sun4v_intr_devino_to_sysino(pbm->vp_devhandle, msi_eq_devino[2], &sysino); if (err != H_EOK) goto disable_queue; - if (vpci_intr_establish(sc->sc_bust, sc->sc_bust, sysino, + if (vpci_intr_establish(pbm->vp_memt, pbm->vp_memt, sysino, IPL_HIGH, 0, vpci_msi_eq_intr, pbm, sc->sc_dv.dv_xname) == NULL) goto disable_queue; @@ -333,7 +333,7 @@ vpci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) int err; if (*ihp != (pci_intr_handle_t)-1) { - err = hv_intr_devino_to_sysino(devhandle, devino, &sysino); + err = sun4v_intr_devino_to_sysino(devhandle, devino, &sysino); if (err != H_EOK) return (-1); @@ -513,6 +513,7 @@ vpci_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, int level, int flags, int (*handler)(void *), void *arg, const char *what) { struct vpci_pbm *pbm = t->cookie; + uint64_t devhandle = pbm->vp_devhandle; uint64_t sysino = INTVEC(ihandle); struct intrhand *ih; int err; @@ -560,19 +561,23 @@ vpci_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, return (ih); } + err = sun4v_intr_setcookie(devhandle, sysino, (vaddr_t)ih); + if (err != H_EOK) + return (NULL); + intr_establish(ih->ih_pil, ih); ih->ih_ack = vpci_intr_ack; - err = hv_intr_settarget(sysino, ih->ih_cpu->ci_upaid); + err = sun4v_intr_settarget(devhandle, sysino, ih->ih_cpu->ci_upaid); if (err != H_EOK) return (NULL); /* Clear pending interrupts. */ - err = hv_intr_setstate(sysino, INTR_IDLE); + err = sun4v_intr_setstate(devhandle, sysino, INTR_IDLE); if (err != H_EOK) return (NULL); - err = hv_intr_setenabled(sysino, INTR_ENABLED); + err = sun4v_intr_setenabled(devhandle, sysino, INTR_ENABLED); if (err != H_EOK) return (NULL); @@ -582,7 +587,11 @@ vpci_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle, void vpci_intr_ack(struct intrhand *ih) { - hv_intr_setstate(ih->ih_number, INTR_IDLE); + bus_space_tag_t t = ih->ih_bus; + struct vpci_pbm *pbm = t->cookie; + uint64_t devhandle = pbm->vp_devhandle; + + sun4v_intr_setstate(devhandle, ih->ih_number, INTR_IDLE); } void diff --git a/sys/arch/sparc64/include/hypervisor.h b/sys/arch/sparc64/include/hypervisor.h index f01d1f9b734..39fad757502 100644 --- a/sys/arch/sparc64/include/hypervisor.h +++ b/sys/arch/sparc64/include/hypervisor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hypervisor.h,v 1.15 2014/01/23 23:56:27 kettenis Exp $ */ +/* $OpenBSD: hypervisor.h,v 1.16 2017/12/06 16:20:53 kettenis Exp $ */ /* * Copyright (c) 2008 Mark Kettenis @@ -320,3 +320,11 @@ int64_t hv_rng_data_read(paddr_t raddr, uint64_t *delta); #define H_ENOMAP 14 #define H_ETOOMANY 15 #define H_ECHANNEL 16 + +extern uint64_t sun4v_group_interrupt_major; + +int64_t sun4v_intr_devino_to_sysino(uint64_t, uint64_t, uint64_t *); +int64_t sun4v_intr_setcookie(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_setenabled(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_setstate(uint64_t, uint64_t, uint64_t); +int64_t sun4v_intr_settarget(uint64_t, uint64_t, uint64_t); diff --git a/sys/arch/sparc64/sparc64/autoconf.c b/sys/arch/sparc64/sparc64/autoconf.c index 1a9f711f535..fee9fbc8b89 100644 --- a/sys/arch/sparc64/sparc64/autoconf.c +++ b/sys/arch/sparc64/sparc64/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.128 2017/04/30 16:45:45 mpi Exp $ */ +/* $OpenBSD: autoconf.c,v 1.129 2017/12/06 16:20:53 kettenis Exp $ */ /* $NetBSD: autoconf.c,v 1.51 2001/07/24 19:32:11 eeh Exp $ */ /* @@ -170,6 +170,8 @@ void sun4v_set_soft_state(int, const char *); #define __align32 __attribute__((__aligned__(32))) char sun4v_soft_state_booting[] __align32 = "OpenBSD booting"; char sun4v_soft_state_running[] __align32 = "OpenBSD running"; + +void sun4v_interrupt_init(void); #endif #ifdef DEBUG @@ -436,6 +438,7 @@ bootstrap(int nctx) if (CPU_ISSUN4V) { sun4v_soft_state_init(); sun4v_set_soft_state(SIS_TRANSITION, sun4v_soft_state_booting); + sun4v_interrupt_init(); } #endif } @@ -733,6 +736,7 @@ cpu_configure(void) #ifdef SUN4V +#define HSVC_GROUP_INTERRUPT 0x002 #define HSVC_GROUP_SOFT_STATE 0x003 int sun4v_soft_state_initialized = 0; @@ -765,6 +769,18 @@ sun4v_set_soft_state(int state, const char *desc) if (err != H_EOK) printf("soft_state_set: %d\n", err); } + +void +sun4v_interrupt_init(void) +{ + uint64_t minor; + + if (prom_set_sun4v_api_version(HSVC_GROUP_INTERRUPT, 3, 0, &minor)) + return; + + sun4v_group_interrupt_major = 3; +} + #endif void diff --git a/sys/arch/sparc64/sparc64/intr.c b/sys/arch/sparc64/sparc64/intr.c index f82f6427c28..193e734e345 100644 --- a/sys/arch/sparc64/sparc64/intr.c +++ b/sys/arch/sparc64/sparc64/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.56 2017/04/30 16:45:45 mpi Exp $ */ +/* $OpenBSD: intr.c,v 1.57 2017/12/06 16:20:53 kettenis Exp $ */ /* $NetBSD: intr.c,v 1.39 2001/07/19 23:38:11 eeh Exp $ */ /* @@ -383,3 +383,57 @@ splassert_check(int wantipl, const char *func) } } #endif + +#ifdef SUN4V + +#include + +uint64_t sun4v_group_interrupt_major; + +int64_t +sun4v_intr_devino_to_sysino(uint64_t devhandle, uint64_t devino, uint64_t *ino) +{ + if (sun4v_group_interrupt_major < 3) + return hv_intr_devino_to_sysino(devhandle, devino, ino); + + *ino = devino; + return H_EOK; +} + +int64_t +sun4v_intr_setcookie(uint64_t devhandle, uint64_t ino, uint64_t cookie_value) +{ + if (sun4v_group_interrupt_major < 3) + return H_EOK; + + return hv_vintr_setcookie(devhandle, ino, cookie_value); +} + +int64_t +sun4v_intr_setenabled(uint64_t devhandle, uint64_t ino, uint64_t intr_enabled) +{ + if (sun4v_group_interrupt_major < 3) + return hv_intr_setenabled(ino, intr_enabled); + + return hv_vintr_setenabled(devhandle, ino, intr_enabled); +} + +int64_t +sun4v_intr_setstate(uint64_t devhandle, uint64_t ino, uint64_t intr_state) +{ + if (sun4v_group_interrupt_major < 3) + return hv_intr_setstate(ino, intr_state); + + return hv_vintr_setstate(devhandle, ino, intr_state); +} + +int64_t +sun4v_intr_settarget(uint64_t devhandle, uint64_t ino, uint64_t cpuid) +{ + if (sun4v_group_interrupt_major < 3) + return hv_intr_settarget(ino, cpuid); + + return hv_vintr_settarget(devhandle, ino, cpuid); +} + +#endif -- 2.20.1