summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2017-12-06 16:20:53 +0000
committerkettenis <kettenis@openbsd.org>2017-12-06 16:20:53 +0000
commit01555c0fe019dcc734978f70d604f127b47ff70e (patch)
treef65decaebcdc5b61150b451b8aeb23468d07f28d
parentDisentangle dhclient.conf static lease handling from dynamic (diff)
downloadwireguard-openbsd-01555c0fe019dcc734978f70d604f127b47ff70e.tar.xz
wireguard-openbsd-01555c0fe019dcc734978f70d604f127b47ff70e.zip
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).
-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