[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [IA64] Final patch to make evtchn fully working for xen/ia64
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID f0f88d9c4c9ede9c37b15a46f790d81f7648518a # Parent 5be25952b50d362f945db9e997c48f76d209cc36 [IA64] Final patch to make evtchn fully working for xen/ia64 OK, this is the last one of patch sets, which enables xen/ia64 to work on event channel mechanism fully. Now user may observe /proc/interrupts of dom0 as: CPU0 34: 12 Phys-irq ide0 39: 0 Phys-irq acpi 45: 322 Phys-irq serial 48: 115006 Phys-irq peth0 49: 16269 Phys-irq ioc0 50: 31 Phys-irq ioc1 51: 2 Phys-irq ehci_hcd:usb1 52: 0 Phys-irq uhci_hcd:usb2 53: 55 Phys-irq uhci_hcd:usb3 256: 0 Dynamic-irq RESCHED0 257: 0 Dynamic-irq IPI0 258: 44572 Dynamic-irq timer0 259: 2316 Dynamic-irq xenbus 260: 8304 Dynamic-irq blkif-backend 261: 25947 Dynamic-irq vif3.0 ERR: 0 Based on this patch, dom0's performance is not affected, while domU's network output is seen with several percents increase. More important, now xen/ia64 can progress a base step towards driver domain support! Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx> --- linux-2.6-xen-sparse/arch/ia64/kernel/iosapic.c | 2 linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c | 191 +++++++++++++- linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 4 linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile | 2 linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c | 1 linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S | 29 ++ linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h | 8 linux-2.6-xen-sparse/include/asm-ia64/irq.h | 31 ++ xen/arch/ia64/linux-xen/entry.S | 17 - xen/arch/ia64/xen/hyperprivop.S | 5 xen/arch/ia64/xen/irq.c | 8 11 files changed, 277 insertions(+), 21 deletions(-) diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/arch/ia64/kernel/iosapic.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/iosapic.c Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/iosapic.c Tue May 23 09:17:57 2006 -0600 @@ -670,6 +670,7 @@ register_intr (unsigned int gsi, int vec iosapic_intr_info[vector].dmode = delivery; iosapic_intr_info[vector].trigger = trigger; +#ifndef CONFIG_XEN if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; else @@ -682,6 +683,7 @@ register_intr (unsigned int gsi, int vec __FUNCTION__, vector, idesc->handler->typename, irq_type->typename); idesc->handler = irq_type; } +#endif return 0; } diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c Tue May 23 09:17:57 2006 -0600 @@ -229,6 +229,150 @@ static struct irqaction ipi_irqaction = }; #endif +#ifdef CONFIG_XEN +#include <xen/evtchn.h> +#include <xen/interface/callback.h> + +static char timer_name[NR_CPUS][15]; +static char ipi_name[NR_CPUS][15]; +static char resched_name[NR_CPUS][15]; + +struct saved_irq { + unsigned int irq; + struct irqaction *action; +}; +/* 16 should be far optimistic value, since only several percpu irqs + * are registered early. + */ +#define MAX_LATE_IRQ 16 +static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ]; +static unsigned short late_irq_cnt = 0; +static unsigned short saved_irq_cnt = 0; +static int xen_slab_ready = 0; + +/* Dummy stub. Though we may check RESCHEDULE_VECTOR before __do_IRQ, + * it ends up to issue several memory accesses upon percpu data and + * thus adds unnecessary traffic to other paths. + */ +irqreturn_t handle_reschedule(int irq, void *dev_id, struct pt_regs *regs) +{ + + return IRQ_HANDLED; +} + +static struct irqaction resched_irqaction = { + .handler = handle_reschedule, + .flags = SA_INTERRUPT, + .name = "RESCHED" +}; + +/* + * This is xen version percpu irq registration, which needs bind + * to xen specific evtchn sub-system. One trick here is that xen + * evtchn binding interface depends on kmalloc because related + * port needs to be freed at device/cpu down. So we cache the + * registration on BSP before slab is ready and then deal them + * at later point. For rest instances happening after slab ready, + * we hook them to xen evtchn immediately. + * + * FIXME: MCA is not supported by far, and thus "nomca" boot param is + * required. + */ +void +xen_register_percpu_irq (unsigned int irq, struct irqaction *action, int save) +{ + char name[15]; + unsigned int cpu = smp_processor_id(); + int ret = 0; + + if (xen_slab_ready) { + switch (irq) { + case IA64_TIMER_VECTOR: + sprintf(timer_name[cpu], "%s%d", action->name, cpu); + ret = bind_virq_to_irqhandler(VIRQ_ITC, cpu, + action->handler, action->flags, + timer_name[cpu], action->dev_id); + printk(KERN_INFO "register VIRQ_ITC (%s) to xen irq (%d)\n", name, ret); + break; + case IA64_IPI_RESCHEDULE: + sprintf(resched_name[cpu], "%s%d", action->name, cpu); + ret = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu, + action->handler, action->flags, + resched_name[cpu], action->dev_id); + printk(KERN_INFO "register RESCHEDULE_VECTOR (%s) to xen irq (%d)\n", name, ret); + break; + case IA64_IPI_VECTOR: + sprintf(ipi_name[cpu], "%s%d", action->name, cpu); + ret = bind_ipi_to_irqhandler(IPI_VECTOR, cpu, + action->handler, action->flags, + ipi_name[cpu], action->dev_id); + printk(KERN_INFO "register IPI_VECTOR (%s) to xen irq (%d)\n", name, ret); + break; + default: + printk(KERN_WARNING "Percpu irq %d is unsupported by xen!\n", irq); + break; + } + BUG_ON(ret < 0); + } + + /* For BSP, we cache registered percpu irqs, and then re-walk + * them when initializing APs + */ + if (!cpu && save) { + BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); + saved_percpu_irqs[saved_irq_cnt].irq = irq; + saved_percpu_irqs[saved_irq_cnt].action = action; + saved_irq_cnt++; + if (!xen_slab_ready) + late_irq_cnt++; + } +} + +void +xen_bind_early_percpu_irq (void) +{ + int i; + + xen_slab_ready = 1; + /* There's no race when accessing this cached array, since only + * BSP will face with such step shortly + */ + for (i = 0; i < late_irq_cnt; i++) + xen_register_percpu_irq(saved_percpu_irqs[i].irq, + saved_percpu_irqs[i].action, 0); +} + +/* FIXME: There's no obvious point to check whether slab is ready. So + * a hack is used here by utilizing a late time hook. + */ +extern void (*late_time_init)(void); +extern char xen_event_callback; +extern void xen_init_IRQ(void); + +DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]); +void xen_smp_intr_init(void) +{ +#ifdef CONFIG_SMP + unsigned int cpu = smp_processor_id(); + unsigned int i = 0; + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = (unsigned long)&xen_event_callback, + }; + + if (!cpu) + return; + + /* This should be piggyback when setup vcpu guest context */ + BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); + + for (i = 0; i < saved_irq_cnt; i++) + xen_register_percpu_irq(saved_percpu_irqs[i].irq, + saved_percpu_irqs[i].action, 0); +#endif /* CONFIG_SMP */ +} +#endif /* CONFIG_XEN */ + void register_percpu_irq (ia64_vector vec, struct irqaction *action) { @@ -237,6 +381,10 @@ register_percpu_irq (ia64_vector vec, st for (irq = 0; irq < NR_IRQS; ++irq) if (irq_to_vector(irq) == vec) { +#ifdef CONFIG_XEN + if (running_on_xen) + return xen_register_percpu_irq(vec, action, 1); +#endif desc = irq_descp(irq); desc->status |= IRQ_PER_CPU; desc->handler = &irq_type_ia64_lsapic; @@ -248,7 +396,21 @@ void __init void __init init_IRQ (void) { +#ifdef CONFIG_XEN + /* Maybe put into platform_irq_init later */ + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = (unsigned long)&xen_event_callback, + }; + xen_init_IRQ(); + BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); + late_time_init = xen_bind_early_percpu_irq; +#ifdef CONFIG_SMP + register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); +#endif +#else /* CONFIG_XEN */ register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL); +#endif /* CONFIG_XEN */ #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); #endif @@ -267,9 +429,32 @@ ia64_send_ipi (int cpu, int vector, int #ifdef CONFIG_XEN if (running_on_xen) { - extern void xen_send_ipi (int cpu, int vec); - xen_send_ipi (cpu, vector); - return; + int irq = -1; + + /* TODO: we need to call vcpu_up here */ + if (unlikely(vector == ap_wakeup_vector)) { + extern void xen_send_ipi (int cpu, int vec); + xen_send_ipi (cpu, vector); + //vcpu_prepare_and_up(cpu); + return; + } + + switch(vector) { + case IA64_IPI_VECTOR: + irq = per_cpu(ipi_to_irq, cpu)[IPI_VECTOR]; + break; + case IA64_IPI_RESCHEDULE: + irq = per_cpu(ipi_to_irq, cpu)[RESCHEDULE_VECTOR]; + break; + default: + printk(KERN_WARNING"Unsupported IPI type 0x%x\n", vector); + irq = 0; + break; + } + + BUG_ON(irq < 0); + notify_remote_via_irq(irq); + return; } #endif /* CONFIG_XEN */ diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/arch/ia64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Tue May 23 09:17:57 2006 -0600 @@ -923,6 +923,10 @@ cpu_init (void) /* size of physical stacked register partition plus 8 bytes: */ __get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8; platform_cpu_init(); +#ifdef CONFIG_XEN + /* Need to be moved into platform_cpu_init later */ + xen_smp_intr_init(); +#endif pm_idle = default_idle; } diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile Tue May 23 09:17:57 2006 -0600 @@ -6,7 +6,7 @@ obj-$(CONFIG_PROC_FS) += xen_proc.o obj-$(CONFIG_PROC_FS) += xen_proc.o ifeq ($(ARCH),ia64) -obj-y += evtchn_ia64.o +obj-y += evtchn.o obj-y += xenia64_init.o ifeq ($(CONFIG_XEN_IA64_DOM0_VP),y) obj-$(CONFIG_NET) += skbuff.o diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c Tue May 23 09:17:57 2006 -0600 @@ -33,7 +33,6 @@ int xen_init(void) s->arch.start_info_pfn, xen_start_info->nr_pages, xen_start_info->flags); - evtchn_init(); initialized = 1; return 0; } diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenivt.S Tue May 23 09:17:57 2006 -0600 @@ -2130,5 +2130,32 @@ non_ia32_syscall: mov rp=r15 br.ret.sptk.many rp END(dispatch_to_ia32_handler) - #endif /* CONFIG_IA32_SUPPORT */ + +#ifdef CONFIG_XEN + .section .text,"ax" +GLOBAL_ENTRY(xen_event_callback) + mov r31=pr // prepare to save predicates + ;; + SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 + ;; + movl r3=XSI_PSR_IC + mov r14=1 + ;; + st4 [r3]=r14 + ;; + adds r3=8,r2 // set up second base pointer for SAVE_REST + srlz.i // ensure everybody knows psr.ic is back on + ;; + SAVE_REST + ;; + alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group + add out0=16,sp // pass pointer to pt_regs as first arg + ;; + srlz.d // make sure we see the effect of cr.ivr + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.call.sptk.many b6=evtchn_do_upcall +END(xen_event_callback) +#endif diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h Tue May 23 09:17:57 2006 -0600 @@ -15,7 +15,11 @@ #include <asm/ptrace.h> #include <asm/smp.h> +#ifndef CONFIG_XEN typedef u8 ia64_vector; +#else +typedef u16 ia64_vector; +#endif /* * 0 special @@ -86,11 +90,15 @@ extern void ia64_send_ipi (int cpu, int extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); +#ifndef CONFIG_XEN static inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int vector) { platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); } +#else +extern void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i); +#endif /* CONFIG_XEN */ /* * Default implementations for the irq-descriptor API: diff -r 5be25952b50d -r f0f88d9c4c9e linux-2.6-xen-sparse/include/asm-ia64/irq.h --- a/linux-2.6-xen-sparse/include/asm-ia64/irq.h Tue May 23 08:56:13 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-ia64/irq.h Tue May 23 09:17:57 2006 -0600 @@ -11,8 +11,39 @@ * 02/29/00 D.Mosberger moved most things into hw_irq.h */ +#ifndef CONFIG_XEN #define NR_IRQS 256 #define NR_IRQ_VECTORS NR_IRQS +#else +/* + * The flat IRQ space is divided into two regions: + * 1. A one-to-one mapping of real physical IRQs. This space is only used + * if we have physical device-access privilege. This region is at the + * start of the IRQ space so that existing device drivers do not need + * to be modified to translate physical IRQ numbers into our IRQ space. + * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These + * are bound using the provided bind/unbind functions. + */ + +#define PIRQ_BASE 0 +#define NR_PIRQS 256 + +#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS) +#define NR_DYNIRQS 256 + +#define NR_IRQS (NR_PIRQS + NR_DYNIRQS) +#define NR_IRQ_VECTORS NR_IRQS + +#define pirq_to_irq(_x) ((_x) + PIRQ_BASE) +#define irq_to_pirq(_x) ((_x) - PIRQ_BASE) + +#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE) +#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE) + +#define RESCHEDULE_VECTOR 0 +#define IPI_VECTOR 1 +#define NR_IPIS 2 +#endif /* CONFIG_XEN */ /* * IRQ line status macro IRQ_PER_CPU is used diff -r 5be25952b50d -r f0f88d9c4c9e xen/arch/ia64/linux-xen/entry.S --- a/xen/arch/ia64/linux-xen/entry.S Tue May 23 08:56:13 2006 -0600 +++ b/xen/arch/ia64/linux-xen/entry.S Tue May 23 09:17:57 2006 -0600 @@ -906,17 +906,12 @@ GLOBAL_ENTRY(ia64_leave_kernel) ;; alloc loc0=ar.pfs,0,1,1,0 adds out0=16,r12 - adds r7 = PT(EML_UNAT)+16,r12 - ;; - ld8 r7 = [r7] - ;; -#if 0 -leave_kernel_self: - cmp.ne p8,p0 = r0, r7 -(p8) br.sptk.few leave_kernel_self - ;; -#endif -(pUStk) br.call.sptk.many b0=deliver_pending_interrupt + adds r7 = PT(EML_UNAT)+16,r12 + ;; + ld8 r7 = [r7] + ;; +(pUStk) br.call.sptk.many b0=reflect_event +//(pUStk) br.call.sptk.many b0=deliver_pending_interrupt ;; mov ar.pfs=loc0 mov ar.unat=r7 /* load eml_unat */ diff -r 5be25952b50d -r f0f88d9c4c9e xen/arch/ia64/xen/hyperprivop.S --- a/xen/arch/ia64/xen/hyperprivop.S Tue May 23 08:56:13 2006 -0600 +++ b/xen/arch/ia64/xen/hyperprivop.S Tue May 23 09:17:57 2006 -0600 @@ -106,6 +106,11 @@ GLOBAL_ENTRY(fast_hyperprivop) or r23=r23,r24; or r21=r21,r22;; or r20=r23,r21;; 1: // when we get to here r20=~=interrupts pending + // Check pending event indication +(p7) adds r20=XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS,r18;; +(p7) ld8 r20=[r20];; +(p7) adds r20=-1,r20;; +(p7) ld1 r20=[r20];; // HYPERPRIVOP_RFI? cmp.eq p7,p6=HYPERPRIVOP_RFI,r17 diff -r 5be25952b50d -r f0f88d9c4c9e xen/arch/ia64/xen/irq.c --- a/xen/arch/ia64/xen/irq.c Tue May 23 08:56:13 2006 -0600 +++ b/xen/arch/ia64/xen/irq.c Tue May 23 09:17:57 2006 -0600 @@ -70,11 +70,13 @@ */ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { - .status = IRQ_DISABLED | IRQ_GUEST, + .status = IRQ_DISABLED, .handler = &no_irq_type, .lock = SPIN_LOCK_UNLOCKED } }; + +void __do_IRQ_guest(int irq); /* * Special irq handlers. @@ -167,9 +169,7 @@ fastcall unsigned int __do_IRQ(unsigned spin_lock(&desc->lock); if (desc->status & IRQ_GUEST) { - /* __do_IRQ_guest(irq); */ - vcpu_pend_interrupt(dom0->vcpu[0],irq); - vcpu_wake(dom0->vcpu[0]); + __do_IRQ_guest(irq); spin_unlock(&desc->lock); return 1; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |