PERFORCE change 93959 for review

Kip Macy kmacy at FreeBSD.org
Sat Mar 25 04:20:14 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=93959

Change 93959 by kmacy at kmacy_storage:sun4vtmp on 2006/03/25 04:19:49

	pull in initial {dev,cpu}_mondo implementation

Affected files ...

.. //depot/projects/kmacy_sun4v/src/sys/sparc64/sparc64/genassym.c#15 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/exception.S#39 edit
.. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/interrupt.S#4 edit

Differences ...

==== //depot/projects/kmacy_sun4v/src/sys/sparc64/sparc64/genassym.c#15 (text+ko) ====

@@ -205,9 +205,9 @@
 ASSYM(PC_SIZEOF, sizeof(struct pcpu));
 
 #ifdef SUN4V
-ASSYM(PC_CPU_Q_BASE, offsetof(struct pcpu, pc_cpu_q_ra));
+ASSYM(PC_CPU_Q_RA, offsetof(struct pcpu, pc_cpu_q_ra));
 ASSYM(PC_CPU_Q_SIZE, offsetof(struct pcpu, pc_cpu_q_size));
-ASSYM(PC_DEV_Q_BASE, offsetof(struct pcpu, pc_dev_q_ra));
+ASSYM(PC_DEV_Q_RA, offsetof(struct pcpu, pc_dev_q_ra));
 ASSYM(PC_DEV_Q_SIZE, offsetof(struct pcpu, pc_dev_q_size));
 
 ASSYM(PC_RQ_BASE, offsetof(struct pcpu, pc_rq_ra));
@@ -222,6 +222,7 @@
 ASSYM(PC_CURPCB_RA, offsetof(struct pcpu, pc_curpcb_ra));
 
 ASSYM(PCB_RA, offsetof(struct pcb, pcb_ra));
+ASSYM(INTR_REPORT_SIZE, INTR_REPORT_SIZE);
 #else
 ASSYM(PC_TLB_CTX, offsetof(struct pcpu, pc_tlb_ctx));
 ASSYM(PC_TLB_CTX_MAX, offsetof(struct pcpu, pc_tlb_ctx_max));

==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/exception.S#39 (text+ko) ====

@@ -324,14 +324,11 @@
 	.endm
 	
 	.macro	cpu_mondo
-	MAGIC_TRAP_ON
 	ba,a,pt %xcc, cpu_mondo
 	.align	32
 	.endm
 
 	.macro	dev_mondo
-	MAGIC_TRAP_ON
-	MAGIC_EXIT
 	ba,a,pt %xcc, dev_mondo
 	.align	32
 	.endm

==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/interrupt.S#4 (text+ko) ====

@@ -27,6 +27,8 @@
 #include <machine/asm.h>
 __FBSDID("$FreeBSD: src/sys/sparc64/sparc64/interrupt.S,v 1.8 2005/04/16 15:05:56 marius Exp $");
 
+#include "opt_simulator.h"
+#include <machine/hypervisorvar.h>
 #include <machine/asi.h>
 #include <machine/asmacros.h>
 #include <machine/ktr.h>
@@ -79,3 +81,267 @@
 	ba,a	%xcc, 1b
 	 nop
 END(intr_fast)
+
+/*
+ * Running tally of invalid CPU mondo interrupts
+ */
+#if defined(lint)
+uint64_t cpu_mondo_invalid;
+#else /* lint */
+        .data
+        .globl cpu_mondo_invalid
+        .align  8
+cpu_mondo_invalid:
+        .skip   8
+
+        .text
+#endif  /* lint */
+
+#if defined(lint)
+void
+cpu_mondo(void)
+{}
+#else   /* lint */
+
+/*
+ * (TT 0x7c, TL>0) CPU Mondo Queue Handler
+ *      Globals are the Interrupt Globals.
+ *
+ * Interrupts in sun4v are delivered to privileged code in the form 
+ * of interrupt reports.  Each interrupt report is 64-bytes long, 
+ * consisting of 8 64-bit words.  Each interrupt report is appended 
+ * onto the appropriate interrupt queue of which there are currently two,
+ * one for CPU mondos (formerly referred to as cross trap function
+ * requests) and one for device mondos.  Each queue has its own 
+ * trap vector.
+ *
+ * New reports are appended onto the tail of the queue, and privileged
+ * code reads the report from the queue's head.  The head pointer is stored
+ * in a register and is equal to the current offset from the base address 
+ * of its associated queue.  
+ *
+ * The structure of the cpu mondo report follows sun4u conventions:
+ *
+ * word 0:	address of cross-trap handler
+ * word 1:	first argument to handler
+ * word 2:	second argument to handler
+ * word 3-7:	unused
+ *
+ * Privileged code is responsible for incrementing the head pointer 
+ * to remove each entry.  The pointers are updated using modulo
+ * arithmetic such that the queue is empty when head == tail and is full
+ * when the addition of an entry would make head == tail. 
+ * 
+ * This trap handler is called when the cpu mondo queue becomes non-empty
+ * and will continue to be called while interrupts enabled until the 
+ * queue becomes empty.
+ *
+ */
+ENTRY(cpu_mondo)
+	MAGIC_TRAP_ON
+        !
+        !       Register Usage:-
+        !       %g5     PC for fasttrap TL>0 handler
+        !       %g1     arg 1   
+        !       %g2     arg 2
+        !       %g3     queue base VA 
+        !       %g4     queue size mask
+        !       %g6     head ptr
+        mov     CPU_MONDO_QUEUE_HEAD, %g1     
+        ldxa    [%g1]ASI_QUEUE, %g6     ! %g6 = head ptr 
+        mov     CPU_MONDO_QUEUE_TAIL, %g2     
+        ldxa    [%g2]ASI_QUEUE, %g4     ! %g4 = tail ptr 
+        cmp     %g6, %g4
+        be,pn   %xcc, 0f                ! head == tail
+        nop
+
+	/*
+	 * Get the address of the current CPU and index into
+	 * the pcpu structure for the Q values.
+	 */
+	GET_PCPU_SCRATCH
+	ldx	[PCPU(CPU_Q_RA)], %g3		! %g3 = queue base PA
+	ldx	[PCPU(CPU_Q_SIZE)], %g4		! %g4 = queue size
+        sub     %g4, 1, %g4             	! %g4 = queue size mask 
+
+        ! Load interrupt receive data registers 1 and 2 to fetch
+        ! the arguments for the fast trap handler.
+        !
+        ! Since the data words in the interrupt report are not defined yet 
+        ! we assume that the consective words contain valid data and preserve
+        ! sun4u's xcall mondo arguments. 
+        ! Register usage:
+        !       %g5     PC for fasttrap TL>0 handler
+        !       %g1     arg 1   
+        !       %g2     arg 2   
+
+        ldxa    [%g3 + %g6]ASI_REAL, %g5 	! get PC from q base + head
+        add     %g6, 0x8, %g6           	! inc head 8 bytes
+        ldxa    [%g3 + %g6]ASI_REAL, %g1 	! read data word 1
+        add     %g6, 0x8, %g6           	! inc head 8 bytes
+        ldxa    [%g3 + %g6]ASI_REAL, %g2 	! read data word 2
+        add     %g6, (INTR_REPORT_SIZE - 16) , %g6 
+						! inc head to next record
+
+        and     %g6, %g4, %g6           ! and size mask for wrap around 
+        mov     CPU_MONDO_QUEUE_HEAD, %g3     
+        stxa    %g6, [%g3]ASI_QUEUE     ! store head pointer 
+        membar  #Sync
+
+        /*
+         * For now catch invalid PC being passed via cpu_mondo queue
+         */
+        set     KERNBASE, %g4
+        cmp     %g5, %g4
+        bl,a,pn %xcc, 1f                ! branch if bad %pc
+        nop
+
+        jmp     %g5                     ! jump to traphandler
+        nop
+1:
+        ! invalid trap handler, discard it for now
+        set     cpu_mondo_invalid, %g4
+        ldx     [%g4], %g5
+        inc     %g5
+        stx     %g5, [%g4]
+0:
+        retry
+        /* NOTREACHED */
+END(cpu_mondo)
+
+#endif /* lint */
+
+
+#if defined(lint)
+void
+dev_mondo(void)
+{}
+#else   /* lint */
+
+/*
+ * (TT 0x7d, TL>0) Dev Mondo Queue Handler
+ *      Globals are the Interrupt Globals.
+ *
+ * Device interrupt reports take the following form:
+ * Bits:   	63		11 10		6 5		0
+ * word 0: 	|   zero	 | |  bus port  | | device ID 	|
+ * word 1-7: 			unused
+ *
+ */
+ENTRY(dev_mondo)
+        /*
+         *       Register Usage:-
+         *       %g5     inum
+         *       %g1     ptr to intrerrupt vector entry for inum
+         *       %g3     queue base PA 
+         *       %g4     queue size mask
+         *       %g6     head ptr
+	 */
+        mov     DEV_MONDO_QUEUE_HEAD, %g1     
+        ldxa    [%g1]ASI_QUEUE, %g6     	! %g6 = head ptr 
+        mov     DEV_MONDO_QUEUE_TAIL, %g2     
+        ldxa    [%g2]ASI_QUEUE, %g4     	! %g4 = tail ptr 
+        cmp     %g6, %g4
+        be,pn   %xcc, 0f                	! head == tail
+        nop
+
+	/*
+	 * Get CPU address and index to Q base
+	 */
+	GET_PCPU_SCRATCH
+        ldx     [PCPU(DEV_Q_RA)], %g3  		! %g3 = queue base PA
+
+        /*
+	 *  Register usage:
+         *       %g5 - inum
+         */
+        ldxa    [%g3 + %g6]ASI_REAL, %g5 	! %g5 = inum from q base + head
+
+        /*
+         * We verify that inum is valid ( < IV_MAX). If it is greater
+         * than IV_MAX, we let the software interrupt handler take care
+	 * of it.
+	 */
+        set     IV_MAX, %g4
+        cmp     %g5, %g4
+        bgeu,a,pn       %xcc, 1f
+        ldx     [PCPU(DEV_Q_SIZE)], %g4		! queue size (delay slot)
+
+        /*
+	 * Find the function, argument and desired priority from the
+	 * intr_vectors table
+	 */
+        set     intr_vectors, %g1
+        sll     %g5, IV_SHIFT, %g2
+        add     %g1, %g2, %g1                   ! %g1 = &intr_vectors[inum]
+
+        /*
+         * Get an intr_request from the free list.  There should always be one
+         * unless we are getting an interrupt storm from stray interrupts, in
+         * which case the we will dereference a NULL pointer and panic.
+         */
+	ldx	[PCPU(IRFREE)], %g2		! %g2 = ptr to tail element
+
+	/*
+	 * Sun4v-fixme: It might be better to have the software interrupt
+	 * handler deal with this scenario rather than just panic.
+	 */
+	!brz,a,pt        %g2, 1f
+	!ldx     [PCPU(DEV_Q_SIZE)], %g4	! queue size (delay slot)
+
+	ldx	[%g2 + IR_NEXT], %g3		! %g3 = next element in list
+	stx	%g3, [PCPU(IRFREE)]		! %g3 is now the tail
+
+	/*
+	 * Store the vector number, function, argument, and priority.
+	 */
+	stw	%g5, [%g2 + IR_VEC]
+	ldx     [%g1 + IV_FUNC], %g3		! %g3 = function ptr
+	stx	%g3, [%g2 + IR_FUNC]
+	ldx	[%g1 + IV_ARG], %g3		! %g3 = argument ptr
+	stx	%g3, [%g2 + IR_ARG]
+	lduw	[%g1 + IV_PRI], %g1		! %g1 = priority
+	stw	%g1, [%g2 + IR_PRI]
+
+	/*
+	 * Link it onto the end of the active list
+	 */
+	stx	%g0, [%g2 + IR_NEXT]
+	ldx	[PCPU(IRTAIL)], %g3		! %g3 = ptr to tail
+	stx	%g2, [%g3]
+	add	%g2, IR_NEXT, %g2
+	stx	%g2, [PCPU(IRTAIL)]
+	
+ 	/* 
+	 * Unlike Solaris, FreeBSD throws away the rest of the 
+	 * 64-byte packet.  We may want to revisit this philosophy
+	 * at some point since information in the packet is defined by 
+	 * the device and MAY be meaningful.
+	 *
+	 * For now, we retain FreeBSD's sun4u semantics.
+	 */
+        ldx     [PCPU(DEV_Q_SIZE)], %g4		! queue size
+
+1:      sub     %g4, 1, %g4             	! %g4 = queue size mask 
+        add     %g6, INTR_REPORT_SIZE, %g6 	! inc head to next record   
+        and     %g6, %g4, %g6           	! and mask for wrap around      
+        mov     DEV_MONDO_QUEUE_HEAD, %g3     
+        stxa    %g6, [%g3]ASI_QUEUE     	! increment head offset 
+        membar  #Sync
+
+	/*
+	 * Trigger a softint at the level indicated by the priority
+	 */
+	mov	1, %g6
+	sllx	%g6, %g1, %g6
+	wr	%g6, 0, %set_softint
+
+	/*
+	 * Done, retry the instruction	
+	 */
+0:      retry 
+
+        /* NOTREACHED */
+END(dev_mondo)
+#endif /* lint */
+


More information about the p4-projects mailing list