summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-12-06 16:20:54 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-12-06 16:20:54 +0000
commit3e609ed7f050756b135c2e76d1821eff150d8bd8 (patch)
treedc51e7a2858bd643dc4e541daba3150d3bce9abb /sys/arch
parenta26017407cda41dd47792e2c2da36f679e5195ef (diff)
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).
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc64/dev/vbus.c25
-rw-r--r--sys/arch/sparc64/dev/vpci.c25
-rw-r--r--sys/arch/sparc64/include/hypervisor.h10
-rw-r--r--sys/arch/sparc64/sparc64/autoconf.c18
-rw-r--r--sys/arch/sparc64/sparc64/intr.c56
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 **)&reg);
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 <kettenis@openbsd.org>
*
@@ -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 <machine/hypervisor.h>
+
+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