Module Name:    src
Committed By:   palle
Date:           Tue May 10 19:24:00 UTC 2016

Modified Files:
        src/sys/arch/sparc64/dev: fhc.c psycho.c pyro.c sbus.c schizo.c vpci.c
        src/sys/arch/sparc64/include: cpu.h
        src/sys/arch/sparc64/sparc64: genassym.cf intr.c locore.s

Log Message:
sun4v: make device interrupts work. Introduce a new intrhand_alloc() function 
for allocation of interrupt handlers and adapt to this. Parts from OpenBSD. ok 
martin@


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/sparc64/dev/fhc.c
cvs rdiff -u -r1.123 -r1.124 src/sys/arch/sparc64/dev/psycho.c
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/sparc64/dev/pyro.c
cvs rdiff -u -r1.93 -r1.94 src/sys/arch/sparc64/dev/sbus.c
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/sparc64/dev/schizo.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/sparc64/dev/vpci.c
cvs rdiff -u -r1.118 -r1.119 src/sys/arch/sparc64/include/cpu.h
cvs rdiff -u -r1.76 -r1.77 src/sys/arch/sparc64/sparc64/genassym.cf
cvs rdiff -u -r1.67 -r1.68 src/sys/arch/sparc64/sparc64/intr.c
cvs rdiff -u -r1.390 -r1.391 src/sys/arch/sparc64/sparc64/locore.s

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/sparc64/dev/fhc.c
diff -u src/sys/arch/sparc64/dev/fhc.c:1.3 src/sys/arch/sparc64/dev/fhc.c:1.4
--- src/sys/arch/sparc64/dev/fhc.c:1.3	Sun Mar 18 05:26:58 2012
+++ src/sys/arch/sparc64/dev/fhc.c	Tue May 10 19:23:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: fhc.c,v 1.3 2012/03/18 05:26:58 mrg Exp $	*/
+/*	$NetBSD: fhc.c,v 1.4 2016/05/10 19:23:59 palle Exp $	*/
 /*	$OpenBSD: fhc.c,v 1.17 2010/11/11 17:58:23 miod Exp $	*/
 
 /*
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fhc.c,v 1.3 2012/03/18 05:26:58 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fhc.c,v 1.4 2016/05/10 19:23:59 palle Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -251,10 +251,7 @@ fhc_intr_establish(bus_space_tag_t t, in
 	vec = ((sc->sc_ign << INTMAP_IGN_SHIFT) & INTMAP_IGN) |
 	    INTINO(ihandle);
 
-	ih = (struct intrhand *)
-		malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
-	if (ih == NULL)
-		return (NULL);
+	ih = intrhand_alloc();
 
 	ih->ih_ivec = ihandle;
 

Index: src/sys/arch/sparc64/dev/psycho.c
diff -u src/sys/arch/sparc64/dev/psycho.c:1.123 src/sys/arch/sparc64/dev/psycho.c:1.124
--- src/sys/arch/sparc64/dev/psycho.c:1.123	Fri Nov 27 00:36:58 2015
+++ src/sys/arch/sparc64/dev/psycho.c	Tue May 10 19:23:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: psycho.c,v 1.123 2015/11/27 00:36:58 mrg Exp $	*/
+/*	$NetBSD: psycho.c,v 1.124 2016/05/10 19:23:59 palle Exp $	*/
 
 /*
  * Copyright (c) 1999, 2000 Matthew R. Green
@@ -55,7 +55,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.123 2015/11/27 00:36:58 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: psycho.c,v 1.124 2016/05/10 19:23:59 palle Exp $");
 
 #include "opt_ddb.h"
 
@@ -707,8 +707,7 @@ psycho_set_intr(struct psycho_softc *sc,
 {
 	struct intrhand *ih;
 
-	ih = (struct intrhand *)malloc(sizeof(struct intrhand),
-		M_DEVBUF, M_NOWAIT);
+	ih = intrhand_alloc();
 	ih->ih_arg = sc;
 	ih->ih_map = mapper;
 	ih->ih_clr = clearer;
@@ -1273,9 +1272,7 @@ psycho_intr_establish(bus_space_tag_t t,
 	int ino;
 	long vec = INTVEC(ihandle);
 
-	ih = malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
-	if (ih == NULL)
-		return (NULL);
+	ih = intrhand_alloc();
 
 	ih->ih_ivec = ihandle;
 

Index: src/sys/arch/sparc64/dev/pyro.c
diff -u src/sys/arch/sparc64/dev/pyro.c:1.16 src/sys/arch/sparc64/dev/pyro.c:1.17
--- src/sys/arch/sparc64/dev/pyro.c:1.16	Fri Oct  2 05:22:52 2015
+++ src/sys/arch/sparc64/dev/pyro.c	Tue May 10 19:23:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: pyro.c,v 1.16 2015/10/02 05:22:52 msaitoh Exp $	*/
+/*	$NetBSD: pyro.c,v 1.17 2016/05/10 19:23:59 palle Exp $	*/
 /*	from: $OpenBSD: pyro.c,v 1.20 2010/12/05 15:15:14 kettenis Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pyro.c,v 1.16 2015/10/02 05:22:52 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pyro.c,v 1.17 2016/05/10 19:23:59 palle Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -580,9 +580,7 @@ pyro_intr_establish(bus_space_tag_t t, i
 
 	ino |= INTVEC(ihandle);
 
-	ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
-	if (ih == NULL)
-		return (NULL);
+	ih = intrhand_alloc();
 
 	/* Register the map and clear intr registers */
 	ih->ih_map = intrmapptr;

