Date: Sat, 25 Mar 2006 04:20:13 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 93959 for review Message-ID: <200603250420.k2P4KDXD046605@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=93959 Change 93959 by kmacy@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 */ +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603250420.k2P4KDXD046605>