Index: src/sys/arch/sparc64/dev/sbus.c
diff -u src/sys/arch/sparc64/dev/sbus.c:1.93 src/sys/arch/sparc64/dev/sbus.c:1.94
--- src/sys/arch/sparc64/dev/sbus.c:1.93	Mon Jan 30 04:25:15 2012
+++ src/sys/arch/sparc64/dev/sbus.c	Tue May 10 19:23:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: sbus.c,v 1.93 2012/01/30 04:25:15 mrg Exp $ */
+/*	$NetBSD: sbus.c,v 1.94 2016/05/10 19:23:59 palle Exp $ */
 
 /*
  * Copyright (c) 1999-2002 Eduardo Horvath
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sbus.c,v 1.93 2012/01/30 04:25:15 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sbus.c,v 1.94 2016/05/10 19:23:59 palle Exp $");
 
 #include "opt_ddb.h"
 
@@ -254,8 +254,7 @@ sbus_attach(device_t parent, device_t se
 	iommu_init(name, &sc->sc_is, 0, -1);
 
 	/* Enable the over temp intr */
-	ih = (struct intrhand *)
-		malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
+	ih = intrhand_alloc();
 	ih->ih_map = &sc->sc_sysio->therm_int_map;
 	ih->ih_clr = NULL; /* &sc->sc_sysio->therm_clr_int; */
 	ih->ih_fun = sbus_overtemp;
@@ -508,10 +507,7 @@ sbus_intr_establish(bus_space_tag_t t, i
 	int ipl;
 	long vec = pri; 
 
-	ih = (struct intrhand *)
-		malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
-	if (ih == NULL)
-		return (NULL);
+	ih = intrhand_alloc();
 
 	if ((vec & SBUS_INTR_COMPAT) != 0)
 		ipl = vec & ~SBUS_INTR_COMPAT;

Index: src/sys/arch/sparc64/dev/schizo.c
diff -u src/sys/arch/sparc64/dev/schizo.c:1.35 src/sys/arch/sparc64/dev/schizo.c:1.36
--- src/sys/arch/sparc64/dev/schizo.c:1.35	Fri Nov 27 09:34:36 2015
+++ src/sys/arch/sparc64/dev/schizo.c	Tue May 10 19:23:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: schizo.c,v 1.35 2015/11/27 09:34:36 martin Exp $	*/
+/*	$NetBSD: schizo.c,v 1.36 2016/05/10 19:23:59 palle Exp $	*/
 /*	$OpenBSD: schizo.c,v 1.55 2008/08/18 20:29:37 brad Exp $	*/
 
 /*
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: schizo.c,v 1.35 2015/11/27 09:34:36 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: schizo.c,v 1.36 2016/05/10 19:23:59 palle Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -588,10 +588,8 @@ schizo_set_intr(struct schizo_softc *sc,
 	DPRINTF(SDB_INTR, (" mapoff %" PRIx64 " clroff %" PRIx64 "\n",
 	    mapoff, clroff));
 
-	ih = (struct intrhand *)
-		kmem_alloc(sizeof(struct intrhand), KM_NOSLEEP);
-	if (ih == NULL)
-		return;
+	ih = intrhand_alloc();
+	
 	ih->ih_arg = arg;
 	intrregs = (uintptr_t)bus_space_vaddr(pbm->sp_regt, pbm->sp_intrh);
 	ih->ih_map = (uint64_t *)(uintptr_t)(intrregs + mapoff);
@@ -815,9 +813,7 @@ schizo_intr_establish(bus_space_tag_t t,
 	vec = INTVEC(ihandle);
 	ino = INTINO(vec);
 
-	ih = kmem_alloc(sizeof *ih, KM_NOSLEEP);
-	if (ih == NULL)
-		return (NULL);
+	ih = intrhand_alloc();
 
 	DPRINTF(SDB_INTR, ("\n%s: ihandle %x level %d fn %p arg %p\n", __func__,
 	    ihandle, level, handler, arg));

Index: src/sys/arch/sparc64/dev/vpci.c
diff -u src/sys/arch/sparc64/dev/vpci.c:1.6 src/sys/arch/sparc64/dev/vpci.c:1.7
--- src/sys/arch/sparc64/dev/vpci.c:1.6	Fri Nov 27 13:51:57 2015
+++ src/sys/arch/sparc64/dev/vpci.c	Tue May 10 19:23:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: vpci.c,v 1.6 2015/11/27 13:51:57 joerg Exp $	*/
+/*	$NetBSD: vpci.c,v 1.7 2016/05/10 19:23:59 palle Exp $	*/
 /*
  * Copyright (c) 2015 Palle Lyckegaard
  * All rights reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vpci.c,v 1.6 2015/11/27 13:51:57 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vpci.c,v 1.7 2016/05/10 19:23:59 palle Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -114,7 +114,7 @@ void vpci_conf_write(pci_chipset_tag_t, 
 static void * vpci_pci_intr_establish(pci_chipset_tag_t pc,
 				      pci_intr_handle_t ih, int level,
 				      int (*func)(void *), void *arg);
-
+void vpci_intr_ack(struct intrhand *);
 int vpci_intr_map(const struct pci_attach_args *, pci_intr_handle_t *);
 int vpci_bus_map(bus_space_tag_t, bus_addr_t,
     bus_size_t, int, vaddr_t, bus_space_handle_t *);
@@ -596,9 +596,7 @@ vpci_intr_establish(bus_space_tag_t t, i
 	ino |= INTVEC(ihandle);
 	DPRINTF(VDB_INTR, ("%s: ih %lx; level %d ino %#x\n", __func__, (u_long)ihandle, level, ino));
 
-	ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
-	if (ih == NULL)
-		return (NULL);
+	ih = intrhand_alloc();
 
 	ih->ih_ivec = ihandle;
 	ih->ih_fun = handler;
@@ -606,12 +604,44 @@ vpci_intr_establish(bus_space_tag_t t, i
 	ih->ih_pil = level;
 	ih->ih_number = ino;
 	ih->ih_pending = 0;
-	
+	ih->ih_ack = vpci_intr_ack;
 	intr_establish(ih->ih_pil, level != IPL_VM, ih);
 
+	uint64_t sysino = INTVEC(ihandle);
+	DPRINTF(VDB_INTR, ("vpci_intr_establish(): sysino 0x%lx\n", sysino));
+
+	int err;
+
+	err = hv_intr_settarget(sysino, cpus->ci_cpuid);
+	if (err != H_EOK)
+		printf("hv_intr_settarget(%lu, %u) failed - err = %d\n", 
+		       (long unsigned int)sysino, cpus->ci_cpuid, err);
+
+	/* Clear pending interrupts. */
+	err = hv_intr_setstate(sysino, INTR_IDLE);
+	if (err != H_EOK)
+	  printf("hv_intr_setstate(%lu, INTR_IDLE) failed - err = %d\n", 
+		(long unsigned int)sysino, err);
+
+	err = hv_intr_setenabled(sysino, INTR_ENABLED);
+	if (err != H_EOK)
+	  printf("hv_intr_setenabled(%lu) failed - err = %d\n", 
+		(long unsigned int)sysino, err);
+
+	DPRINTF(VDB_INTR, ("%s() returning %p\n", __func__, ih));
 	return (ih);
 }
 
+void
+vpci_intr_ack(struct intrhand *ih)
+{
+	int err;
+	err = hv_intr_setstate(ih->ih_number, INTR_IDLE);
+	if (err != H_EOK)
+	  panic("%s(%u, INTR_IDLE) failed - err = %d\n", 
+		__func__, ih->ih_number, err);
+}
+
 static void *
 vpci_pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
 	int (*func)(void *), void *arg)

Index: src/sys/arch/sparc64/include/cpu.h
diff -u src/sys/arch/sparc64/include/cpu.h:1.118 src/sys/arch/sparc64/include/cpu.h:1.119
--- src/sys/arch/sparc64/include/cpu.h:1.118	Mon Sep  7 20:00:49 2015
+++ src/sys/arch/sparc64/include/cpu.h	Tue May 10 19:24:00 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.118 2015/09/07 20:00:49 palle Exp $ */
+/*	$NetBSD: cpu.h,v 1.119 2016/05/10 19:24:00 palle Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -361,6 +361,7 @@ struct intrhand {
 	struct intrhand		*ih_pending;	/* interrupt queued */
 	volatile uint64_t	*ih_map;	/* Interrupt map reg */
 	volatile uint64_t	*ih_clr;	/* clear interrupt reg */
+	void			(*ih_ack)(struct intrhand *); /* ack interrupt function */
 	struct evcnt		ih_cnt;		/* counter for vmstat */
 	uint32_t		ih_ivec;
 	char			ih_name[32];	/* name for the above */
@@ -372,6 +373,7 @@ void	intr_establish(int level, bool mpsa
 void	*sparc_softintr_establish(int, int (*)(void *), void *);
 void	sparc_softintr_schedule(void *);
 void	sparc_softintr_disestablish(void *);
+struct intrhand *intrhand_alloc(void);
 
 /* cpu.c */
 int	cpu_myid(void);

Index: src/sys/arch/sparc64/sparc64/genassym.cf
diff -u src/sys/arch/sparc64/sparc64/genassym.cf:1.76 src/sys/arch/sparc64/sparc64/genassym.cf:1.77
--- src/sys/arch/sparc64/sparc64/genassym.cf:1.76	Wed Apr  1 18:38:30 2015
+++ src/sys/arch/sparc64/sparc64/genassym.cf	Tue May 10 19:24:00 2016
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.76 2015/04/01 18:38:30 palle Exp $
+#	$NetBSD: genassym.cf,v 1.77 2016/05/10 19:24:00 palle Exp $
 
 #
 # Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -170,6 +170,7 @@ define	CI_TSB_IMMU	offsetof(struct cpu_i
 define	CI_MMFSA	offsetof(struct cpu_info, ci_mmfsa)
 define	CI_TSB_DESC	offsetof(struct cpu_info, ci_tsb_desc)
 define	CI_CPUMQ	offsetof(struct cpu_info, ci_cpumq)
+define	CI_DEVMQ	offsetof(struct cpu_info, ci_devmq)
 ifdef MULTIPROCESSOR
 define	CI_IPIEVC	offsetof(struct cpu_info, ci_ipi_evcnt[0].ev_count)
 endif
@@ -254,6 +255,7 @@ define	IH_PEND		offsetof(struct intrhand
 define	IH_NEXT		offsetof(struct intrhand, ih_next)
 define	IH_MAP		offsetof(struct intrhand, ih_map)
 define	IH_CLR		offsetof(struct intrhand, ih_clr)
+define	IH_ACK		offsetof(struct intrhand, ih_ack)
 define  IH_CNT		offsetof(struct intrhand, ih_cnt)
 	
 # mbuf fields of import

Index: src/sys/arch/sparc64/sparc64/intr.c
diff -u src/sys/arch/sparc64/sparc64/intr.c:1.67 src/sys/arch/sparc64/sparc64/intr.c:1.68
--- src/sys/arch/sparc64/sparc64/intr.c:1.67	Sat Aug 11 21:50:09 2012
+++ src/sys/arch/sparc64/sparc64/intr.c	Tue May 10 19:24:00 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.67 2012/08/11 21:50:09 mrg Exp $ */
+/*	$NetBSD: intr.c,v 1.68 2016/05/10 19:24:00 palle Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.67 2012/08/11 21:50:09 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.68 2016/05/10 19:24:00 palle Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.6
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/kmem.h>
 #include <sys/malloc.h>
 
 #include <dev/cons.h>
@@ -170,6 +171,21 @@ intr_biglock_wrapper(void *vp)
 #endif
 
 /*
+ * Allocate memory for interrupt handler.
+ * The allocated memory is initialized with zeros so 
+ * e.g. pointers in the intrhand structure are properly initialized.
+ * A valid pointer is always returned by the function.
+ */
+struct intrhand*
+intrhand_alloc(void)
+{
+	struct intrhand *ih = kmem_zalloc(sizeof(struct intrhand), KM_NOSLEEP);
+	if (ih == NULL)
+		panic("%s: failed to allocate intrhand", __func__);
+	return ih;
+}
+
+/*
  * Attach an interrupt handler to the vector chain for the given level.
  * This is not possible if it has been taken away as a fast vector.
  */
@@ -247,9 +263,7 @@ intr_establish(int level, bool mpsafe, s
 			    ("intr_establish: intr reused %x\n",
 			     ih->ih_number));
 			if (q->ih_fun != intr_list_handler) {
-				nih = (struct intrhand *)
-					malloc(sizeof(struct intrhand),
-						M_DEVBUF, M_NOWAIT);
+				nih = intrhand_alloc();
 				/* Point the old IH at the new handler */
 				*nih = *q;
 				nih->ih_next = NULL;
@@ -284,10 +298,7 @@ sparc_softintr_establish(int pil, int (*
 {
 	struct intrhand *ih;
 
-	ih = malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT|M_ZERO);
-	if (ih == NULL)
-		panic("could not allocate softint interrupt handler");
-
+	ih = intrhand_alloc();
 	ih->ih_fun = fun;
 	ih->ih_pil = pil;
 	ih->ih_arg = arg;

Index: src/sys/arch/sparc64/sparc64/locore.s
diff -u src/sys/arch/sparc64/sparc64/locore.s:1.390 src/sys/arch/sparc64/sparc64/locore.s:1.391
--- src/sys/arch/sparc64/sparc64/locore.s:1.390	Wed Mar  9 12:20:20 2016
+++ src/sys/arch/sparc64/sparc64/locore.s	Tue May 10 19:24:00 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.s,v 1.390 2016/03/09 12:20:20 nakayama Exp $	*/
+/*	$NetBSD: locore.s,v 1.391 2016/05/10 19:24:00 palle Exp $	*/
 
 /*
  * Copyright (c) 2006-2010 Matthew R. Green
@@ -1071,7 +1071,8 @@ _C_LABEL(trapbase_sun4v):
 	HARDINT4V(15)						! 0x04f = level 15 interrupt
 	sun4v_trap_entry 44					! 0x050-0x07b
 	VTRAP(T_CPU_MONDO, sun4v_cpu_mondo)			! 0x07c = cpu mondo
-	sun4v_trap_entry 3					! 0x07d-0x07f
+	VTRAP(T_DEV_MONDO, sun4v_dev_mondo)			! 0x07d = dev mondo
+	sun4v_trap_entry 2					! 0x07e-0x07f
 	SPILL64(uspill8_sun4vt0,ASI_AIUS)			! 0x080 spill_0_normal -- used to save user windows in user mode
 	SPILL32(uspill4_sun4vt0,ASI_AIUS)			! 0x084 spill_1_normal
 	SPILLBOTH(uspill8_sun4vt0,uspill4_sun4vt0,ASI_AIUS)	! 0x088 spill_2_normal
@@ -3592,6 +3593,8 @@ ret_from_intr_vector:
 	 nop				! XXX spitfire bug?
 
 sun4v_cpu_mondo:
+! XXX Rework this when a UP kernel works - crash for now	
+	sir			
 	mov	0x3c0, %g1			 ! CPU Mondo Queue Head
 	ldxa	[%g1] ASI_QUEUE, %g2		 ! fetch index value for head
 	set	CPUINFO_VA, %g3
@@ -3616,7 +3619,45 @@ sun4v_cpu_mondo:
 	retry
 	NOTREACHED
 
-	
+sun4v_dev_mondo:
+	mov	0x3d0, %g1			! Dev Mondo Queue Head
+	ldxa	[%g1] ASI_QUEUE, %g2		! fetch index value
+	mov	0x3d8, %g1			! Dev Mondo Queue Tail
+	ldxa	[%g1] ASI_QUEUE, %g4		! fetch index value
+	cmp	%g2, %g4			! head = queue? 
+	bne,pt 	%xcc, 2f			! unsually not the case
+	 nop
+	retry					! unlikely, ingnore interrupt
+2:	
+	set	CPUINFO_VA, %g3			 ! fetch cpuinfo pa
+	LDPTR	[%g3 + CI_PADDR], %g3		 ! fetch intstack pa
+	set	CPUINFO_VA-INTSTACK, %g4	 ! offset to cpuinfo
+	add	%g4, %g3, %g3			 ! %g3 is now cpuifo
+	add	%g3, CI_DEVMQ, %g3		 ! calc offset to devmq
+	ldxa	[%g3] ASI_PHYS_CACHED, %g3	 ! fetch address of devmq
+	ldxa	[%g3 + %g2] ASI_PHYS_CACHED, %g5 !
+	add	%g2, 64, %g2			 ! each element is 64 bytes 		
+	and	%g2, 0x7ff, %g2			 ! assume 32 elements
+	mov	0x3d0, %g1			 ! Dev Mondo Queue Head
+	stxa	%g2, [%g1] ASI_QUEUE		 ! ajust head index value
+	membar	#Sync
+
+	cmp	%g5, MAXINTNUM			! out of bounds?
+	bgeu,pn	%xcc, 2f
+	 nop					! no just continue
+
+	sethi	%hi(_C_LABEL(intrlev)), %g3
+	or	%g3, %lo(_C_LABEL(intrlev)), %g3
+	sllx	%g5, 3, %g5		! Calculate entry number
+	ldx	[%g3 + %g5], %g5	! We have a pointer to the handler
+1:
+	brnz,pt	%g5, setup_sparcintr	! branch if valid handle
+	 nop
+
+	ba,a	3b			! log if invalid handle
+	 nop
+2:
+	sir				! out of bounds - crash
 /*
  * Ultra1 and Ultra2 CPUs use soft interrupts for everything.  What we do
  * on a soft interrupt, is we should check which bits in SOFTINT(%asr22)
@@ -3910,6 +3951,12 @@ sparc_intr_retry:
 	stx	%g0, [%l1]		! Clear intr source
 	membar	#Sync			! Should not be needed
 0:
+	ldx	[%l2 + IH_ACK], %l1	! ih->ih_ack
+	brz,pn	%l1, 1f
+	 nop
+	jmpl	%l1, %o7		! (*ih->ih_ack)(ih)
+	 mov	%l2, %o0
+1:	
 	cmp	%l7, -1
 	bne,pn	CCCR, 2b		! 'Nother?
 	 mov	%l7, %l2

Reply via email to