From fd8719a93192f01e88303d3b5f42619aa04fed90 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 28 Mar 2006 18:43:30 +0100 Subject: [PATCH 001/151] Clean up and fix VCPU hotplug and SMP save/restore. 1. No longer hold xenbus_lock while taking down VCPUs in SMP suspend path. This allows block device hotplug to continue working and so we will not deadlock on paging in userspace hotplug code. 2. Track xenbus and local-admin permitted cpumasks for VCPUs to bring online. So, if a local admin takes a CPU down, that won't surprisingly get overridden next time the kernel interrogates xenstore. Signed-off-by: Keir Fraser --- .../drivers/xen/core/reboot.c | 107 +++------------ .../drivers/xen/core/smpboot.c | 123 +++++++++++++++++- .../drivers/xen/pciback/xenbus.c | 2 +- .../drivers/xen/xenbus/xenbus_xs.c | 29 ++++- linux-2.6-xen-sparse/include/xen/gnttab.h | 3 + linux-2.6-xen-sparse/include/xen/xenbus.h | 9 ++ 6 files changed, 176 insertions(+), 97 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index e63e40465d..f0f1d803a5 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #if defined(__i386__) || defined(__x86_64__) @@ -76,31 +77,24 @@ static int shutting_down = SHUTDOWN_INVALID; static void __shutdown_handler(void *unused); static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); -#ifndef CONFIG_HOTPLUG_CPU -#define cpu_down(x) (-EOPNOTSUPP) -#define cpu_up(x) (-EOPNOTSUPP) +#ifdef CONFIG_SMP +int smp_suspend(void); +void smp_resume(void); +#else +#define smp_suspend() (0) +#define smp_resume() ((void)0) #endif - static int __do_suspend(void *ignore) { - int i, j, k, fpp; + int i, j, k, fpp, err; extern unsigned long max_pfn; extern unsigned long *pfn_to_mfn_frame_list_list; extern unsigned long *pfn_to_mfn_frame_list[]; - extern int gnttab_suspend(void); - extern int gnttab_resume(void); extern void time_resume(void); -#ifdef CONFIG_SMP - cpumask_t prev_online_cpus; - int vcpu_prepare(int vcpu); -#endif - - int err = 0; - BUG_ON(smp_processor_id() != 0); BUG_ON(in_interrupt()); @@ -110,40 +104,12 @@ static int __do_suspend(void *ignore) return -EOPNOTSUPP; } -#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) - if (num_online_cpus() > 1) { - printk(KERN_WARNING "Can't suspend SMP guests " - "without CONFIG_HOTPLUG_CPU\n"); - return -EOPNOTSUPP; - } -#endif + err = smp_suspend(); + if (err) + return err; xenbus_suspend(); - lock_cpu_hotplug(); -#ifdef CONFIG_SMP - /* - * Take all other CPUs offline. We hold the hotplug mutex to - * avoid other processes bringing up CPUs under our feet. - */ - cpus_clear(prev_online_cpus); - while (num_online_cpus() > 1) { - for_each_online_cpu(i) { - if (i == 0) - continue; - unlock_cpu_hotplug(); - err = cpu_down(i); - lock_cpu_hotplug(); - if (err != 0) { - printk(KERN_CRIT "Failed to take all CPUs " - "down: %d.\n", err); - goto out_reenable_cpus; - } - cpu_set(i, prev_online_cpus); - } - } -#endif - preempt_disable(); #ifdef __i386__ @@ -153,7 +119,6 @@ static int __do_suspend(void *ignore) __cli(); preempt_enable(); - unlock_cpu_hotplug(); gnttab_suspend(); @@ -203,30 +168,9 @@ static int __do_suspend(void *ignore) xencons_resume(); -#ifdef CONFIG_SMP - for_each_cpu(i) - vcpu_prepare(i); - -#endif - - /* - * Only resume xenbus /after/ we've prepared our VCPUs; otherwise - * the VCPU hotplug callback can race with our vcpu_prepare - */ xenbus_resume(); -#ifdef CONFIG_SMP - out_reenable_cpus: - for_each_cpu_mask(i, prev_online_cpus) { - j = cpu_up(i); - if ((j != 0) && !cpu_online(i)) { - printk(KERN_CRIT "Failed to bring cpu " - "%d back up (%d).\n", - i, j); - err = j; - } - } -#endif + smp_resume(); return err; } @@ -334,7 +278,6 @@ static void shutdown_handler(struct xenbus_watch *watch, kfree(str); } -#ifdef CONFIG_MAGIC_SYSRQ static void sysrq_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { @@ -360,45 +303,35 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec, if (err == -EAGAIN) goto again; - if (sysrq_key != '\0') { +#ifdef CONFIG_MAGIC_SYSRQ + if (sysrq_key != '\0') handle_sysrq(sysrq_key, NULL, NULL); - } -} #endif +} static struct xenbus_watch shutdown_watch = { .node = "control/shutdown", .callback = shutdown_handler }; -#ifdef CONFIG_MAGIC_SYSRQ static struct xenbus_watch sysrq_watch = { .node ="control/sysrq", .callback = sysrq_handler }; -#endif static int setup_shutdown_watcher(struct notifier_block *notifier, unsigned long event, void *data) { - int err1 = 0; -#ifdef CONFIG_MAGIC_SYSRQ - int err2 = 0; -#endif + int err; - err1 = register_xenbus_watch(&shutdown_watch); -#ifdef CONFIG_MAGIC_SYSRQ - err2 = register_xenbus_watch(&sysrq_watch); -#endif - - if (err1) + err = register_xenbus_watch(&shutdown_watch); + if (err) printk(KERN_ERR "Failed to set shutdown watcher\n"); -#ifdef CONFIG_MAGIC_SYSRQ - if (err2) + err = register_xenbus_watch(&sysrq_watch); + if (err) printk(KERN_ERR "Failed to set sysrq watcher\n"); -#endif return NOTIFY_DONE; } diff --git a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c index fb0b822b5c..1f588c59ee 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c @@ -79,6 +79,15 @@ EXPORT_SYMBOL(x86_cpu_to_apicid); unsigned int maxcpus = NR_CPUS; #endif +/* + * Set of CPUs that remote admin software will allow us to bring online. + * Notified to us via xenbus. + */ +static cpumask_t xenbus_allowed_cpumask; + +/* Set of CPUs that local admin will allow us to bring online. */ +static cpumask_t local_allowed_cpumask = CPU_MASK_ALL; + void __init prefill_possible_map(void) { int i, rc; @@ -146,7 +155,7 @@ static void cpu_bringup(void) cpu_idle(); } -void vcpu_prepare(int vcpu) +static void vcpu_prepare(int vcpu) { vcpu_guest_context_t ctxt; struct task_struct *idle = idle_task(vcpu); @@ -278,6 +287,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) vcpu_prepare(cpu); } + xenbus_allowed_cpumask = cpu_present_map; + /* Currently, Xen gives no dynamic NUMA/HT info. */ for (cpu = 1; cpu < NR_CPUS; cpu++) { cpu_sibling_map[cpu] = cpumask_of_cpu(cpu); @@ -301,6 +312,15 @@ void __devinit smp_prepare_boot_cpu(void) cpu_online_map = cpumask_of_cpu(0); } +static int local_cpu_hotplug_request(void) +{ + /* + * We assume a CPU hotplug request comes from local admin if it is made + * via a userspace process (i.e., one with a real mm_struct). + */ + return (current->mm != NULL); +} + #ifdef CONFIG_HOTPLUG_CPU /* @@ -331,8 +351,10 @@ static void vcpu_hotplug(unsigned int cpu) } if (strcmp(state, "online") == 0) { + cpu_set(cpu, xenbus_allowed_cpumask); (void)cpu_up(cpu); } else if (strcmp(state, "offline") == 0) { + cpu_clear(cpu, xenbus_allowed_cpumask); (void)cpu_down(cpu); } else { printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", @@ -353,6 +375,22 @@ static void handle_vcpu_hotplug_event( } } +static int smpboot_cpu_notify(struct notifier_block *notifier, + unsigned long action, void *hcpu) +{ + int cpu = (long)hcpu; + + /* + * We do this in a callback notifier rather than __cpu_disable() + * because local_cpu_hotplug_request() does not work in the latter + * as it's always executed from within a stopmachine kthread. + */ + if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request()) + cpu_clear(cpu, local_allowed_cpumask); + + return NOTIFY_OK; +} + static int setup_cpu_watcher(struct notifier_block *notifier, unsigned long event, void *data) { @@ -360,7 +398,8 @@ static int setup_cpu_watcher(struct notifier_block *notifier, static struct xenbus_watch cpu_watch = { .node = "cpu", - .callback = handle_vcpu_hotplug_event }; + .callback = handle_vcpu_hotplug_event, + .flags = XBWF_new_thread }; (void)register_xenbus_watch(&cpu_watch); if (!(xen_start_info->flags & SIF_INITDOMAIN)) { @@ -375,14 +414,62 @@ static int setup_cpu_watcher(struct notifier_block *notifier, static int __init setup_vcpu_hotplug_event(void) { + static struct notifier_block hotplug_cpu = { + .notifier_call = smpboot_cpu_notify }; static struct notifier_block xsn_cpu = { .notifier_call = setup_cpu_watcher }; + + register_cpu_notifier(&hotplug_cpu); register_xenstore_notifier(&xsn_cpu); + return 0; } arch_initcall(setup_vcpu_hotplug_event); +int smp_suspend(void) +{ + int i, err; + + lock_cpu_hotplug(); + + /* + * Take all other CPUs offline. We hold the hotplug mutex to + * avoid other processes bringing up CPUs under our feet. + */ + while (num_online_cpus() > 1) { + unlock_cpu_hotplug(); + for_each_online_cpu(i) { + if (i == 0) + continue; + err = cpu_down(i); + if (err) { + printk(KERN_CRIT "Failed to take all CPUs " + "down: %d.\n", err); + for_each_cpu(i) + vcpu_hotplug(i); + return err; + } + } + lock_cpu_hotplug(); + } + + return 0; +} + +void smp_resume(void) +{ + int i; + + for_each_cpu(i) + vcpu_prepare(i); + + unlock_cpu_hotplug(); + + for_each_cpu(i) + vcpu_hotplug(i); +} + int __cpu_disable(void) { cpumask_t map = cpu_online_map; @@ -415,6 +502,20 @@ void __cpu_die(unsigned int cpu) #else /* !CONFIG_HOTPLUG_CPU */ +int smp_suspend(void) +{ + if (num_online_cpus() > 1) { + printk(KERN_WARNING "Can't suspend SMP guests " + "without CONFIG_HOTPLUG_CPU\n"); + return -EOPNOTSUPP; + } + return 0; +} + +void smp_resume(void) +{ +} + int __cpu_disable(void) { return -ENOSYS; @@ -429,6 +530,20 @@ void __cpu_die(unsigned int cpu) int __devinit __cpu_up(unsigned int cpu) { + int rc; + + if (local_cpu_hotplug_request()) { + cpu_set(cpu, local_allowed_cpumask); + if (!cpu_isset(cpu, xenbus_allowed_cpumask)) { + printk("%s: attempt to bring up CPU %u disallowed by " + "remote admin.\n", __FUNCTION__, cpu); + return -EBUSY; + } + } else if (!cpu_isset(cpu, local_allowed_cpumask) || + !cpu_isset(cpu, xenbus_allowed_cpumask)) { + return -EBUSY; + } + #ifdef CONFIG_SMP_ALTERNATIVES if (num_online_cpus() == 1) prepare_for_smp(); @@ -436,7 +551,9 @@ int __devinit __cpu_up(unsigned int cpu) xen_smp_intr_init(cpu); cpu_set(cpu, cpu_online_map); - if (HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL) != 0) + + rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); + if (rc != 0) BUG(); return 0; diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c index f338de1f37..c64d250067 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c @@ -16,7 +16,7 @@ static struct pciback_device *alloc_pdev(struct xenbus_device *xdev) { struct pciback_device *pdev; - pdev = kmalloc(sizeof(struct pciback_device), GFP_KERNEL); + pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL); if (pdev == NULL) goto out; dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index 7e343eff21..2cb2e97a87 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -685,6 +685,24 @@ void xs_resume(void) up_write(&xs_state.suspend_mutex); } +static int xenwatch_handle_callback(void *data) +{ + struct xs_stored_msg *msg = data; + + msg->u.watch.handle->callback(msg->u.watch.handle, + (const char **)msg->u.watch.vec, + msg->u.watch.vec_size); + + kfree(msg->u.watch.vec); + kfree(msg); + + /* Kill this kthread if we were spawned just for this callback. */ + if (current->pid != xenwatch_pid) + do_exit(0); + + return 0; +} + static int xenwatch_thread(void *unused) { struct list_head *ent; @@ -707,12 +725,11 @@ static int xenwatch_thread(void *unused) if (ent != &watch_events) { msg = list_entry(ent, struct xs_stored_msg, list); - msg->u.watch.handle->callback( - msg->u.watch.handle, - (const char **)msg->u.watch.vec, - msg->u.watch.vec_size); - kfree(msg->u.watch.vec); - kfree(msg); + if (msg->u.watch.handle->flags & XBWF_new_thread) + kthread_run(xenwatch_handle_callback, + msg, "xenwatch_cb"); + else + xenwatch_handle_callback(msg); } mutex_unlock(&xenwatch_mutex); diff --git a/linux-2.6-xen-sparse/include/xen/gnttab.h b/linux-2.6-xen-sparse/include/xen/gnttab.h index 584a5db355..e9fd1b63ae 100644 --- a/linux-2.6-xen-sparse/include/xen/gnttab.h +++ b/linux-2.6-xen-sparse/include/xen/gnttab.h @@ -110,6 +110,9 @@ void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) #endif +int gnttab_suspend(void); +int gnttab_resume(void); + #endif /* __ASM_GNTTAB_H__ */ /* diff --git a/linux-2.6-xen-sparse/include/xen/xenbus.h b/linux-2.6-xen-sparse/include/xen/xenbus.h index 122480584f..6d69963870 100644 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h @@ -55,8 +55,17 @@ struct xenbus_watch /* Callback (executed in a process context with no locks held). */ void (*callback)(struct xenbus_watch *, const char **vec, unsigned int len); + + /* See XBWF_ definitions below. */ + unsigned long flags; }; +/* + * Execute callback in its own kthread. Useful if the callback is long + * running or heavily serialised, to avoid taking out the main xenwatch thread + * for a long period of time (or even unwittingly causing a deadlock). + */ +#define XBWF_new_thread 1 /* A xenbus device. */ struct xenbus_device { From 57f82067cf679f7e3fa2d5d37fbaa233ff4cebcf Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 28 Mar 2006 21:21:26 +0100 Subject: [PATCH 002/151] Fix get_page_type() when passed PGT_va_mutable. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 4977a6d2da..564d7e6f98 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1528,10 +1528,9 @@ int get_page_type(struct page_info *page, unsigned long type) nx &= ~PGT_va_mask; nx |= type; /* we know the actual type is correct */ } - else + else if ( (type & PGT_va_mask) != PGT_va_mutable ) { ASSERT((type & PGT_va_mask) != (x & PGT_va_mask)); - ASSERT((type & PGT_va_mask) != PGT_va_mutable); #ifdef CONFIG_X86_PAE /* We use backptr as extra typing. Cannot be unknown. */ if ( (type & PGT_type_mask) == PGT_l2_page_table ) From f73e4555d65cfa4e99186593593f104333109a7f Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 10:46:36 +0100 Subject: [PATCH 003/151] Initialise p2m entries to INVALID_MFN and disable debug printk in pfn to mfn lookup. Signed-off-by: Christian Limpach --- xen/arch/x86/shadow32.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/shadow32.c b/xen/arch/x86/shadow32.c index 89cac6e263..2bfae17ab7 100644 --- a/xen/arch/x86/shadow32.c +++ b/xen/arch/x86/shadow32.c @@ -924,7 +924,8 @@ set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn, } l1 = map_domain_page_with_cache(page_to_mfn(l1page), l1cache); - memset(l1, 0, PAGE_SIZE); + /* Initialise entries to INVALID_MFN = ~0 */ + memset(l1, -1, PAGE_SIZE); unmap_domain_page_with_cache(l1, l1cache); l2e = l2e_from_page(l1page, __PAGE_HYPERVISOR); @@ -1686,8 +1687,10 @@ get_mfn_from_gpfn_foreign(struct domain *d, unsigned long gpfn) unmap_domain_page(l2); if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) { +#if 0 printk("%s(d->id=%d, gpfn=%lx) => 0 l2e=%" PRIpte "\n", __func__, d->domain_id, gpfn, l2e_get_intpte(l2e)); +#endif return INVALID_MFN; } l1 = map_domain_page(l2e_get_pfn(l2e)); From 111ce84369db4f646df18d79f1bc8d9960323033 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 12:02:45 +0100 Subject: [PATCH 004/151] Some fixes to IRET hypercall and failsafe callback handlers: 1. IRET hypercall must restore the event callback mask. This was missing on x86/64, and both subarchitectures now restore from EFLAGS.IF. 2. Failsafe callbacks are fixed to detect whether fault is due to bad segment or due to IRET. In the latter case we now immediatiately kill the process. This avoids infinite looping between IRET hypercall and failsafe callback handler in the guest. Signed-off-by: Keir Fraser --- .../arch/i386/kernel/entry-xen.S | 83 +++++++++++-------- .../arch/x86_64/kernel/entry-xen.S | 60 ++++++++++---- .../arch/x86_64/kernel/xen_entry.S | 3 +- xen/arch/x86/x86_32/asm-offsets.c | 1 - xen/arch/x86/x86_32/traps.c | 4 +- xen/arch/x86/x86_64/asm-offsets.c | 1 - xen/arch/x86/x86_64/traps.c | 3 + 7 files changed, 99 insertions(+), 56 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S index 3d05727fdf..c1784979e3 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S @@ -65,7 +65,6 @@ ES = 0x20 ORIG_EAX = 0x24 EIP = 0x28 CS = 0x2C -EVENT_MASK = 0x2E EFLAGS = 0x30 OLDESP = 0x34 OLDSS = 0x38 @@ -290,14 +289,14 @@ restore_all: restore_nocheck: #else restore_nocheck: - testl $(VM_MASK|NMI_MASK), EFLAGS(%esp) + movl EFLAGS(%esp), %eax + testl $(VM_MASK|NMI_MASK), %eax jnz hypervisor_iret - movb EVENT_MASK(%esp), %al - notb %al # %al == ~saved_mask + shr $9, %eax # EAX[0] == IRET_EFLAGS.IF GET_VCPU_INFO andb evtchn_upcall_mask(%esi),%al - andb $1,%al # %al == mask & ~saved_mask - jnz restore_all_enable_events # != 0 => reenable event delivery + andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask + jnz restore_all_enable_events # != 0 => enable event delivery #endif RESTORE_REGS addl $4, %esp @@ -555,14 +554,9 @@ scrit: /**** START OF CRITICAL REGION ****/ RESTORE_REGS addl $4, %esp 1: iret -.section .fixup,"ax" -2: pushl $0 - pushl $do_iret_error - jmp error_code -.previous .section __ex_table,"a" .align 4 - .long 1b,2b + .long 1b,iret_exc .previous 14: __DISABLE_INTERRUPTS jmp 11b @@ -614,30 +608,51 @@ critical_fixup_table: .byte 0x00,0x00 # jmp 11b # Hypervisor uses this for application faults while it executes. +# We get here for two reasons: +# 1. Fault while reloading DS, ES, FS or GS +# 2. Fault while executing IRET +# Category 1 we fix up by reattempting the load, and zeroing the segment +# register if the load fails. +# Category 2 we fix up by jumping to do_iret_error. We cannot use the +# normal Linux return path in this case because if we use the IRET hypercall +# to pop the stack frame we end up in an infinite loop of failsafe callbacks. +# We distinguish between categories by maintaining a status value in EAX. ENTRY(failsafe_callback) -1: popl %ds -2: popl %es -3: popl %fs -4: popl %gs - subl $4,%esp + pushl %eax + movl $1,%eax +1: mov 4(%esp),%ds +2: mov 8(%esp),%es +3: mov 12(%esp),%fs +4: mov 16(%esp),%gs + testl %eax,%eax + popl %eax + jz 5f + addl $16,%esp # EAX != 0 => Category 2 (Bad IRET) + jmp iret_exc +5: addl $16,%esp # EAX == 0 => Category 1 (Bad segment) + pushl $0 SAVE_ALL - jmp ret_from_exception -.section .fixup,"ax"; \ -6: movl $0,(%esp); \ - jmp 1b; \ -7: movl $0,(%esp); \ - jmp 2b; \ -8: movl $0,(%esp); \ - jmp 3b; \ -9: movl $0,(%esp); \ - jmp 4b; \ -.previous; \ -.section __ex_table,"a";\ - .align 4; \ - .long 1b,6b; \ - .long 2b,7b; \ - .long 3b,8b; \ - .long 4b,9b; \ + jmp ret_from_exception +.section .fixup,"ax"; \ +6: xorl %eax,%eax; \ + movl %eax,4(%esp); \ + jmp 1b; \ +7: xorl %eax,%eax; \ + movl %eax,8(%esp); \ + jmp 2b; \ +8: xorl %eax,%eax; \ + movl %eax,12(%esp); \ + jmp 3b; \ +9: xorl %eax,%eax; \ + movl %eax,16(%esp); \ + jmp 4b; \ +.previous; \ +.section __ex_table,"a"; \ + .align 4; \ + .long 1b,6b; \ + .long 2b,7b; \ + .long 3b,8b; \ + .long 4b,9b; \ .previous #endif diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S index ea24701bb8..604365dec3 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S @@ -520,13 +520,13 @@ retint_check: CFI_REMEMBER_STATE jnz retint_careful retint_restore_args: - movb EVENT_MASK-REST_SKIP(%rsp), %al - notb %al # %al == ~saved_mask - XEN_GET_VCPU_INFO(%rsi) - andb evtchn_upcall_mask(%rsi),%al - andb $1,%al # %al == mask & ~saved_mask - jnz restore_all_enable_events # != 0 => reenable event delivery - XEN_PUT_VCPU_INFO(%rsi) + movl EFLAGS-REST_SKIP(%rsp), %eax + shr $9, %eax # EAX[0] == IRET_EFLAGS.IF + XEN_GET_VCPU_INFO(%rsi) + andb evtchn_upcall_mask(%rsi),%al + andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask + jnz restore_all_enable_events # != 0 => enable event delivery + XEN_PUT_VCPU_INFO(%rsi) RESTORE_ARGS 0,8,0 HYPERVISOR_IRET 0 @@ -803,12 +803,11 @@ ENTRY(hypervisor_callback) # So, on entry to the handler we detect whether we interrupted an # existing activation in its critical region -- if so, we pop the current # activation and restart the handler using the previous one. -ENTRY(do_hypervisor_callback) # do_hyperviosr_callback(struct *pt_regs) +ENTRY(do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs) # Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will # see the correct pointer to the pt_regs movq %rdi, %rsp # we don't return, adjust the stack frame -11: movb $0, EVENT_MASK(%rdi) - movq %gs:pda_irqstackptr,%rax +11: movq %gs:pda_irqstackptr,%rax incl %gs:pda_irqcount cmovzq %rax,%rsp pushq %rdi @@ -853,15 +852,44 @@ ecrit: /**** END OF CRITICAL REGION ****/ # When the kernel is interrupted in the critical section, the kernel # will do IRET in that case, and everything will be restored at that point, # i.e. it just resumes from the next instruction interrupted with the same context. - + # Hypervisor uses this for application faults while it executes. -# Unlike i386 there is no need to reload the saved segment selectors: -# Xen already reloaded all valid ones and zeroed the others. +# We get here for two reasons: +# 1. Fault while reloading DS, ES, FS or GS +# 2. Fault while executing IRET +# Category 1 we do not need to fix up as Xen has already reloaded all segment +# registers that could be reloaded and zeroed the others. +# Category 2 we fix up by killing the current process. We cannot use the +# normal Linux return path in this case because if we use the IRET hypercall +# to pop the stack frame we end up in an infinite loop of failsafe callbacks. +# We distinguish between categories by comparing each saved segment register +# with its current contents: any discrepancy means we in category 1. ENTRY(failsafe_callback) - addq $0x30,%rsp /* skip %rcx,%r11,%ds,%es,%fs,%gs */ + movw %ds,%cx + cmpw %cx,0x10(%rsp) + jne 1f + movw %es,%cx + cmpw %cx,0x18(%rsp) + jne 1f + movw %fs,%cx + cmpw %cx,0x20(%rsp) + jne 1f + movw %gs,%cx + cmpw %cx,0x28(%rsp) + jne 1f + /* All segments match their saved values => Category 2 (Bad IRET). */ + movq (%rsp),%rcx + movq 8(%rsp),%r11 + addq $0x30,%rsp + movq $-9999,%rdi /* better code? */ + jmp do_exit +1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */ + movq (%rsp),%rcx + movq 8(%rsp),%r11 + addq $0x30,%rsp + pushq $0 SAVE_ALL - jmp error_exit - + jmp error_exit #if 0 .section __ex_table,"a" .align 8 diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/xen_entry.S b/linux-2.6-xen-sparse/arch/x86_64/kernel/xen_entry.S index 9b42d15566..b3d7f19405 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/xen_entry.S +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/xen_entry.S @@ -2,7 +2,7 @@ * Copied from arch/xen/i386/kernel/entry.S */ /* Offsets into shared_info_t. */ -#define evtchn_upcall_pending 0 +#define evtchn_upcall_pending /* 0 */ #define evtchn_upcall_mask 1 #define sizeof_vcpu_shift 6 @@ -35,7 +35,6 @@ XEN_PUT_VCPU_INFO(reg) #define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(reg) -EVENT_MASK = (CS+4) VGCF_IN_SYSCALL = (1<<8) diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c index 960a52cb74..07830746be 100644 --- a/xen/arch/x86/x86_32/asm-offsets.c +++ b/xen/arch/x86/x86_32/asm-offsets.c @@ -44,7 +44,6 @@ void __dummy__(void) OFFSET(UREGS_eflags, struct cpu_user_regs, eflags); OFFSET(UREGS_error_code, struct cpu_user_regs, error_code); OFFSET(UREGS_entry_vector, struct cpu_user_regs, entry_vector); - OFFSET(UREGS_saved_upcall_mask, struct cpu_user_regs, saved_upcall_mask); OFFSET(UREGS_kernel_sizeof, struct cpu_user_regs, esp); DEFINE(UREGS_user_sizeof, sizeof(struct cpu_user_regs)); BLANK(); diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 1c5daca90d..59d1a845a8 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -230,8 +230,8 @@ unsigned long do_iret(void) /* No longer in NMI context. */ clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); - /* Restore upcall mask from saved value. */ - current->vcpu_info->evtchn_upcall_mask = regs->saved_upcall_mask; + /* Restore upcall mask from supplied EFLAGS.IF. */ + current->vcpu_info->evtchn_upcall_mask = !(eflags & X86_EFLAGS_IF); /* * The hypercall exit path will overwrite EAX with this return diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index 91e9e81027..ebc3059a9c 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -48,7 +48,6 @@ void __dummy__(void) OFFSET(UREGS_eflags, struct cpu_user_regs, eflags); OFFSET(UREGS_rsp, struct cpu_user_regs, rsp); OFFSET(UREGS_ss, struct cpu_user_regs, ss); - OFFSET(UREGS_saved_upcall_mask, struct cpu_user_regs, saved_upcall_mask); OFFSET(UREGS_kernel_sizeof, struct cpu_user_regs, es); DEFINE(UREGS_user_sizeof, sizeof(struct cpu_user_regs)); BLANK(); diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 46835570c4..6794cefecf 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -210,6 +210,9 @@ unsigned long do_iret(void) /* No longer in NMI context. */ clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); + /* Restore upcall mask from supplied EFLAGS.IF. */ + current->vcpu_info->evtchn_upcall_mask = !(iret_saved.rflags & EF_IE); + /* Saved %rax gets written back to regs->rax in entry.S. */ return iret_saved.rax; } From fd24f14fe4867cd41ddc00fe41ed3f5a01326c01 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 13:56:26 +0100 Subject: [PATCH 005/151] SVM patch to update guest time with latest hvm modifications. Signed-off-by: Tom Woller --- xen/arch/x86/hvm/svm/intr.c | 2 +- xen/arch/x86/hvm/svm/svm.c | 5 +++-- xen/arch/x86/hvm/svm/vmcb.c | 8 +++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index 46de3cd40a..6d3289e695 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -81,7 +81,7 @@ interrupt_post_injection(struct vcpu * v, int vector, int type) } vpit->inject_point = NOW(); - vpit->last_pit_gtime += vpit->period; + vpit->last_pit_gtime += vpit->period_cycles; svm_set_guest_time(v, vpit->last_pit_gtime); } diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index dcecfda39f..d43bfb08d8 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -674,9 +674,10 @@ static void svm_freeze_time(struct vcpu *v) { struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; - v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v); - if ( vpit->first_injected ) + if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) { + v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v); stop_timer(&(vpit->pit_timer)); + } } static void svm_ctxt_switch_from(struct vcpu *v) diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 8b46e104e5..0d101206b6 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -498,8 +498,11 @@ void svm_do_resume(struct vcpu *v) svm_stts(v); /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( vpit->first_injected) { - svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time); + if ( vpit->first_injected ) { + if ( v->domain->arch.hvm_domain.guest_time ) { + svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time); + v->domain->arch.hvm_domain.guest_time = 0; + } pickup_deactive_ticks(vpit); } @@ -511,7 +514,6 @@ void svm_do_resume(struct vcpu *v) ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)); } - void svm_launch_fail(unsigned long eflags) { BUG(); From bf952827326514e26b6a5b3b5209c1e64076db97 Mon Sep 17 00:00:00 2001 From: "anthony@rhesis.austin.ibm.com" Date: Wed, 29 Mar 2006 14:50:57 +0100 Subject: [PATCH 006/151] Remove vcpu_avail from the public S-Expression that's passed over the wire. This trips up the XML-RPC layer on large SMP systems and isn't actually used by xm. Signed-off-by: Anthony Liguori --- tools/python/xen/xend/server/XMLRPCServer.py | 21 ++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py index 7d03cfb3dc..b1a288d84b 100644 --- a/tools/python/xen/xend/server/XMLRPCServer.py +++ b/tools/python/xen/xend/server/XMLRPCServer.py @@ -24,6 +24,7 @@ from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN from xen.xend.XendError import * +from types import ListType def lookup(domid): info = XendDomain.instance().domain_lookup_by_name_or_id(domid) @@ -35,24 +36,36 @@ def dispatch(domid, fn, args): info = lookup(domid) return getattr(info, fn)(*args) +# vcpu_avail is a long and is not needed by the clients. It's far easier +# to just remove it then to try and marshal the long. +def fixup_sxpr(sexpr): + ret = [] + for k in sexpr: + if type(k) is ListType: + if len(k) != 2 or k[0] != 'vcpu_avail': + ret.append(fixup_sxpr(k)) + else: + ret.append(k) + return ret + def domain(domid): info = lookup(domid) - return info.sxpr() + return fixup_sxpr(info.sxpr()) def domains(detail=1): if detail < 1: return XendDomain.instance().list_names() else: domains = XendDomain.instance().list_sorted() - return map(lambda dom: dom.sxpr(), domains) + return map(lambda dom: fixup_sxpr(dom.sxpr()), domains) def domain_create(config): info = XendDomain.instance().domain_create(config) - return info.sxpr() + return fixup_sxpr(info.sxpr()) def domain_restore(src): info = XendDomain.instance().domain_restore(src) - return info.sxpr() + return fixup_sxpr(info.sxpr()) def get_log(): f = open(XendLogging.getLogFilename(), 'r') From 54336cd68592c0d48749ac5d3ce2c20fbfd2ab46 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 14:54:43 +0100 Subject: [PATCH 007/151] Make maximum number of supported physical CPUs a compile-time option via the 'max_phys_cpus=' compilation parameter. Based on a patch from Aravindh Puthiyaparambil at Unisys. Signed-off-by: Keir Fraser --- xen/Rules.mk | 4 ++++ xen/arch/x86/smpboot.c | 20 ++++++++++++++++---- xen/arch/x86/x86_64/mm.c | 8 +++++--- xen/include/asm-x86/config.h | 8 ++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index 55aab4c95e..f887ea44f5 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -51,6 +51,10 @@ CFLAGS-$(crash_debug) += -DCRASH_DEBUG CFLAGS-$(perfc) += -DPERF_COUNTERS CFLAGS-$(perfc_arrays) += -DPERF_ARRAYS +ifneq ($(max_phys_cpus),) +CFLAGS-y += -DMAX_PHYS_CPUS=$(max_phys_cpus) +endif + ALL_OBJS := $(ALL_OBJS-y) CFLAGS := $(strip $(CFLAGS) $(CFLAGS-y)) diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 5427c42f27..498c2b5ba2 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -880,18 +880,30 @@ static int __devinit do_boot_cpu(int apicid, int cpu) * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. */ { - struct vcpu *v; unsigned long boot_error; int timeout; unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; + struct domain *d; + struct vcpu *v; + int vcpu_id; ++cpucount; - v = idle_vcpu[cpu] = alloc_vcpu(idle_vcpu[0]->domain, cpu, cpu); - BUG_ON(v == NULL); + if ((vcpu_id = cpu % MAX_VIRT_CPUS) == 0) { + d = domain_create(IDLE_DOMAIN_ID, cpu); + BUG_ON(d == NULL); + v = d->vcpu[0]; + } else { + d = idle_vcpu[cpu - vcpu_id]->domain; + BUG_ON(d == NULL); + v = alloc_vcpu(d, vcpu_id, cpu); + } - v->arch.monitor_table = mk_pagetable(__pa(idle_pg_table)); + idle_vcpu[cpu] = v; + BUG_ON(v == NULL); + + v->arch.monitor_table = mk_pagetable(__pa(idle_pg_table)); /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index aa51f434e9..ee8a1a9bf3 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -148,12 +148,14 @@ void subarch_init_memory(void) if ( ((offsetof(struct page_info, u.inuse._domain) != (offsetof(struct page_info, count_info) + sizeof(u32)))) || ((offsetof(struct page_info, count_info) & 7) != 0) || - (sizeof(struct page_info) != 40) ) + (sizeof(struct page_info) != + (32 + BITS_TO_LONGS(NR_CPUS)*sizeof(long))) ) { - printk("Weird page_info layout (%ld,%ld,%ld)\n", + printk("Weird page_info layout (%ld,%ld,%ld,%ld)\n", offsetof(struct page_info, count_info), offsetof(struct page_info, u.inuse._domain), - sizeof(struct page_info)); + sizeof(struct page_info), + 32 + BITS_TO_LONGS(NR_CPUS)*sizeof(long)); for ( ; ; ) ; } diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index b901ed3036..3360a2a5a0 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -35,7 +35,15 @@ #define OPT_CONSOLE_STR "com1,vga" +#ifdef MAX_PHYS_CPUS +#define NR_CPUS MAX_PHYS_CPUS +#else #define NR_CPUS 32 +#endif + +#if defined(__i386__) && (NR_CPUS > 32) +#error "Maximum of 32 physical processors supported by Xen on x86_32" +#endif #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL # define supervisor_mode_kernel (1) From 0f60ff7a3bbc10ff56b5c00498f16206ade50fe9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 15:39:22 +0100 Subject: [PATCH 008/151] Ensure curr_vcpu in domain.c is set correctly, even when nr physical cpus is greater than max virtual cpus per domain. Also do not initialise secondary CPU smp_processor_id() from smpboot.c cpucount. It will be wrong if some CPUs fail to boot. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 16 +++++++--------- xen/arch/x86/setup.c | 1 + xen/arch/x86/smpboot.c | 9 ++++++--- xen/include/asm-x86/current.h | 2 ++ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 025c76759e..b8e6ce9708 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -208,6 +208,11 @@ void dump_pageframe_info(struct domain *d) } } +void set_current_execstate(struct vcpu *v) +{ + percpu_ctxt[smp_processor_id()].curr_vcpu = v; +} + struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) { struct vcpu *v; @@ -219,15 +224,8 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.flags = TF_kernel_mode; - if ( is_idle_domain(d) ) - { - percpu_ctxt[vcpu_id].curr_vcpu = v; - v->arch.schedule_tail = continue_idle_domain; - } - else - { - v->arch.schedule_tail = continue_nonidle_domain; - } + v->arch.schedule_tail = is_idle_domain(d) ? + continue_idle_domain : continue_nonidle_domain; v->arch.ctxt_switch_from = paravirt_ctxt_switch_from; v->arch.ctxt_switch_to = paravirt_ctxt_switch_to; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index b5b0fd68e0..88e667b1ec 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -404,6 +404,7 @@ void __init __start_xen(multiboot_info_t *mbi) BUG_ON(idle_domain == NULL); set_current(idle_domain->vcpu[0]); + set_current_execstate(idle_domain->vcpu[0]); idle_vcpu[0] = current; paging_init(); diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 498c2b5ba2..3a35ca339e 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -441,7 +441,7 @@ void __devinit smp_callin(void) calibrate_tsc_ap(); } -static int cpucount; +static int cpucount, booting_cpu; /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; @@ -524,12 +524,13 @@ void __devinit start_secondary(void *unused) * booting is too fragile that we want to limit the * things done here to the most necessary things. */ - unsigned int cpu = cpucount; + unsigned int cpu = booting_cpu; extern void percpu_traps_init(void); - set_current(idle_vcpu[cpu]); set_processor_id(cpu); + set_current(idle_vcpu[cpu]); + set_current_execstate(idle_vcpu[cpu]); percpu_traps_init(); @@ -890,6 +891,8 @@ static int __devinit do_boot_cpu(int apicid, int cpu) ++cpucount; + booting_cpu = cpu; + if ((vcpu_id = cpu % MAX_VIRT_CPUS) == 0) { d = domain_create(IDLE_DOMAIN_ID, cpu); BUG_ON(d == NULL); diff --git a/xen/include/asm-x86/current.h b/xen/include/asm-x86/current.h index 2a63b75002..5803141f2a 100644 --- a/xen/include/asm-x86/current.h +++ b/xen/include/asm-x86/current.h @@ -53,4 +53,6 @@ static inline struct cpu_info *get_cpu_info(void) #define schedule_tail(_ed) (((_ed)->arch.schedule_tail)(_ed)) +extern void set_current_execstate(struct vcpu *v); + #endif /* __X86_CURRENT_H__ */ From 816b45f1c4833c77ba4e15655c992b1f3de76710 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 16:02:40 +0100 Subject: [PATCH 009/151] Compute actual baud rate from UART divisor latch contents when no baud rate is specified. Generalise the divisor calculation based on external clock rate. Signed-off-by: Keir Fraser --- xen/drivers/char/ns16550.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index f1ad820f0d..b9e4950af1 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -99,6 +99,9 @@ static struct ns16550 { #define PARITY_MARK (5<<3) #define PARITY_SPACE (7<<3) +/* Frequency of external clock source. This definition assumes PC platform. */ +#define UART_CLOCK_HZ 1843200 + static char ns_read_reg(struct ns16550 *uart, int reg) { if ( uart->remapped_io_base == NULL ) @@ -171,6 +174,7 @@ static void ns16550_init_preirq(struct serial_port *port) { struct ns16550 *uart = port->uart; unsigned char lcr; + unsigned int divisor; /* I/O ports are distinguished by their size (16 bits). */ if ( uart->io_base >= 0x10000 ) @@ -182,13 +186,22 @@ static void ns16550_init_preirq(struct serial_port *port) ns_write_reg(uart, IER, 0); /* Line control and baud-rate generator. */ + ns_write_reg(uart, LCR, lcr | LCR_DLAB); if ( uart->baud != BAUD_AUTO ) { - ns_write_reg(uart, LCR, lcr | LCR_DLAB); - ns_write_reg(uart, DLL, 115200/uart->baud); /* baud lo */ - ns_write_reg(uart, DLM, 0); /* baud hi */ + /* Baud rate specified: program it into the divisor latch. */ + divisor = UART_CLOCK_HZ / (uart->baud * 16); + ns_write_reg(uart, DLL, (char)divisor); + ns_write_reg(uart, DLM, (char)(divisor >> 8)); } - ns_write_reg(uart, LCR, lcr); /* parity, data, stop */ + else + { + /* Baud rate already set: read it out from the divisor latch. */ + divisor = ns_read_reg(uart, DLL); + divisor |= ns_read_reg(uart, DLM) << 8; + uart->baud = UART_CLOCK_HZ / (divisor * 16); + } + ns_write_reg(uart, LCR, lcr); /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */ ns_write_reg(uart, MCR, MCR_DTR | MCR_RTS); From a10d8554f8deecbfd3937964c7c031592c7ac365 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 16:47:46 +0100 Subject: [PATCH 010/151] Re-arrange code for followup patch and remove extra shadow_lock in function which is only called with the lock already held. Signed-off-by: Christian Limpach --- xen/include/asm-x86/shadow.h | 86 ++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 5a52029840..ca988bbece 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -135,6 +135,8 @@ extern int set_p2m_entry( struct domain_mmap_cache *l1cache); extern void remove_shadow(struct domain *d, unsigned long gpfn, u32 stype); +extern void free_shadow_page(unsigned long smfn); + extern void shadow_l1_normal_pt_update(struct domain *d, paddr_t pa, l1_pgentry_t l1e, struct domain_mmap_cache *cache); @@ -660,55 +662,13 @@ static inline void shadow_sync_and_drop_references( if ( likely(!shadow_mode_refcounts(d)) ) return; - shadow_lock(d); - if ( page_out_of_sync(page) ) __shadow_sync_mfn(d, page_to_mfn(page)); shadow_remove_all_access(d, page_to_mfn(page)); - - shadow_unlock(d); } #endif -static inline void guest_physmap_add_page( - struct domain *d, unsigned long gpfn, unsigned long mfn) -{ - struct domain_mmap_cache c1, c2; - - if ( likely(!shadow_mode_translate(d)) ) - return; - - domain_mmap_cache_init(&c1); - domain_mmap_cache_init(&c2); - shadow_lock(d); - shadow_sync_and_drop_references(d, mfn_to_page(mfn)); - set_p2m_entry(d, gpfn, mfn, &c1, &c2); - set_gpfn_from_mfn(mfn, gpfn); - shadow_unlock(d); - domain_mmap_cache_destroy(&c1); - domain_mmap_cache_destroy(&c2); -} - -static inline void guest_physmap_remove_page( - struct domain *d, unsigned long gpfn, unsigned long mfn) -{ - struct domain_mmap_cache c1, c2; - - if ( likely(!shadow_mode_translate(d)) ) - return; - - domain_mmap_cache_init(&c1); - domain_mmap_cache_init(&c2); - shadow_lock(d); - shadow_sync_and_drop_references(d, mfn_to_page(mfn)); - set_p2m_entry(d, gpfn, -1, &c1, &c2); - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); - shadow_unlock(d); - domain_mmap_cache_destroy(&c1); - domain_mmap_cache_destroy(&c2); -} - /************************************************************************/ /* @@ -739,8 +699,6 @@ get_shadow_ref(unsigned long smfn) return 1; } -extern void free_shadow_page(unsigned long smfn); - /* * Drop a shadow reference to smfn. */ @@ -1525,6 +1483,46 @@ static inline void set_shadow_status( /************************************************************************/ +static inline void guest_physmap_add_page( + struct domain *d, unsigned long gpfn, unsigned long mfn) +{ + struct domain_mmap_cache c1, c2; + + if ( likely(!shadow_mode_translate(d)) ) + return; + + domain_mmap_cache_init(&c1); + domain_mmap_cache_init(&c2); + shadow_lock(d); + shadow_sync_and_drop_references(d, mfn_to_page(mfn)); + set_p2m_entry(d, gpfn, mfn, &c1, &c2); + set_gpfn_from_mfn(mfn, gpfn); + shadow_unlock(d); + domain_mmap_cache_destroy(&c1); + domain_mmap_cache_destroy(&c2); +} + +static inline void guest_physmap_remove_page( + struct domain *d, unsigned long gpfn, unsigned long mfn) +{ + struct domain_mmap_cache c1, c2; + + if ( likely(!shadow_mode_translate(d)) ) + return; + + domain_mmap_cache_init(&c1); + domain_mmap_cache_init(&c2); + shadow_lock(d); + shadow_sync_and_drop_references(d, mfn_to_page(mfn)); + set_p2m_entry(d, gpfn, -1, &c1, &c2); + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); + shadow_unlock(d); + domain_mmap_cache_destroy(&c1); + domain_mmap_cache_destroy(&c2); +} + +/************************************************************************/ + void static inline shadow_update_min_max(unsigned long smfn, int index) { From 4df87c91b1f5c65f96a98cdf66ee783dac649329 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 16:50:59 +0100 Subject: [PATCH 011/151] Free shadows of any pages which are released by a domain back to Xen. This should fix the "Assertion '! IS_INVALID_M2P_ENTRY(gpfn)'"-crash in free_shadow_page on domain destruction. Signed-off-by: Christian Limpach --- xen/include/asm-x86/shadow.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index ca988bbece..28d50466ea 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -1506,6 +1506,7 @@ static inline void guest_physmap_remove_page( struct domain *d, unsigned long gpfn, unsigned long mfn) { struct domain_mmap_cache c1, c2; + unsigned long type; if ( likely(!shadow_mode_translate(d)) ) return; @@ -1514,6 +1515,8 @@ static inline void guest_physmap_remove_page( domain_mmap_cache_init(&c2); shadow_lock(d); shadow_sync_and_drop_references(d, mfn_to_page(mfn)); + while ( (type = shadow_max_pgtable_type(d, gpfn, NULL)) != PGT_none ) + free_shadow_page(__shadow_status(d, gpfn, type)); set_p2m_entry(d, gpfn, -1, &c1, &c2); set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); shadow_unlock(d); From 473e020902bd7413b979e047429e2096e3933825 Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 18:06:27 +0100 Subject: [PATCH 012/151] Fix save/restore bug; further rationalization of xenbus state machine logic deferred until post 3.0.2. Signed-off-by: Steven Hand --- linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 82625a9715..23fe51a362 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -253,15 +253,20 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: - case XenbusStateConnected: break; case XenbusStateInitialised: + case XenbusStateConnected: + /* Ensure we connect even when two watches fire in + close successsion and we miss the intermediate value + of frontend_state. */ + if (dev->state == XenbusStateConnected) + break; + err = connect_ring(be); - if (err) { - return; - } - update_blkif_status(be->blkif); + if (err) + break; + update_blkif_status(be->blkif); break; case XenbusStateClosing: From f9bdf89a1b78397a2b26421ec839f54d38697047 Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Wed, 29 Mar 2006 18:07:36 +0100 Subject: [PATCH 013/151] Fix save/restore on 64-bit. Signed-off-by: Steven Hand --- linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index f0f1d803a5..828d287f3e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -114,8 +114,8 @@ static int __do_suspend(void *ignore) #ifdef __i386__ kmem_cache_shrink(pgd_cache); - mm_pin_all(); #endif + mm_pin_all(); __cli(); preempt_enable(); From f61bc4e0b8d4ed5e7f65dc17aeb3c8a42755b346 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Wed, 29 Mar 2006 18:41:30 +0100 Subject: [PATCH 014/151] Merged. --- .../drivers/xen/blkback/xenbus.c | 1 + xen/arch/x86/domain.c | 7 +++ xen/arch/x86/smpboot.c | 1 + xen/include/asm-x86/shadow.h | 44 +++++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 23fe51a362..c1b63752a1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -253,6 +253,7 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: + case XenbusStateConnected: break; case XenbusStateInitialised: diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index b8e6ce9708..0a48ba6053 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -226,6 +226,13 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.schedule_tail = is_idle_domain(d) ? continue_idle_domain : continue_nonidle_domain; + percpu_ctxt[vcpu_id].curr_vcpu = v; + v->arch.schedule_tail = continue_idle_domain; + } + else + { + v->arch.schedule_tail = continue_nonidle_domain; + } v->arch.ctxt_switch_from = paravirt_ctxt_switch_from; v->arch.ctxt_switch_to = paravirt_ctxt_switch_to; diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 3a35ca339e..f908af1c79 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -881,6 +881,7 @@ static int __devinit do_boot_cpu(int apicid, int cpu) * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. */ { + struct vcpu *v; unsigned long boot_error; int timeout; unsigned long start_eip; diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 28d50466ea..989768daa4 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -662,10 +662,14 @@ static inline void shadow_sync_and_drop_references( if ( likely(!shadow_mode_refcounts(d)) ) return; + shadow_lock(d); + if ( page_out_of_sync(page) ) __shadow_sync_mfn(d, page_to_mfn(page)); shadow_remove_all_access(d, page_to_mfn(page)); + + shadow_unlock(d); } #endif @@ -699,6 +703,46 @@ get_shadow_ref(unsigned long smfn) return 1; } + shadow_sync_and_drop_references(d, mfn_to_page(mfn)); + set_p2m_entry(d, gpfn, -1, &c1, &c2); + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); + shadow_unlock(d); + domain_mmap_cache_destroy(&c1); + domain_mmap_cache_destroy(&c2); +} + +/************************************************************************/ + +/* + * Add another shadow reference to smfn. + */ +static inline int +get_shadow_ref(unsigned long smfn) +{ + u32 x, nx; + + ASSERT(mfn_valid(smfn)); + + x = mfn_to_page(smfn)->count_info; + nx = x + 1; + + if ( unlikely(nx == 0) ) + { + printk("get_shadow_ref overflow, gmfn=%" PRtype_info " smfn=%lx\n", + mfn_to_page(smfn)->u.inuse.type_info & PGT_mfn_mask, + smfn); + BUG(); + } + + // Guarded by the shadow lock... + // + mfn_to_page(smfn)->count_info = nx; + + return 1; +} + +extern void free_shadow_page(unsigned long smfn); + /* * Drop a shadow reference to smfn. */ From 4b4593251a2c222a642a84533e0280a9ec291f6d Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Wed, 29 Mar 2006 18:46:51 +0100 Subject: [PATCH 015/151] Revert accidental commit. Signed-off-by: Ewan Mellor --- .../drivers/xen/blkback/xenbus.c | 1 - xen/arch/x86/domain.c | 7 --- xen/arch/x86/smpboot.c | 1 - xen/include/asm-x86/shadow.h | 44 ------------------- 4 files changed, 53 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index c1b63752a1..23fe51a362 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -253,7 +253,6 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: - case XenbusStateConnected: break; case XenbusStateInitialised: diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 0a48ba6053..b8e6ce9708 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -226,13 +226,6 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.schedule_tail = is_idle_domain(d) ? continue_idle_domain : continue_nonidle_domain; - percpu_ctxt[vcpu_id].curr_vcpu = v; - v->arch.schedule_tail = continue_idle_domain; - } - else - { - v->arch.schedule_tail = continue_nonidle_domain; - } v->arch.ctxt_switch_from = paravirt_ctxt_switch_from; v->arch.ctxt_switch_to = paravirt_ctxt_switch_to; diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index f908af1c79..3a35ca339e 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -881,7 +881,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu) * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu. */ { - struct vcpu *v; unsigned long boot_error; int timeout; unsigned long start_eip; diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 989768daa4..28d50466ea 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -662,14 +662,10 @@ static inline void shadow_sync_and_drop_references( if ( likely(!shadow_mode_refcounts(d)) ) return; - shadow_lock(d); - if ( page_out_of_sync(page) ) __shadow_sync_mfn(d, page_to_mfn(page)); shadow_remove_all_access(d, page_to_mfn(page)); - - shadow_unlock(d); } #endif @@ -703,46 +699,6 @@ get_shadow_ref(unsigned long smfn) return 1; } - shadow_sync_and_drop_references(d, mfn_to_page(mfn)); - set_p2m_entry(d, gpfn, -1, &c1, &c2); - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); - shadow_unlock(d); - domain_mmap_cache_destroy(&c1); - domain_mmap_cache_destroy(&c2); -} - -/************************************************************************/ - -/* - * Add another shadow reference to smfn. - */ -static inline int -get_shadow_ref(unsigned long smfn) -{ - u32 x, nx; - - ASSERT(mfn_valid(smfn)); - - x = mfn_to_page(smfn)->count_info; - nx = x + 1; - - if ( unlikely(nx == 0) ) - { - printk("get_shadow_ref overflow, gmfn=%" PRtype_info " smfn=%lx\n", - mfn_to_page(smfn)->u.inuse.type_info & PGT_mfn_mask, - smfn); - BUG(); - } - - // Guarded by the shadow lock... - // - mfn_to_page(smfn)->count_info = nx; - - return 1; -} - -extern void free_shadow_page(unsigned long smfn); - /* * Drop a shadow reference to smfn. */ From 5ed66abe17f3f16ff1323695daea15785c2701d4 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 00:07:23 +0100 Subject: [PATCH 016/151] Xen waits 5 seconds to reboot when domain 0 crashes, giving time to read crash messages. From: Chris Wright Signed-off-by: Keir Fraser --- xen/common/domain.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xen/common/domain.c b/xen/common/domain.c index e98b4994d3..b582719545 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -222,6 +223,13 @@ void domain_shutdown(struct domain *d, u8 reason) printk("Domain 0 halted: halting machine.\n"); machine_halt(); } + else if ( reason == SHUTDOWN_crash ) + { + printk("Domain 0 crashed: rebooting machine in 5 seconds.\n"); + watchdog_disable(); + mdelay(5000); + machine_restart(0); + } else { printk("Domain 0 shutdown: rebooting machine.\n"); From 919a239a3c8f70cdb6963f76787588bd7a2a17a7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 00:11:53 +0100 Subject: [PATCH 017/151] Same panic() behaviour as native Linux when running as domain 0. That is, no reboot: just sit there and flash the keyboard LEDs. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c index 6e3a87ae5b..8a83da25e7 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c @@ -1633,9 +1633,9 @@ void __init setup_arch(char **cmdline_p) physdev_op_t op; unsigned long max_low_pfn; - /* Force a quick death if the kernel panics. */ + /* Force a quick death if the kernel panics (not domain 0). */ extern int panic_timeout; - if (panic_timeout == 0) + if (!panic_timeout && !(xen_start_info->flags & SIF_INITDOMAIN)) panic_timeout = 1; /* Register a call for panic conditions. */ From 5707afc46f6d7e98ee2e06ff11c45e6b1192d4cc Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 11:38:56 +0100 Subject: [PATCH 018/151] Fix xenconsoled when sending lots of console data to a domU. Fixes bug #477. Signed-off-by: Keir Fraser --- tools/console/daemon/io.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index 8b187e5e82..deea3ef6ec 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -434,26 +434,37 @@ void enum_domains(void) } } +static int ring_free_bytes(struct domain *dom) +{ + struct xencons_interface *intf = dom->interface; + XENCONS_RING_IDX cons, prod, space; + + cons = intf->in_cons; + prod = intf->in_prod; + mb(); + + space = prod - cons; + if (space > sizeof(intf->in)) + return 0; /* ring is screwed: ignore it */ + + return (sizeof(intf->in) - space); +} + static void handle_tty_read(struct domain *dom) { ssize_t len = 0; char msg[80]; int i; struct xencons_interface *intf = dom->interface; - XENCONS_RING_IDX cons, prod; - - cons = intf->in_cons; - prod = intf->in_prod; - mb(); - - if (sizeof(intf->in) > (prod - cons)) - len = sizeof(intf->in) - (prod - cons); - if (len > sizeof(msg)) - len = sizeof(msg); + XENCONS_RING_IDX prod; + len = ring_free_bytes(dom); if (len == 0) return; + if (len > sizeof(msg)) + len = sizeof(msg); + len = read(dom->tty_fd, msg, len); if (len < 1) { close(dom->tty_fd); @@ -465,6 +476,7 @@ static void handle_tty_read(struct domain *dom) shutdown_domain(dom); } } else if (domain_is_valid(dom->domid)) { + prod = intf->in_prod; for (i = 0; i < len; i++) { intf->in[MASK_XENCONS_IDX(prod++, intf->in)] = msg[i]; @@ -514,7 +526,7 @@ static void handle_ring_read(struct domain *dom) (void)write_sync(dom->evtchn_fd, &v, sizeof(v)); } -static void handle_xs(int fd) +static void handle_xs(void) { char **vec; int domid; @@ -560,7 +572,7 @@ void handle_io(void) } if (d->tty_fd != -1) { - if (!d->is_dead) + if (!d->is_dead && ring_free_bytes(d)) FD_SET(d->tty_fd, &readfds); if (!buffer_empty(&d->buffer)) @@ -572,7 +584,7 @@ void handle_io(void) ret = select(max_fd + 1, &readfds, &writefds, 0, NULL); if (FD_ISSET(xs_fileno(xs), &readfds)) - handle_xs(xs_fileno(xs)); + handle_xs(); for (d = dom_head; d; d = n) { n = d->next; From c705b05a310d753c900aa76fff6f3e9cb3e37769 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 30 Mar 2006 11:51:44 +0100 Subject: [PATCH 019/151] Fix the ProtocolError seen when the server throws an exception and running under Python 2.3; traceback.format_exc was introduced in 2.4, so we can't use it. Added some exception logging. Signed-off-by: Ewan Mellor --- tools/python/xen/util/xmlrpclib2.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index 538cbd8a95..214a678fac 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -23,9 +23,13 @@ An enhanced XML-RPC client/server interface for Python. from httplib import HTTPConnection, HTTP from xmlrpclib import Transport from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler -import xmlrpclib, socket, os, traceback +import xmlrpclib, socket, os import SocketServer +import xen.xend.XendClient +from xen.xend.XendLogging import log + + # A new ServerProxy that also supports httpu urls. An http URL comes in the # form: # @@ -60,8 +64,7 @@ class ServerProxy(xmlrpclib.ServerProxy): verbose, allow_none) # This is a base XML-RPC server for TCP. It sets allow_reuse_address to -# true, and has an improved marshaller that serializes unknown exceptions -# with full traceback information. +# true, and has an improved marshaller that logs and serializes exceptions. class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): allow_reuse_address = True @@ -80,10 +83,10 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): allow_none=1) except xmlrpclib.Fault, fault: response = xmlrpclib.dumps(fault) - except: + except Exception, exn: + log.exception(exn) response = xmlrpclib.dumps( - xmlrpclib.Fault(1, traceback.format_exc()) - ) + xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn))) return response From 51260a849cd9d952e20ba2a2094427aad8bffbfd Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 30 Mar 2006 11:54:07 +0100 Subject: [PATCH 020/151] Check the return value of domain_lookup_by_name_or_id_nr for None (i.e. no such domain) inside each of the public-facing functions. This fixes the Internal errors seen when specifying an invalid domain. domain_pincpu takes cpumap, which is a list, not a string, so there's no need to try and split it up. Fixes xm vcpu-pin. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomain.py | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 62268c0010..a762f88c6a 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -34,7 +34,7 @@ import XendDomainInfo from xen.xend import XendRoot from xen.xend import XendCheckpoint -from xen.xend.XendError import XendError +from xen.xend.XendError import XendError, XendInvalidDomain from xen.xend.XendLogging import log from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xswatch import xswatch @@ -357,6 +357,8 @@ class XendDomain: """Unpause domain execution.""" try: dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) log.info("Domain %s (%d) unpaused.", dominfo.getName(), dominfo.getDomid()) return dominfo.unpause() @@ -368,6 +370,8 @@ class XendDomain: """Pause domain execution.""" try: dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) log.info("Domain %s (%d) paused.", dominfo.getName(), dominfo.getDomid()) return dominfo.pause() @@ -395,6 +399,8 @@ class XendDomain: """Start domain migration.""" dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) if dominfo.getDomid() == PRIV_DOMAIN: raise XendError("Cannot migrate privileged domain %i" % domid) @@ -420,6 +426,8 @@ class XendDomain: try: dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) if dominfo.getDomid() == PRIV_DOMAIN: raise XendError("Cannot save privileged domain %i" % domid) @@ -440,9 +448,9 @@ class XendDomain: @param cpumap: string repr of list of usable cpus """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) - # convert cpumap string into a list of ints - cpumap = map(lambda x: int(x), - cpumap.replace("[", "").replace("]", "").split(",")) + if not dominfo: + raise XendInvalidDomain(str(domid)) + try: return xc.vcpu_setaffinity(dominfo.getDomid(), vcpu, cpumap) except Exception, ex: @@ -453,6 +461,8 @@ class XendDomain: """Set BVT (Borrowed Virtual Time) scheduler parameters for a domain. """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) try: return xc.bvtsched_domain_set(dom=dominfo.getDomid(), mcuadv=mcuadv, @@ -466,6 +476,8 @@ class XendDomain: """Get BVT (Borrowed Virtual Time) scheduler parameters for a domain. """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) try: return xc.bvtsched_domain_get(dominfo.getDomid()) except Exception, ex: @@ -477,6 +489,8 @@ class XendDomain: """Set Simple EDF scheduler parameters for a domain. """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) try: return xc.sedf_domain_set(dominfo.getDomid(), period, slice_, latency, extratime, weight) @@ -487,8 +501,9 @@ class XendDomain: """Get Simple EDF scheduler parameters for a domain. """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) try: - sedf_info = xc.sedf_domain_get(dominfo.getDomid()) # return sxpr return ['sedf', @@ -509,6 +524,8 @@ class XendDomain: @return: 0 on success, -1 on error """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) maxmem = int(mem) * 1024 try: return xc.domain_setmaxmem(dominfo.getDomid(), maxmem) @@ -523,6 +540,8 @@ class XendDomain: @return: 0 on success, -1 on error """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) nr_ports = last - first + 1 try: return xc.domain_ioport_permission(dominfo.getDomid(), @@ -540,6 +559,8 @@ class XendDomain: @return: 0 on success, -1 on error """ dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if not dominfo: + raise XendInvalidDomain(str(domid)) nr_ports = last - first + 1 try: return xc.domain_ioport_permission(dominfo.getDomid(), From 31903a3370b4c056d7d97ee3b495bd48677d4ab9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 14:06:11 +0100 Subject: [PATCH 021/151] Include the E7520 (e.g., Dell 1850) irqbalance quirk fix even when building a non-SMP kernel. The underlying hypervisor may still be SMP. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c index 39d9ed110a..7e44d81bdc 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c @@ -5,7 +5,7 @@ #include #include -#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) +#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI) static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) { From 4734f491063e6b2d43e273a178da06e93a92080d Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 14:31:57 +0100 Subject: [PATCH 022/151] Use AFLAGS for assembly files so we can "+=" more flags. From: Jimi Xenidis Signed-off-by: Keir Fraser --- xen/Rules.mk | 5 ++++- xen/arch/ia64/Makefile | 2 +- xen/arch/x86/Makefile | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index f887ea44f5..ade8b87a1e 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -55,11 +55,14 @@ ifneq ($(max_phys_cpus),) CFLAGS-y += -DMAX_PHYS_CPUS=$(max_phys_cpus) endif +AFLAGS-y += -D__ASSEMBLY__ + ALL_OBJS := $(ALL_OBJS-y) CFLAGS := $(strip $(CFLAGS) $(CFLAGS-y)) +AFLAGS := $(strip $(AFLAGS) $(AFLAGS-y)) %.o: %.c $(HDRS) Makefile $(CC) $(CFLAGS) -c $< -o $@ %.o: %.S $(HDRS) Makefile - $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@ + $(CC) $(CFLAGS) $(AFLAGS) -c $< -o $@ diff --git a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile index 444f4eb30b..381c6d739b 100644 --- a/xen/arch/ia64/Makefile +++ b/xen/arch/ia64/Makefile @@ -76,7 +76,7 @@ $(BASEDIR)/include/asm-ia64/.offsets.h.stamp: # I'm sure a Makefile wizard would know a better way to do this xen.lds.s: xen/xen.lds.S - $(CC) -E $(CPPFLAGS) -P -DXEN -D__ASSEMBLY__ \ + $(CC) -E $(CPPFLAGS) -P -DXEN $(AFLAGS) \ -o xen.lds.s xen/xen.lds.S clean:: FORCE diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 3fa20dd7d0..c7a2e6ae1d 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -72,7 +72,7 @@ asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS) $(CC) $(CFLAGS) -S -o $@ $< xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(HDRS) - $(CC) $(CFLAGS) -P -E -Ui386 -D__ASSEMBLY__ -o $@ $< + $(CC) $(CFLAGS) -P -E -Ui386 $(AFLAGS) -o $@ $< boot/mkelf32: boot/mkelf32.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< From ce0dc718f220044a326161df9ee36c6ce4ccd30e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 14:37:22 +0100 Subject: [PATCH 023/151] More fixes to gdbserver for HVM guest debugging. Also fix writing back of register state for HVM guests. From: Nitin A Kamble Signed-off-by: Keir Fraser --- tools/libxc/xc_ptrace.c | 221 +++++++++++++++++------------ tools/libxc/xc_ptrace.h | 6 +- xen/arch/x86/domain.c | 2 +- xen/arch/x86/hvm/svm/svm.c | 7 - xen/arch/x86/hvm/svm/vmcb.c | 17 --- xen/arch/x86/hvm/vmx/vmcs.c | 26 ---- xen/arch/x86/hvm/vmx/vmx.c | 56 ++++++-- xen/include/asm-x86/hvm/hvm.h | 8 -- xen/include/asm-x86/hvm/svm/svm.h | 1 - xen/include/asm-x86/hvm/vmx/vmcs.h | 2 - 10 files changed, 180 insertions(+), 166 deletions(-) diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c index 715cb73b39..f83005b45c 100644 --- a/tools/libxc/xc_ptrace.c +++ b/tools/libxc/xc_ptrace.c @@ -153,6 +153,79 @@ online_vcpus_changed(cpumap_t cpumap) } /* --------------------- */ +/* XXX application state */ +static long nr_pages = 0; +static unsigned long *page_array = NULL; + +static void * +map_domain_va_32( + int xc_handle, + int cpu, + void *guest_va, + int perm) +{ + unsigned long pde, page; + unsigned long va = (unsigned long)guest_va; + + static unsigned long cr3_phys[MAX_VIRT_CPUS]; + static uint32_t *cr3_virt[MAX_VIRT_CPUS]; + static unsigned long pde_phys[MAX_VIRT_CPUS]; + static uint32_t *pde_virt[MAX_VIRT_CPUS]; + static unsigned long page_phys[MAX_VIRT_CPUS]; + static uint32_t *page_virt[MAX_VIRT_CPUS]; + static int prev_perm[MAX_VIRT_CPUS]; + + if (ctxt[cpu].ctrlreg[3] == 0) + return NULL; + if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] ) + { + cr3_phys[cpu] = ctxt[cpu].ctrlreg[3]; + if ( cr3_virt[cpu] ) + munmap(cr3_virt[cpu], PAGE_SIZE); + cr3_virt[cpu] = xc_map_foreign_range( + xc_handle, current_domid, PAGE_SIZE, PROT_READ, + cr3_phys[cpu] >> PAGE_SHIFT); + if ( cr3_virt[cpu] == NULL ) + return NULL; + } + if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 ) + return NULL; + if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) ) + pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; + if ( pde != pde_phys[cpu] ) + { + pde_phys[cpu] = pde; + if ( pde_virt[cpu] ) + munmap(pde_virt[cpu], PAGE_SIZE); + pde_virt[cpu] = xc_map_foreign_range( + xc_handle, current_domid, PAGE_SIZE, PROT_READ, + pde_phys[cpu] >> PAGE_SHIFT); + if ( pde_virt[cpu] == NULL ) + return NULL; + } + if ( (page = pde_virt[cpu][vtopti(va)]) == 0 ) + return NULL; + if (ctxt[cpu].flags & VGCF_HVM_GUEST) + page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT; + if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) ) + { + page_phys[cpu] = page; + if ( page_virt[cpu] ) + munmap(page_virt[cpu], PAGE_SIZE); + page_virt[cpu] = xc_map_foreign_range( + xc_handle, current_domid, PAGE_SIZE, perm, + page_phys[cpu] >> PAGE_SHIFT); + if ( page_virt[cpu] == NULL ) + { + page_phys[cpu] = 0; + return NULL; + } + prev_perm[cpu] = perm; + } + + return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); +} + static void * map_domain_va_pae( @@ -165,28 +238,31 @@ map_domain_va_pae( uint64_t *l3, *l2, *l1; static void *v; - if (fetch_regs(xc_handle, cpu, NULL)) - return NULL; - l3 = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); if ( l3 == NULL ) return NULL; l2p = l3[l3_table_offset_pae(va)] >> PAGE_SHIFT; + l2p = page_array[l2p]; l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p); + munmap(l3, PAGE_SIZE); if ( l2 == NULL ) return NULL; l1p = l2[l2_table_offset_pae(va)] >> PAGE_SHIFT; + l1p = page_array[l1p]; l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p); + munmap(l2, PAGE_SIZE); if ( l1 == NULL ) return NULL; p = l1[l1_table_offset_pae(va)] >> PAGE_SHIFT; + p = page_array[p]; if ( v != NULL ) munmap(v, PAGE_SIZE); v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p); + munmap(l1, PAGE_SIZE); if ( v == NULL ) return NULL; @@ -195,46 +271,58 @@ map_domain_va_pae( #ifdef __x86_64__ static void * -map_domain_va( +map_domain_va_64( int xc_handle, int cpu, void *guest_va, int perm) { - unsigned long l3p, l2p, l1p, p, va = (unsigned long)guest_va; + unsigned long l3p, l2p, l1p, l1e, p, va = (unsigned long)guest_va; uint64_t *l4, *l3, *l2, *l1; static void *v; if ((ctxt[cpu].ctrlreg[4] & 0x20) == 0 ) /* legacy ia32 mode */ - return map_domain_va_pae(xc_handle, cpu, guest_va, perm); + return map_domain_va_32(xc_handle, cpu, guest_va, perm); - if (fetch_regs(xc_handle, cpu, NULL)) - return NULL; - - l4 = xc_map_foreign_range( - xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); + l4 = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE, + PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); if ( l4 == NULL ) return NULL; l3p = l4[l4_table_offset(va)] >> PAGE_SHIFT; + l3p = page_array[l3p]; l3 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l3p); + munmap(l4, PAGE_SIZE); if ( l3 == NULL ) return NULL; l2p = l3[l3_table_offset(va)] >> PAGE_SHIFT; + l2p = page_array[l2p]; l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p); + munmap(l3, PAGE_SIZE); if ( l2 == NULL ) return NULL; - l1p = l2[l2_table_offset(va)] >> PAGE_SHIFT; - l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p); - if ( l1 == NULL ) - return NULL; + l1 = NULL; + l1e = l2[l2_table_offset(va)]; + l1p = l1e >> PAGE_SHIFT; + if (l1e & 0x80) { /* 2M pages */ + p = (l1p + l1_table_offset(va)); + } else { /* 4K pages */ + l1p = page_array[l1p]; + l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p); + munmap(l2, PAGE_SIZE); + if ( l1 == NULL ) + return NULL; - p = l1[l1_table_offset(va)] >> PAGE_SHIFT; + p = l1[l1_table_offset(va)] >> PAGE_SHIFT; + } + p = page_array[p]; if ( v != NULL ) munmap(v, PAGE_SIZE); v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p); + if (l1) + munmap(l1, PAGE_SIZE); if ( v == NULL ) return NULL; @@ -242,11 +330,6 @@ map_domain_va( } #endif -#ifdef __i386__ -/* XXX application state */ -static long nr_pages = 0; -static unsigned long *page_array = NULL; - static void * map_domain_va( int xc_handle, @@ -254,20 +337,9 @@ map_domain_va( void *guest_va, int perm) { - - unsigned long pde, page; - unsigned long va = (unsigned long)guest_va; + unsigned long va = (unsigned long) guest_va; long npgs = xc_get_tot_pages(xc_handle, current_domid); - - - static uint32_t cr3_phys[MAX_VIRT_CPUS]; - static unsigned long *cr3_virt[MAX_VIRT_CPUS]; - static unsigned long pde_phys[MAX_VIRT_CPUS]; - static unsigned long *pde_virt[MAX_VIRT_CPUS]; - static unsigned long page_phys[MAX_VIRT_CPUS]; - static unsigned long *page_virt[MAX_VIRT_CPUS]; - static int prev_perm[MAX_VIRT_CPUS]; - static enum { MODE_UNKNOWN, MODE_32, MODE_PAE, MODE_64 } mode; + static enum { MODE_UNKNOWN, MODE_64, MODE_32, MODE_PAE } mode; if ( mode == MODE_UNKNOWN ) { @@ -281,9 +353,6 @@ map_domain_va( mode = MODE_32; } - if ( mode == MODE_PAE ) - return map_domain_va_pae(xc_handle, cpu, guest_va, perm); - if ( nr_pages != npgs ) { if ( nr_pages > 0 ) @@ -305,60 +374,32 @@ map_domain_va( if (fetch_regs(xc_handle, cpu, NULL)) return NULL; - if (paging_enabled(&ctxt[cpu])) { - if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] ) - { - cr3_phys[cpu] = ctxt[cpu].ctrlreg[3]; - if ( cr3_virt[cpu] ) - munmap(cr3_virt[cpu], PAGE_SIZE); - cr3_virt[cpu] = xc_map_foreign_range( - xc_handle, current_domid, PAGE_SIZE, PROT_READ, - cr3_phys[cpu] >> PAGE_SHIFT); - if ( cr3_virt[cpu] == NULL ) - return NULL; - } - if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 ) + if (!paging_enabled(&ctxt[cpu])) { + static void * v; + unsigned long page; + + if ( v != NULL ) + munmap(v, PAGE_SIZE); + + page = page_array[va >> PAGE_SHIFT] << PAGE_SHIFT; + + v = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE, + perm, page >> PAGE_SHIFT); + + if ( v == NULL ) return NULL; - if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) ) - pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; - if ( pde != pde_phys[cpu] ) - { - pde_phys[cpu] = pde; - if ( pde_virt[cpu] ) - munmap(pde_virt[cpu], PAGE_SIZE); - pde_virt[cpu] = xc_map_foreign_range( - xc_handle, current_domid, PAGE_SIZE, PROT_READ, - pde_phys[cpu] >> PAGE_SHIFT); - if ( pde_virt[cpu] == NULL ) - return NULL; - } - if ( (page = pde_virt[cpu][vtopti(va)]) == 0 ) - return NULL; - } else { - page = va; + + return (void *)(((unsigned long)v) | (va & BSD_PAGE_MASK)); } - if (ctxt[cpu].flags & VGCF_HVM_GUEST) - page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT; - if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) ) - { - page_phys[cpu] = page; - if ( page_virt[cpu] ) - munmap(page_virt[cpu], PAGE_SIZE); - page_virt[cpu] = xc_map_foreign_range( - xc_handle, current_domid, PAGE_SIZE, perm, - page_phys[cpu] >> PAGE_SHIFT); - if ( page_virt[cpu] == NULL ) - { - page_phys[cpu] = 0; - return NULL; - } - prev_perm[cpu] = perm; - } - - return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); -} - +#ifdef __x86_64__ + if ( mode == MODE_64 ) + return map_domain_va_64(xc_handle, cpu, guest_va, perm); #endif + if ( mode == MODE_PAE ) + return map_domain_va_pae(xc_handle, cpu, guest_va, perm); + /* else ( mode == MODE_32 ) */ + return map_domain_va_32(xc_handle, cpu, guest_va, perm); +} static int __xc_waitdomain( @@ -470,7 +511,7 @@ xc_ptrace( break; case PTRACE_SETREGS: - if (!current_isfile) + if (current_isfile) goto out_unspported; /* XXX not yet supported */ SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs); if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, @@ -492,7 +533,7 @@ xc_ptrace( case PTRACE_CONT: case PTRACE_DETACH: - if (!current_isfile) + if (current_isfile) goto out_unspported; /* XXX not yet supported */ if ( request != PTRACE_SINGLESTEP ) { diff --git a/tools/libxc/xc_ptrace.h b/tools/libxc/xc_ptrace.h index 2119d9c984..b6d5bea314 100644 --- a/tools/libxc/xc_ptrace.h +++ b/tools/libxc/xc_ptrace.h @@ -31,7 +31,7 @@ struct gdb_regs unsigned long orig_rax; unsigned long rip; unsigned long xcs; - unsigned long eflags; + unsigned long rflags; unsigned long rsp; unsigned long xss; unsigned long fs_base; @@ -61,7 +61,7 @@ struct gdb_regs pt.rax = xc.rax; \ pt.rip = xc.rip; \ pt.xcs = xc.cs; \ - pt.eflags = xc.eflags; \ + pt.rflags = xc.rflags; \ pt.rsp = xc.rsp; \ pt.xss = xc.ss; \ pt.xes = xc.es; \ @@ -89,7 +89,7 @@ struct gdb_regs xc.rax = pt->rax; \ xc.rip = pt->rip; \ xc.cs = pt->xcs; \ - xc.eflags = pt->eflags; \ + xc.rflags = pt->rflags & 0xffffffff; \ xc.rsp = pt->rsp; \ xc.ss = pt->xss; \ xc.es = pt->xes; \ diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index b8e6ce9708..8cb91ead4d 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -393,7 +393,7 @@ int arch_set_info_guest( } else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) { - hvm_modify_guest_state(v); + hvm_load_cpu_guest_regs(v, &v->arch.guest_context.user_regs); } if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index d43bfb08d8..77ba3f8089 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -382,11 +382,6 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) return 1; } -void svm_modify_guest_state(struct vcpu *v) -{ - svm_modify_vmcb(v, &v->arch.guest_context.user_regs); -} - int svm_realmode(struct vcpu *v) { unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0; @@ -449,8 +444,6 @@ int start_svm(void) hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs; hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs; - hvm_funcs.modify_guest_state = svm_modify_guest_state; - hvm_funcs.realmode = svm_realmode; hvm_funcs.paging_enabled = svm_paging_enabled; hvm_funcs.instruction_length = svm_instruction_length; diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 0d101206b6..33c995a6f6 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -160,23 +160,6 @@ static int construct_vmcb_controls(struct arch_svm_struct *arch_svm) } -/* - * modify guest eflags and execption bitmap for gdb - */ -int svm_modify_vmcb(struct vcpu *v, struct cpu_user_regs *regs) -{ - int error; - if ((error = load_vmcb(&v->arch.hvm_svm, v->arch.hvm_svm.host_save_pa))) - { - printk("svm_modify_vmcb: load_vmcb failed: VMCB = %lx\n", - (unsigned long) v->arch.hvm_svm.host_save_pa); - return -EINVAL; - } - svm_load_cpu_user_regs(v,regs); - return 0; -} - - /* * Initially set the same environement as host. */ diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index a4e09344c4..7a2f50bb27 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -487,32 +487,6 @@ void destroy_vmcs(struct arch_vmx_struct *arch_vmx) arch_vmx->io_bitmap_b = NULL; } -/* - * modify guest eflags and execption bitmap for gdb - */ -int modify_vmcs(struct arch_vmx_struct *arch_vmx, - struct cpu_user_regs *regs) -{ - int error; - u64 vmcs_phys_ptr, old, old_phys_ptr; - vmcs_phys_ptr = (u64) virt_to_maddr(arch_vmx->vmcs); - - old_phys_ptr = virt_to_maddr(&old); - __vmptrst(old_phys_ptr); - if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) { - printk("modify_vmcs: load_vmcs failed: VMCS = %lx\n", - (unsigned long) vmcs_phys_ptr); - return -EINVAL; - } - -/* XXX VMX change modify_vmcs arg to v */ - hvm_load_cpu_guest_regs(current, regs); - - __vmptrld(old_phys_ptr); - - return 0; -} - void vm_launch_fail(unsigned long eflags) { unsigned long error; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 9e146477cc..623fb22922 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -400,7 +400,7 @@ void vmx_migrate_timers(struct vcpu *v) migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor); } -struct vmx_store_cpu_guest_regs_callback_info { +struct vmx_cpu_guest_regs_callback_info { struct vcpu *v; struct cpu_user_regs *regs; unsigned long *crs; @@ -409,12 +409,21 @@ struct vmx_store_cpu_guest_regs_callback_info { static void vmx_store_cpu_guest_regs( struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs); +static void vmx_load_cpu_guest_regs( + struct vcpu *v, struct cpu_user_regs *regs); + static void vmx_store_cpu_guest_regs_callback(void *data) { - struct vmx_store_cpu_guest_regs_callback_info *info = data; + struct vmx_cpu_guest_regs_callback_info *info = data; vmx_store_cpu_guest_regs(info->v, info->regs, info->crs); } +static void vmx_load_cpu_guest_regs_callback(void *data) +{ + struct vmx_cpu_guest_regs_callback_info *info = data; + vmx_load_cpu_guest_regs(info->v, info->regs); +} + static void vmx_store_cpu_guest_regs( struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs) { @@ -426,7 +435,7 @@ static void vmx_store_cpu_guest_regs( if ( v->arch.hvm_vmx.launch_cpu != smp_processor_id() ) { /* Get register details from remote CPU. */ - struct vmx_store_cpu_guest_regs_callback_info info = { + struct vmx_cpu_guest_regs_callback_info info = { .v = v, .regs = regs, .crs = crs }; cpumask_t cpumask = cpumask_of_cpu(v->arch.hvm_vmx.launch_cpu); on_selected_cpus(cpumask, vmx_store_cpu_guest_regs_callback, @@ -479,8 +488,33 @@ static void vmx_store_cpu_guest_regs( void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) { + if ( v != current ) + { + /* Non-current VCPUs must be paused to set the register snapshot. */ + ASSERT(atomic_read(&v->pausecnt) != 0); + + if ( v->arch.hvm_vmx.launch_cpu != smp_processor_id() ) + { + struct vmx_cpu_guest_regs_callback_info info = { + .v = v, .regs = regs }; + cpumask_t cpumask = cpumask_of_cpu(v->arch.hvm_vmx.launch_cpu); + on_selected_cpus(cpumask, vmx_load_cpu_guest_regs_callback, + &info, 1, 1); + return; + } + + /* Register details are on this CPU. Load the correct VMCS. */ + __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs)); + } + + ASSERT(v->arch.hvm_vmx.launch_cpu == smp_processor_id()); + #if defined (__x86_64__) __vmwrite(GUEST_SS_SELECTOR, regs->ss); + __vmwrite(GUEST_DS_SELECTOR, regs->ds); + __vmwrite(GUEST_ES_SELECTOR, regs->es); + __vmwrite(GUEST_GS_SELECTOR, regs->gs); + __vmwrite(GUEST_FS_SELECTOR, regs->fs); __vmwrite(GUEST_RSP, regs->rsp); __vmwrite(GUEST_RFLAGS, regs->rflags); @@ -493,6 +527,11 @@ void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) __vmwrite(GUEST_RIP, regs->rip); #elif defined (__i386__) __vmwrite(GUEST_SS_SELECTOR, regs->ss); + __vmwrite(GUEST_DS_SELECTOR, regs->ds); + __vmwrite(GUEST_ES_SELECTOR, regs->es); + __vmwrite(GUEST_GS_SELECTOR, regs->gs); + __vmwrite(GUEST_FS_SELECTOR, regs->fs); + __vmwrite(GUEST_RSP, regs->esp); __vmwrite(GUEST_RFLAGS, regs->eflags); @@ -503,14 +542,11 @@ void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) __vmwrite(GUEST_CS_SELECTOR, regs->cs); __vmwrite(GUEST_RIP, regs->eip); -#else -#error Unsupported architecture #endif -} -void vmx_modify_guest_state(struct vcpu *v) -{ - modify_vmcs(&v->arch.hvm_vmx, &v->arch.guest_context.user_regs); + /* Reload current VCPU's VMCS if it was temporarily unloaded. */ + if ( (v != current) && hvm_guest(current) ) + __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs)); } int vmx_realmode(struct vcpu *v) @@ -661,8 +697,6 @@ int start_vmx(void) hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs; hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs; - hvm_funcs.modify_guest_state = vmx_modify_guest_state; - hvm_funcs.realmode = vmx_realmode; hvm_funcs.paging_enabled = vmx_paging_enabled; hvm_funcs.instruction_length = vmx_instruction_length; diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index eff373996c..8e830977cc 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -47,8 +47,6 @@ struct hvm_function_table { struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs); void (*load_cpu_guest_regs)( struct vcpu *v, struct cpu_user_regs *r); - void (*modify_guest_state)(struct vcpu *v); - /* * Examine specifics of the guest state: * 1) determine whether the guest is in real or vm8086 mode, @@ -105,12 +103,6 @@ hvm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *r) hvm_funcs.load_cpu_guest_regs(v, r); } -static inline void -hvm_modify_guest_state(struct vcpu *v) -{ - hvm_funcs.modify_guest_state(v); -} - static inline int hvm_realmode(struct vcpu *v) { diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h index b74ed8c759..30d20238cf 100644 --- a/xen/include/asm-x86/hvm/svm/svm.h +++ b/xen/include/asm-x86/hvm/svm/svm.h @@ -39,7 +39,6 @@ extern unsigned int cpu_rev; extern void svm_stop(void); extern void svm_save_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs); extern void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs); -extern int svm_modify_vmcb(struct vcpu *v, struct cpu_user_regs *regs); extern void svm_vmread(struct vcpu *v, int index, unsigned long *value); extern void svm_vmwrite(struct vcpu *v, int index, unsigned long value); extern void svm_final_setup_guest(struct vcpu *v); diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index c77e665463..b2545bbd26 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -89,8 +89,6 @@ struct arch_vmx_struct { void vmx_do_resume(struct vcpu *); struct vmcs_struct *alloc_vmcs(void); -int modify_vmcs(struct arch_vmx_struct *arch_vmx, - struct cpu_user_regs *regs); void destroy_vmcs(struct arch_vmx_struct *arch_vmx); extern void vmx_request_clear_vmcs(struct vcpu *v); From e0d7fab70fbba5d42253b31f7841952121fa5fad Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 15:28:53 +0100 Subject: [PATCH 024/151] Fix comment. Signed-off-by: Steven Hand --- xen/include/asm-x86/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 3360a2a5a0..23aabeb2b9 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -212,13 +212,13 @@ extern unsigned long _end; /* standard ELF symbol */ * ------ ------ * I/O remapping area ( 4MB) * Direct-map (1:1) area [Xen code/data/heap] (12MB) - * Per-domain mappings (inc. 4MB map_domain_page cache) ( 4MB) + * Per-domain mappings (inc. 4MB map_domain_page cache) ( 8MB) * Shadow linear pagetable ( 4MB) ( 8MB) * Guest linear pagetable ( 4MB) ( 8MB) * Machine-to-physical translation table [writable] ( 4MB) (16MB) * Frame-info table (24MB) (96MB) * * Start of guest inaccessible area - * Machine-to-physical translation table [read-only] ( 4MB) + * Machine-to-physical translation table [read-only] ( 4MB) (16MB) * * Start of guest unmodifiable area */ From 20603fcf9a4c03a729762a76dec07a9741b8cb8e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 16:53:37 +0100 Subject: [PATCH 025/151] The attached trivial patch fixes cases where a block device is mounted read-only in domain 0, but still fails to be shared with a domU, because it is mis-identified as being mounted writable. (On SUSE, CDs and DVDs are auto-mounted not with merely permissions "ro", but "ro,nosuid,nodev", hence the mis-identification.) Signed-off-by: Charles Coffing --- tools/examples/block | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/examples/block b/tools/examples/block index 5a43560eff..dae32dc234 100644 --- a/tools/examples/block +++ b/tools/examples/block @@ -72,7 +72,7 @@ check_sharing() then toskip="^$" else - toskip="^[^ ]* [^ ]* [^ ]* ro " + toskip="^[^ ]* [^ ]* [^ ]* ro[, ]" fi for file in $(cat /proc/mounts | grep -v "$toskip" | cut -f 1 -d ' ') From 78b637ac771ca9518659dce465f95592c178eaec Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 30 Mar 2006 17:25:03 +0100 Subject: [PATCH 026/151] Added medium-length (around 20 minute run-time) test group. Signed-off-by: Ewan Mellor --- tools/xm-test/README | 4 +++- tools/xm-test/grouptest/medium | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tools/xm-test/grouptest/medium diff --git a/tools/xm-test/README b/tools/xm-test/README index 978e0dc693..61023f4d7b 100644 --- a/tools/xm-test/README +++ b/tools/xm-test/README @@ -140,9 +140,11 @@ and test lists as required. Default group run is "grouptest/default". # ./runtest.sh -g * NOTE: There is a quick set of tests in group mode, that was added to -run certain casenames and tests. It is not a substitute for the full +run certain casenames and tests, and there is a "medium" group, which is a +medium-length run (around 20 minutes). Neither is a substitute for the full xm-test test suite. # ./runtest.sh -g quick + # ./runtest.sh -g medium diff --git a/tools/xm-test/grouptest/medium b/tools/xm-test/grouptest/medium new file mode 100644 index 0000000000..de88800e63 --- /dev/null +++ b/tools/xm-test/grouptest/medium @@ -0,0 +1,25 @@ +block-create 09_block_attach_and_dettach_device_check_data_pos.test +block-list +console +destroy 01_destroy_basic_pos.test 02_destroy_noparm_neg.test 03_destroy_nonexist_neg.test 04_destroy_badparm_neg.test 05_destroy_byid_pos.test 06_destroy_dom0_neg.test +dmesg +domid +domname +enforce_dom0_cpus +help +info +list +memmax +memset 01_memset_basic_pos.test 02_memset_badparm_neg.test 04_memset_smallmem_pos.test +migrate +network-attach 03_network_attach_detach_multiple_pos.test +reboot +restore 02_restore_badparm_neg.test 03_restore_badfilename_neg.test 04_restore_withdevices_pos.test +save +sedf +shutdown +sysrq 01_sysrq_basic_neg.test 02_sysrq_sync_pos.test +unpause +vcpu-disable +vcpu-pin +vtpm From 811ca618e388b05ea7117aea424c1d3af4a4ef58 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 17:50:40 +0100 Subject: [PATCH 027/151] Change how we add the include asm override to CPPFLAGS. Add to CPPFLAGS instead of entirely redefining it. Signed-off-by: Christian Limpach --- linux-2.6-xen-sparse/arch/i386/Makefile | 2 +- linux-2.6-xen-sparse/arch/x86_64/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/Makefile b/linux-2.6-xen-sparse/arch/i386/Makefile index 527707677e..d715e410e6 100644 --- a/linux-2.6-xen-sparse/arch/i386/Makefile +++ b/linux-2.6-xen-sparse/arch/i386/Makefile @@ -107,7 +107,7 @@ boot := arch/i386/boot zdisk bzdisk fdimage fdimage144 fdimage288 install ifdef CONFIG_XEN -CPPFLAGS := -D__KERNEL__ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(LINUXINCLUDE) +CPPFLAGS := -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS) head-y := arch/i386/kernel/head-xen.o arch/i386/kernel/init_task-xen.o boot := arch/i386/boot-xen .PHONY: vmlinuz diff --git a/linux-2.6-xen-sparse/arch/x86_64/Makefile b/linux-2.6-xen-sparse/arch/x86_64/Makefile index 6ac38f51a8..5d67f13b03 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/Makefile +++ b/linux-2.6-xen-sparse/arch/x86_64/Makefile @@ -71,7 +71,7 @@ boot := arch/x86_64/boot fdimage fdimage144 fdimage288 archclean ifdef CONFIG_XEN -CPPFLAGS := -D__KERNEL__ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(LINUXINCLUDE) +CPPFLAGS := -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS) head-y := arch/x86_64/kernel/head-xen.o arch/x86_64/kernel/head64-xen.o arch/x86_64/kernel/init_task.o LDFLAGS_vmlinux := -e _start boot := arch/i386/boot-xen From 13678d4465f496f1ad01e8cbf6ccbec64b5e35b5 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Thu, 30 Mar 2006 17:50:44 +0100 Subject: [PATCH 028/151] Remove __HYPERVISOR_sched_op_new in favour of a header file interface version number system. Define interface version in Kconfig and define it through CPPFLAGS for C and assembly file compilation. Add HYPERVISOR_{yield,block,shutdown} to remove direct use of sched_op from guest code. Signed-off-by: Christian Limpach --- linux-2.6-xen-sparse/arch/i386/Makefile | 5 ++ .../arch/i386/kernel/process-xen.c | 2 +- .../arch/i386/kernel/setup-xen.c | 2 +- linux-2.6-xen-sparse/arch/ia64/Makefile | 6 ++ linux-2.6-xen-sparse/arch/x86_64/Makefile | 4 ++ .../arch/x86_64/kernel/process-xen.c | 2 +- .../arch/x86_64/kernel/setup-xen.c | 2 +- linux-2.6-xen-sparse/drivers/xen/Kconfig | 14 +++-- .../drivers/xen/core/reboot.c | 4 +- .../include/asm-i386/mach-xen/asm/hypercall.h | 47 ++++++-------- .../asm-i386/mach-xen/asm/hypervisor.h | 61 +++++++++++++++++++ .../include/asm-ia64/hypercall.h | 47 ++++++-------- .../include/asm-ia64/hypervisor.h | 60 ++++++++++++++++++ .../asm-x86_64/mach-xen/asm/hypercall.h | 47 ++++++-------- xen/include/public/xen-compat.h | 21 +++++++ xen/include/public/xen.h | 6 +- 16 files changed, 232 insertions(+), 98 deletions(-) create mode 100644 xen/include/public/xen-compat.h diff --git a/linux-2.6-xen-sparse/arch/i386/Makefile b/linux-2.6-xen-sparse/arch/i386/Makefile index d715e410e6..54ee32ee57 100644 --- a/linux-2.6-xen-sparse/arch/i386/Makefile +++ b/linux-2.6-xen-sparse/arch/i386/Makefile @@ -45,6 +45,11 @@ CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-op CFLAGS += $(cflags-y) +cppflags-$(CONFIG_XEN) += \ + -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) + +CPPFLAGS += $(cppflags-y) + # Default subarch .c files mcore-y := mach-default diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c index 47cde961a3..02f2835f56 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c @@ -114,7 +114,7 @@ void xen_idle(void) smp_mb__after_clear_bit(); stop_hz_timer(); /* Blocking includes an implicit local_irq_enable(). */ - HYPERVISOR_sched_op(SCHEDOP_block, 0); + HYPERVISOR_block(); start_hz_timer(); set_thread_flag(TIF_POLLING_NRFLAG); } diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c index 8a83da25e7..11d17a7a12 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c @@ -1877,7 +1877,7 @@ void __init setup_arch(char **cmdline_p) static int xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { - HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash); + HYPERVISOR_shutdown(SHUTDOWN_crash); /* we're never actually going to get here... */ return NOTIFY_DONE; } diff --git a/linux-2.6-xen-sparse/arch/ia64/Makefile b/linux-2.6-xen-sparse/arch/ia64/Makefile index 172b4cfd44..99487f4433 100644 --- a/linux-2.6-xen-sparse/arch/ia64/Makefile +++ b/linux-2.6-xen-sparse/arch/ia64/Makefile @@ -42,6 +42,12 @@ ifeq ($(call cc-version),0304) endif CFLAGS += $(cflags-y) + +cppflags-$(CONFIG_XEN) += \ + -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) + +CPPFLAGS += $(cppflags-y) + head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o libs-y += arch/ia64/lib/ diff --git a/linux-2.6-xen-sparse/arch/x86_64/Makefile b/linux-2.6-xen-sparse/arch/x86_64/Makefile index 5d67f13b03..9164bf30a0 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/Makefile +++ b/linux-2.6-xen-sparse/arch/x86_64/Makefile @@ -31,6 +31,10 @@ cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) CFLAGS += $(cflags-y) +cppflags-$(CONFIG_XEN) += \ + -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) +CPPFLAGS += $(cppflags-y) + CFLAGS += -m64 CFLAGS += -mno-red-zone CFLAGS += -mcmodel=kernel diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c index d983037572..7127fb57f3 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c @@ -131,7 +131,7 @@ void xen_idle(void) smp_mb__after_clear_bit(); stop_hz_timer(); /* Blocking includes an implicit local_irq_enable(). */ - HYPERVISOR_sched_op(SCHEDOP_block, 0); + HYPERVISOR_block(); start_hz_timer(); set_thread_flag(TIF_POLLING_NRFLAG); } diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c index cfa9bbf17b..30f8b40513 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c @@ -999,7 +999,7 @@ void __init setup_arch(char **cmdline_p) static int xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { - HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash); + HYPERVISOR_shutdown(SHUTDOWN_crash); /* we're never actually going to get here... */ return NOTIFY_DONE; } diff --git a/linux-2.6-xen-sparse/drivers/xen/Kconfig b/linux-2.6-xen-sparse/drivers/xen/Kconfig index f452b2f75d..6518ff821a 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig @@ -10,12 +10,11 @@ config XEN help This is the Linux Xen port. -config NO_IDLE_HZ - bool - depends on XEN - default y - if XEN +config XEN_INTERFACE_VERSION + hex + default 0x00030101 + menu "XEN" config XEN_PRIVILEGED_GUEST @@ -191,7 +190,6 @@ config XEN_DISABLE_SERIAL config XEN_SYSFS tristate "Export Xen attributes in sysfs" - depends on XEN depends on SYSFS default y help @@ -207,4 +205,8 @@ config HAVE_ARCH_DEV_ALLOC_SKB bool default y +config NO_IDLE_HZ + bool + default y + endif diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index 828d287f3e..990dc35cee 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -42,7 +42,7 @@ void machine_emergency_restart(void) { /* We really want to get pending console data out before we die. */ xencons_force_flush(); - HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_reboot); + HYPERVISOR_shutdown(SHUTDOWN_reboot); } void machine_restart(char * __unused) @@ -59,7 +59,7 @@ void machine_power_off(void) { /* We really want to get pending console data out before we die. */ xencons_force_flush(); - HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_poweroff); + HYPERVISOR_shutdown(SHUTDOWN_poweroff); } int reboot_thru_bios = 0; /* for dmi_scan.c */ diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h index a7832cad1a..20977d0b80 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h @@ -33,10 +33,9 @@ #ifndef __HYPERCALL_H__ #define __HYPERCALL_H__ -#include -#include -#include -#include +#ifndef __HYPERVISOR_H__ +# error "please don't include this file directly" +#endif #define __STR(x) #x #define STR(x) __STR(x) @@ -167,35 +166,17 @@ HYPERVISOR_fpu_taskswitch( } static inline int -HYPERVISOR_sched_op( +HYPERVISOR_sched_op_compat( int cmd, unsigned long arg) { - return _hypercall2(int, sched_op, cmd, arg); + return _hypercall2(int, sched_op_compat, cmd, arg); } static inline int -HYPERVISOR_sched_op_new( +HYPERVISOR_sched_op( int cmd, void *arg) { - return _hypercall2(int, sched_op_new, cmd, arg); -} - -static inline int -HYPERVISOR_poll( - evtchn_port_t *ports, unsigned int nr_ports, u64 timeout) -{ - struct sched_poll sched_poll = { - .ports = ports, - .nr_ports = nr_ports, - .timeout = jiffies_to_st(timeout) - }; - - int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll); - - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0); - - return rc; + return _hypercall2(int, sched_op, cmd, arg); } static inline long @@ -327,8 +308,18 @@ static inline int HYPERVISOR_suspend( unsigned long srec) { - return _hypercall3(int, sched_op, SCHEDOP_shutdown, - SHUTDOWN_suspend, srec); + struct sched_shutdown sched_shutdown = { + .reason = SHUTDOWN_suspend + }; + + int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, + &sched_shutdown, srec); + + if (rc == -ENOSYS) + rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, + SHUTDOWN_suspend, srec); + + return rc; } static inline int diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h index 2bc97ae342..325a6c8a5b 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h @@ -37,8 +37,11 @@ #include #include #include +#include #include #include +#include +#include #include #include #if defined(__i386__) @@ -115,6 +118,64 @@ u64 jiffies_to_st(unsigned long jiffies); #define xen_init() (0) +static inline int +HYPERVISOR_yield( + void) +{ + int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); + + return rc; +} + +static inline int +HYPERVISOR_block( + void) +{ + int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0); + + return rc; +} + +static inline int +HYPERVISOR_shutdown( + unsigned int reason) +{ + struct sched_shutdown sched_shutdown = { + .reason = reason + }; + + int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason); + + return rc; +} + +static inline int +HYPERVISOR_poll( + evtchn_port_t *ports, unsigned int nr_ports, u64 timeout) +{ + struct sched_poll sched_poll = { + .ports = ports, + .nr_ports = nr_ports, + .timeout = jiffies_to_st(timeout) + }; + + int rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); + + return rc; +} + static inline void MULTI_update_va_mapping( multicall_entry_t *mcl, unsigned long va, diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h index b260c56e76..d255cf41cf 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @@ -33,10 +33,9 @@ #ifndef __HYPERCALL_H__ #define __HYPERCALL_H__ -#include -#include -#include -#include +#ifndef __HYPERVISOR_H__ +# error "please don't include this file directly" +#endif /* FIXME: temp place to hold these page related macros */ #include @@ -164,35 +163,17 @@ }) static inline int -HYPERVISOR_sched_op( +HYPERVISOR_sched_op_compat( int cmd, unsigned long arg) { - return _hypercall2(int, sched_op, cmd, arg); + return _hypercall2(int, sched_op_compat, cmd, arg); } static inline int -HYPERVISOR_sched_op_new( +HYPERVISOR_sched_op( int cmd, void *arg) { - return _hypercall2(int, sched_op_new, cmd, arg); -} - -static inline int -HYPERVISOR_poll( - evtchn_port_t *ports, unsigned int nr_ports, unsigned long timeout) -{ - struct sched_poll sched_poll = { - .ports = ports, - .nr_ports = nr_ports, - .timeout = jiffies_to_st(timeout) - }; - - int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll); - - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0); - - return rc; + return _hypercall2(int, sched_op, cmd, arg); } static inline long @@ -272,8 +253,18 @@ static inline int HYPERVISOR_suspend( unsigned long srec) { - return _hypercall3(int, sched_op, SCHEDOP_shutdown, - SHUTDOWN_suspend, srec); + struct sched_shutdown sched_shutdown = { + .reason = SHUTDOWN_suspend + }; + + int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, + &sched_shutdown, srec); + + if (rc == -ENOSYS) + rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, + SHUTDOWN_suspend, srec); + + return rc; } extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h index 4a5f424417..ecd51adcc0 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h @@ -37,8 +37,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -54,6 +56,64 @@ int xen_init(void); #include +static inline int +HYPERVISOR_yield( + void) +{ + int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); + + return rc; +} + +static inline int +HYPERVISOR_block( + void) +{ + int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0); + + return rc; +} + +static inline int +HYPERVISOR_shutdown( + unsigned int reason) +{ + struct sched_shutdown sched_shutdown = { + .reason = reason + }; + + int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason); + + return rc; +} + +static inline int +HYPERVISOR_poll( + evtchn_port_t *ports, unsigned int nr_ports, u64 timeout) +{ + struct sched_poll sched_poll = { + .ports = ports, + .nr_ports = nr_ports, + .timeout = jiffies_to_st(timeout) + }; + + int rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); + + return rc; +} + // for drivers/xen/privcmd/privcmd.c #define direct_remap_pfn_range(a,b,c,d,e,f) remap_pfn_range(a,b,c,d,e) #define pfn_to_mfn(x) (x) diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h index 4071a1d6fd..6b7411f4c5 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h @@ -37,10 +37,9 @@ #ifndef __HYPERCALL_H__ #define __HYPERCALL_H__ -#include -#include -#include -#include +#ifndef __HYPERVISOR_H__ +# error "please don't include this file directly" +#endif #define __STR(x) #x #define STR(x) __STR(x) @@ -172,35 +171,17 @@ HYPERVISOR_fpu_taskswitch( } static inline int -HYPERVISOR_sched_op( +HYPERVISOR_sched_op_compat( int cmd, unsigned long arg) { - return _hypercall2(int, sched_op, cmd, arg); + return _hypercall2(int, sched_op_compat, cmd, arg); } static inline int -HYPERVISOR_sched_op_new( +HYPERVISOR_sched_op( int cmd, void *arg) { - return _hypercall2(int, sched_op_new, cmd, arg); -} - -static inline int -HYPERVISOR_poll( - evtchn_port_t *ports, unsigned int nr_ports, u64 timeout) -{ - struct sched_poll sched_poll = { - .ports = ports, - .nr_ports = nr_ports, - .timeout = jiffies_to_st(timeout) - }; - - int rc = HYPERVISOR_sched_op_new(SCHEDOP_poll, &sched_poll); - - if (rc == -ENOSYS) - rc = HYPERVISOR_sched_op(SCHEDOP_yield, 0); - - return rc; + return _hypercall2(int, sched_op, cmd, arg); } static inline long @@ -328,8 +309,18 @@ static inline int HYPERVISOR_suspend( unsigned long srec) { - return _hypercall3(int, sched_op, SCHEDOP_shutdown, - SHUTDOWN_suspend, srec); + struct sched_shutdown sched_shutdown = { + .reason = SHUTDOWN_suspend + }; + + int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, + &sched_shutdown, srec); + + if (rc == -ENOSYS) + rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, + SHUTDOWN_suspend, srec); + + return rc; } static inline int diff --git a/xen/include/public/xen-compat.h b/xen/include/public/xen-compat.h new file mode 100644 index 0000000000..67af72b344 --- /dev/null +++ b/xen/include/public/xen-compat.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * xen-compat.h + * + * Guest OS interface to Xen. Compatibility layer. + * + * Copyright (c) 2006, Christian Limpach + */ + +#ifndef __XEN_PUBLIC_XEN_COMPAT_H__ +#define __XEN_PUBLIC_XEN_COMPAT_H__ + +#ifndef __XEN_INTERFACE_VERSION__ +#define __XEN_INTERFACE_VERSION__ 0x00000000 +#endif + +#if __XEN_INTERFACE_VERSION__ < 0x00030101 +#undef __HYPERVISOR_sched_op +#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat +#endif + +#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 5d88c9c8af..2921a140cd 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -37,7 +37,7 @@ #define __HYPERVISOR_stack_switch 3 #define __HYPERVISOR_set_callbacks 4 #define __HYPERVISOR_fpu_taskswitch 5 -#define __HYPERVISOR_sched_op 6 +#define __HYPERVISOR_sched_op_compat 6 /* compat as of 0x00030101 */ #define __HYPERVISOR_dom0_op 7 #define __HYPERVISOR_set_debugreg 8 #define __HYPERVISOR_get_debugreg 9 @@ -59,7 +59,7 @@ #define __HYPERVISOR_mmuext_op 26 #define __HYPERVISOR_acm_op 27 #define __HYPERVISOR_nmi_op 28 -#define __HYPERVISOR_sched_op_new 29 +#define __HYPERVISOR_sched_op 29 /* * VIRTUAL INTERRUPTS @@ -436,6 +436,8 @@ typedef uint8_t xen_domain_handle_t[16]; #endif /* !__ASSEMBLY__ */ +#include "xen-compat.h" + #endif /* __XEN_PUBLIC_XEN_H__ */ /* From 26c829aa89c7686c0fb591429c654837e1606d40 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Fri, 31 Mar 2006 00:09:42 +0100 Subject: [PATCH 029/151] Don't use abbreviated ip subcommands -- these are not accepted by iproute2. Closes bug #478. Signed-off-by: Ewan Mellor --- tools/examples/README.incompatibilities | 7 +++++++ tools/examples/vif-route | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/examples/README.incompatibilities b/tools/examples/README.incompatibilities index 87b2dbd62e..bb067bd419 100644 --- a/tools/examples/README.incompatibilities +++ b/tools/examples/README.incompatibilities @@ -24,6 +24,13 @@ Gentoo doesn't have ifup/ifdown; appropriate alternatives are defined in xen-network-common.sh. +ip +-- + +Newer ip commands (from iproute2) do not accept the abbreviated syntax "ip r a +..." etc. "ip route add ..." must be used instead. + + sed --- diff --git a/tools/examples/vif-route b/tools/examples/vif-route index d733119d30..1d5d299b60 100755 --- a/tools/examples/vif-route +++ b/tools/examples/vif-route @@ -29,11 +29,11 @@ case "$command" in online) ifconfig ${vif} ${main_ip} netmask 255.255.255.255 up echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp - ipcmd='a' + ipcmd='add' ;; offline) ifdown ${vif} - ipcmd='d' + ipcmd='del' ;; esac @@ -41,7 +41,7 @@ if [ "${ip}" ] ; then # If we've been given a list of IP addresses, then add routes from dom0 to # the guest using those addresses. for addr in ${ip} ; do - ip r ${ipcmd} ${addr} dev ${vif} src ${main_ip} + ip route ${ipcmd} ${addr} dev ${vif} src ${main_ip} done fi From 7a6ee342c3327ed47c87fd52252e8930f3e5b097 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Fri, 31 Mar 2006 00:10:54 +0100 Subject: [PATCH 030/151] Further attempts to recover from a corrupt store, this one triggered when a tdb_store fails. Signed-off-by: Ewan Mellor --- tools/xenstore/xenstored_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 6515b1b21e..f4fa447d07 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -469,6 +469,7 @@ static bool write_node(struct connection *conn, const struct node *node) /* TDB should set errno, but doesn't even set ecode AFAICT. */ if (tdb_store(tdb_context(conn), key, data, TDB_REPLACE) != 0) { + corrupt(conn, "Write of %s = %s failed", key, data); errno = ENOSPC; return false; } From 8d3271b7cc8050da140660c97cbdeed9d8c4768e Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Fri, 31 Mar 2006 00:13:33 +0100 Subject: [PATCH 031/151] Set the permissions correctly on the XML-RPC UDP socket, so that non-root users cannot use the socket. This closes a security hole, and fixes the intermittent failure of xm-test/06_list_nonroot.test. c.f. xen-unstable changeset 9205:faa1eb1621b9 (same bug, different socket). Signed-off-by: Ewan Mellor --- tools/python/xen/util/xmlrpclib2.py | 13 ++++++++----- tools/python/xen/xend/XendClient.py | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index 214a678fac..c0f769f6f2 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -23,7 +23,7 @@ An enhanced XML-RPC client/server interface for Python. from httplib import HTTPConnection, HTTP from xmlrpclib import Transport from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler -import xmlrpclib, socket, os +import xmlrpclib, socket, os, stat import SocketServer import xen.xend.XendClient @@ -105,10 +105,13 @@ class UnixXMLRPCServer(TCPXMLRPCServer): address_family = socket.AF_UNIX def __init__(self, addr, logRequests): - if self.allow_reuse_address: - try: + parent = os.path.dirname(addr) + if os.path.exists(parent): + os.chown(parent, os.geteuid(), os.getegid()) + os.chmod(parent, stat.S_IRWXU) + if self.allow_reuse_address and os.path.exists(addr): os.unlink(addr) - except OSError, exc: - pass + else: + os.makedirs(parent, stat.S_IRWXU) TCPXMLRPCServer.__init__(self, addr, UnixXMLRPCRequestHandler, logRequests) diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 974f4b7121..fb9974aa5a 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -19,10 +19,10 @@ from xen.util.xmlrpclib2 import ServerProxy -XML_RPC_SOCKET = "/var/run/xend-xmlrpc.sock" +XML_RPC_SOCKET = "/var/run/xend/xmlrpc.sock" ERROR_INTERNAL = 1 ERROR_GENERIC = 2 ERROR_INVALID_DOMAIN = 3 -server = ServerProxy('httpu:///var/run/xend-xmlrpc.sock') +server = ServerProxy('httpu:///var/run/xend/xmlrpc.sock') From 6b914525affdc9225cd8d7521382d04c81344bff Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Fri, 31 Mar 2006 00:14:09 +0100 Subject: [PATCH 032/151] Print error messages to stderr. Remove unused handle_xend_error. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index a636dd5e84..9a3c6f5d32 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -291,18 +291,6 @@ def int_unit(str, dest): def err(msg): print >>sys.stderr, "Error:", msg -def handle_xend_error(cmd, args, ex): - non_option = filter(lambda x: x[0] != '-', args) - dom = len(non_option) > 0 and non_option[0] or None - - error = str(ex) - if error == "Not found" and dom != None: - err("Domain '%s' not found when running 'xm %s'" % (dom, cmd)) - else: - err(error) - - sys.exit(1) - ######################################################################### # @@ -1106,9 +1094,10 @@ def main(argv=sys.argv): sys.exit(1) except xmlrpclib.Fault, ex: if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN: - print "Error: the domain '%s' does not exist." % ex.faultString + print >>sys.stderr, ( + "Error: the domain '%s' does not exist." % ex.faultString) else: - print "Error: %s" % ex.faultString + print >>sys.stderr, "Error: %s" % ex.faultString sys.exit(1) except: print "Unexpected error:", sys.exc_info()[0] From 0464aecf6c9e27388f7942f7ae9ff8a30ec4719e Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Fri, 31 Mar 2006 00:15:12 +0100 Subject: [PATCH 033/151] Better formatting of error messages for xmlrpclib.Faults, matching similar code in main.py. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/create.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 045930530d..adfd6f1f42 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -27,9 +27,11 @@ import socket import commands import time import re +import xmlrpclib from xen.xend import sxp from xen.xend import PrettyPrint +import xen.xend.XendClient from xen.xend.XendClient import server from xen.xend.XendBootloader import bootloader from xen.util import blkif @@ -814,6 +816,14 @@ def make_domain(opts, config): try: dominfo = server.xend.domain.create(config) + except xmlrpclib.Fault, ex: + import signal + if vncpid: + os.kill(vncpid, signal.SIGKILL) + if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN: + err("the domain '%s' does not exist." % ex.faultString) + else: + err("%s" % ex.faultString) except Exception, ex: import signal if vncpid: @@ -824,6 +834,9 @@ def make_domain(opts, config): try: server.xend.domain.waitForDevices(dom) + except xmlrpclib.Fault, ex: + server.xend.domain.destroy(dom) + err("%s" % ex.faultString) except: server.xend.domain.destroy(dom) err("Device creation failed for domain %s" % dom) From f207095aac35b93267aaf09faee33cfe80f04f5e Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Fri, 31 Mar 2006 00:24:54 +0100 Subject: [PATCH 034/151] Remove the transaction parameter from xenbus_switch_state and move the state switch out of a transaction, in the few cases where it is inside one. In order to behave properly, it is necessary for a driver to know its own xenbus state (see changeset 9469:b3cb19d2b07f, for example). This value is stored as xenbus_device.state and updated by xenbus_switch_state. If xenbus_switch_state occurs within a transaction, then there is a possibility that the transaction would be aborted, leaving the state field dangerously out of sync with the value currently in the store. This fixes recent problems seen whereby bringing multiple devices up at the same time results in some devices not coming up (often all of the even-numbered ones, because of the pattern of transaction conflict). Signed-off-by: Ewan Mellor --- .../drivers/xen/blkback/xenbus.c | 14 ++++++++------ .../drivers/xen/blkfront/blkfront.c | 12 +++++------- .../drivers/xen/netback/xenbus.c | 6 +++--- .../drivers/xen/netfront/netfront.c | 2 +- .../drivers/xen/pciback/xenbus.c | 8 ++++---- .../drivers/xen/pcifront/xenbus.c | 11 ++++------- .../drivers/xen/tpmback/xenbus.c | 17 +++++++---------- .../drivers/xen/xenbus/xenbus_client.c | 18 +++++++++++------- .../drivers/xen/xenbus/xenbus_probe.c | 4 ++-- linux-2.6-xen-sparse/include/xen/xenbus.h | 10 +++------- 10 files changed, 48 insertions(+), 54 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 23fe51a362..636caefdd8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -142,7 +142,7 @@ static int blkback_probe(struct xenbus_device *dev, if (err) goto fail; - err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait); + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) goto fail; @@ -270,7 +270,7 @@ static void frontend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); + xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: @@ -343,15 +343,17 @@ again: goto abort; } - err = xenbus_switch_state(dev, xbt, XenbusStateConnected); - if (err) - goto abort; - err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) xenbus_dev_fatal(dev, err, "ending transaction"); + + err = xenbus_switch_state(dev, XenbusStateConnected); + if (err) + xenbus_dev_fatal(dev, err, "switching to Connected state", + dev->nodename); + return; abort: xenbus_transaction_end(xbt, 1); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 6e29fa3d75..4999636207 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -176,10 +176,6 @@ again: goto abort_transaction; } - err = xenbus_switch_state(dev, xbt, XenbusStateInitialised); - if (err) - goto abort_transaction; - err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) @@ -188,6 +184,8 @@ again: goto destroy_blkring; } + xenbus_switch_state(dev, XenbusStateInitialised); + return 0; abort_transaction: @@ -324,7 +322,7 @@ static void connect(struct blkfront_info *info) return; } - (void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected); + (void)xenbus_switch_state(info->xbdev, XenbusStateConnected); /* Kick pending requests. */ spin_lock_irq(&blkif_io_lock); @@ -349,7 +347,7 @@ static void blkfront_closing(struct xenbus_device *dev) xlvbd_del(info); - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed); + xenbus_switch_state(dev, XenbusStateClosed); } @@ -755,7 +753,7 @@ static void blkif_recover(struct blkfront_info *info) kfree(copy); - (void)xenbus_switch_state(info->xbdev, XBT_NULL, XenbusStateConnected); + (void)xenbus_switch_state(info->xbdev, XenbusStateConnected); /* Now safe for us to use the shared ring */ spin_lock_irq(&blkif_io_lock); diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index 52a4fc98c8..ea9a02e28e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -92,7 +92,7 @@ static int netback_probe(struct xenbus_device *dev, if (err) goto fail; - err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait); + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) { goto fail; } @@ -209,7 +209,7 @@ static void frontend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); + xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: @@ -254,7 +254,7 @@ static void connect(struct backend_info *be) return; } - xenbus_switch_state(dev, XBT_NULL, XenbusStateConnected); + xenbus_switch_state(dev, XenbusStateConnected); } diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 220e9aa343..6c7b82f789 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -1216,7 +1216,7 @@ static void netfront_closing(struct xenbus_device *dev) close_netdev(info); - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed); + xenbus_switch_state(dev, XenbusStateClosed); } diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c index c64d250067..dc369d0efb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c @@ -137,7 +137,7 @@ static int pciback_attach(struct pciback_device *pdev) dev_dbg(&pdev->xdev->dev, "Connecting...\n"); - err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected); + err = xenbus_switch_state(pdev->xdev, XenbusStateConnected); if (err) xenbus_dev_fatal(pdev->xdev, err, "Error switching to connected state!"); @@ -165,7 +165,7 @@ static void pciback_frontend_changed(struct xenbus_device *xdev, break; case XenbusStateClosing: - xenbus_switch_state(xdev, XBT_NULL, XenbusStateClosing); + xenbus_switch_state(xdev, XenbusStateClosing); break; case XenbusStateClosed: @@ -341,7 +341,7 @@ static int pciback_setup_backend(struct pciback_device *pdev) goto out; } - err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateInitialised); + err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised); if (err) xenbus_dev_fatal(pdev->xdev, err, "Error switching to initialised state!"); @@ -386,7 +386,7 @@ static int pciback_xenbus_probe(struct xenbus_device *dev, } /* wait for xend to configure us */ - err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait); + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) goto out; diff --git a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c index eed89eb5d3..ee154ba360 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c @@ -96,10 +96,6 @@ static int pcifront_publish_info(struct pcifront_device *pdev) if (!err) err = xenbus_printf(trans, pdev->xdev->nodename, "magic", XEN_PCI_MAGIC); - if (!err) - err = - xenbus_switch_state(pdev->xdev, trans, - XenbusStateInitialised); if (err) { xenbus_transaction_end(trans, 1); @@ -118,6 +114,8 @@ static int pcifront_publish_info(struct pcifront_device *pdev) } } + xenbus_switch_state(pdev->xdev, XenbusStateInitialised); + dev_dbg(&pdev->xdev->dev, "publishing successful!\n"); out: @@ -186,7 +184,7 @@ static int pcifront_try_connect(struct pcifront_device *pdev) } } - err = xenbus_switch_state(pdev->xdev, XBT_NULL, XenbusStateConnected); + err = xenbus_switch_state(pdev->xdev, XenbusStateConnected); if (err) goto out; @@ -205,8 +203,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev) prev_state = xenbus_read_driver_state(pdev->xdev->nodename); if (prev_state < XenbusStateClosing) - err = xenbus_switch_state(pdev->xdev, XBT_NULL, - XenbusStateClosing); + err = xenbus_switch_state(pdev->xdev, XenbusStateClosing); if (!err && prev_state == XenbusStateConnected) pcifront_disconnect(pdev); diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index 6ce5f07891..14d6feb75e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -87,7 +87,7 @@ static int tpmback_probe(struct xenbus_device *dev, goto fail; } - err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait); + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) { goto fail; } @@ -175,7 +175,7 @@ static void frontend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); + xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: @@ -247,18 +247,15 @@ again: goto abort; } - err = xenbus_switch_state(dev, xbt, XenbusStateConnected); - if (err) - goto abort; - - be->tpmif->status = CONNECTED; - err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; - if (err) { + if (err) xenbus_dev_fatal(be->dev, err, "end of transaction"); - } + + err = xenbus_switch_state(dev, XenbusStateConnected); + if (!err) + be->tpmif->status = CONNECTED; return; abort: xenbus_transaction_end(xbt, 1); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c index 8126705aeb..38ac7f2c49 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @@ -84,9 +84,7 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path, EXPORT_SYMBOL_GPL(xenbus_watch_path2); -int xenbus_switch_state(struct xenbus_device *dev, - xenbus_transaction_t xbt, - XenbusState state) +int xenbus_switch_state(struct xenbus_device *dev, XenbusState state) { /* We check whether the state is currently set to the given value, and if not, then the state is set. We don't want to unconditionally @@ -94,6 +92,12 @@ int xenbus_switch_state(struct xenbus_device *dev, unnecessarily. Furthermore, if the node has gone, we don't write to it, as the device will be tearing down, and we don't want to resurrect that directory. + + Note that, because of this cached value of our state, this function + will not work inside a Xenstore transaction (something it was + trying to in the past) because dev->state would not get reset if + the transaction was aborted. + */ int current_state; @@ -102,12 +106,12 @@ int xenbus_switch_state(struct xenbus_device *dev, if (state == dev->state) return 0; - err = xenbus_scanf(xbt, dev->nodename, "state", "%d", - ¤t_state); + err = xenbus_scanf(XBT_NULL, dev->nodename, "state", "%d", + ¤t_state); if (err != 1) return 0; - err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); + err = xenbus_printf(XBT_NULL, dev->nodename, "state", "%d", state); if (err) { if (state != XenbusStateClosing) /* Avoid looping */ xenbus_dev_fatal(dev, err, "writing new state"); @@ -193,7 +197,7 @@ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, _dev_error(dev, err, fmt, ap); va_end(ap); - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); + xenbus_switch_state(dev, XenbusStateClosing); } EXPORT_SYMBOL_GPL(xenbus_dev_fatal); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 61158a6034..d3f37e636d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -364,7 +364,7 @@ static int xenbus_dev_probe(struct device *_dev) return 0; fail: xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed); + xenbus_switch_state(dev, XenbusStateClosed); return -ENODEV; } @@ -381,7 +381,7 @@ static int xenbus_dev_remove(struct device *_dev) if (drv->remove) drv->remove(dev); - xenbus_switch_state(dev, XBT_NULL, XenbusStateClosed); + xenbus_switch_state(dev, XenbusStateClosed); return 0; } diff --git a/linux-2.6-xen-sparse/include/xen/xenbus.h b/linux-2.6-xen-sparse/include/xen/xenbus.h index 6d69963870..b5a9da5f64 100644 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h @@ -204,14 +204,10 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path, /** * Advertise in the store a change of the given driver to the given new_state. - * Perform the change inside the given transaction xbt. xbt may be NULL, in - * which case this is performed inside its own transaction. Return 0 on - * success, or -errno on error. On error, the device will switch to - * XenbusStateClosing, and the error will be saved in the store. + * Return 0 on success, or -errno on error. On error, the device will switch + * to XenbusStateClosing, and the error will be saved in the store. */ -int xenbus_switch_state(struct xenbus_device *dev, - xenbus_transaction_t xbt, - XenbusState new_state); +int xenbus_switch_state(struct xenbus_device *dev, XenbusState new_state); /** From f651bf191b0f75c8bc83a1535a2bc328f60ad185 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 10:06:20 +0100 Subject: [PATCH 035/151] The ia64 build doesn't yet include drivers/xen/Kconfig directly so we need to replicate the new XEN_INTERFACE_VERSION option in the arch Kconfig. Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-2.6-xen-sparse/arch/ia64/Kconfig b/linux-2.6-xen-sparse/arch/ia64/Kconfig index 54584bdbac..db86da7611 100644 --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig @@ -91,6 +91,11 @@ config XEN_SYSFS help Xen hypervisor attributes will show up under /sys/hypervisor/. +config XEN_INTERFACE_VERSION + hex + depends on XEN + default 0x00030101 + config SCHED_NO_NO_OMIT_FRAME_POINTER bool default y From 3d95d58003486f471d73cfbefba347aa4a484436 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 10:07:55 +0100 Subject: [PATCH 036/151] Enable the setting and trapping of breakpoints for hvm guest. Catch Ctrl-C for gdbserver and let gdb break from continue command. Signed-Off-By: Nitin A Kamble --- .../gdb/gdbserver/server.c | 33 +++++++++++++++++++ tools/libxc/xc_ptrace.c | 10 ++++-- xen/arch/x86/hvm/vmx/vmx.c | 8 +++++ xen/include/asm-x86/hvm/support.h | 1 + 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c index c987c0eb9d..3e1f50ea49 100644 --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c @@ -286,6 +286,21 @@ handle_v_requests (char *own_buf, char *status, unsigned char *signal) return; } +void +handle_breakpoint_requests (char *own_buf, char *status, unsigned char *signal) +{ + /* Currently we only support software breakpoints */ + switch (own_buf[1]) { + case '0': /* software breakpoint, int3 based */ + own_buf[0] = '\0'; + break; + case '1': /* hardware breakpoint */ + default: + write_enn (own_buf); + break; + } +} + void myresume (int step, int sig) { @@ -322,6 +337,18 @@ gdbserver_usage (void) "HOST:PORT to listen for a TCP connection.\n"); } +extern control_c_pressed_flag; +#include + +void ctrl_c_handler(int signo) +{ + printf("Ctrl-C pressed: Quit from the attached gdb first\n"); + control_c_pressed_flag = 1; +} + +struct sigaction ctrl_c_sigaction = { .sa_handler = ctrl_c_handler }; +struct sigaction old_sigaction; + int main (int argc, char *argv[]) { @@ -396,9 +423,11 @@ main (int argc, char *argv[]) } } + while (1) { remote_open (argv[1]); + sigaction(SIGINT, &ctrl_c_sigaction, &old_sigaction); restart: setjmp (toplevel); @@ -587,6 +616,9 @@ main (int argc, char *argv[]) /* Extended (long) request. */ handle_v_requests (own_buf, &status, &signal); break; + case 'Z': + handle_breakpoint_requests (own_buf, &status, &signal); + break; default: /* It is a request we don't understand. Respond with an empty packet so that gdb knows that we don't support this @@ -643,5 +675,6 @@ main (int argc, char *argv[]) "GDBserver will reopen the connection.\n"); remote_close (); } + sigaction(SIGINT, &old_sigaction, NULL); } } diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c index f83005b45c..30fe1db22e 100644 --- a/tools/libxc/xc_ptrace.c +++ b/tools/libxc/xc_ptrace.c @@ -401,6 +401,8 @@ map_domain_va( return map_domain_va_32(xc_handle, cpu, guest_va, perm); } +int control_c_pressed_flag = 0; + static int __xc_waitdomain( int xc_handle, @@ -419,7 +421,6 @@ __xc_waitdomain( op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = domain; - retry: retval = do_dom0_op(xc_handle, &op); if ( retval || (op.u.getdomaininfo.domain != domain) ) @@ -432,12 +433,17 @@ __xc_waitdomain( if ( options & WNOHANG ) goto done; + if (control_c_pressed_flag) { + xc_domain_pause(xc_handle, domain); + control_c_pressed_flag = 0; + goto done; + } + if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ) { nanosleep(&ts,NULL); goto retry; } - /* XXX check for ^C here */ done: if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap)) printf("get_online_cpumap failed\n"); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 623fb22922..5f7fa0221e 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2130,6 +2130,14 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) break; } + case TRAP_int3: + { + if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) ) + domain_pause_for_debugger(); + else + vmx_inject_exception(v, TRAP_int3, VMX_DELIVER_NO_ERROR_CODE); + break; + } #endif case TRAP_no_device: { diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 043754546a..22b24e392c 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -94,6 +94,7 @@ enum hval_bitmaps { #else #define MONITOR_DEFAULT_EXCEPTION_BITMAP \ ( EXCEPTION_BITMAP_PG | \ + EXCEPTION_BITMAP_BP | \ EXCEPTION_BITMAP_GP ) #endif From 6601a234d1928515b300f9be15f4c3f6c98043fa Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 10:24:17 +0100 Subject: [PATCH 037/151] See panic messages before the post message processing. Signed-off-by: Jimi Xenidis --- xen/drivers/char/console.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 16b07cb3da..dc06857007 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -684,6 +684,7 @@ void panic(const char *fmt, ...) va_end(args); /* Spit out multiline message in one go. */ + console_start_sync(); spin_lock_irqsave(&lock, flags); printk("\n****************************************\n"); printk("Panic on CPU %d:\n", smp_processor_id()); From 5a5d245c8c59a28503353f57d7b2201b507bf99e Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Fri, 31 Mar 2006 11:04:42 +0100 Subject: [PATCH 038/151] Disable xen bus and grant tables when supervisor_mode_kernel is enabled. Neither of these features are useful/available in this mode since only a single domain is supported. Do not attempt to initialise xen bus when supervisor_mode_kernel is enabled. Do not BUG_ON() failure to setup grant tables, future versions of supervisor_mode_kernel may return -ENOSYS here. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/drivers/xen/core/gnttab.c | 8 ++++++-- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c index 1049934008..fa12e701d4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c @@ -395,7 +395,10 @@ gnttab_resume(void) setup.frame_list = frames; rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); - BUG_ON(rc || setup.status); + if (rc < 0) + return rc; + + BUG_ON(setup.status); #ifndef __ia64__ if (shared == NULL) { @@ -436,7 +439,8 @@ gnttab_init(void) if (xen_init() < 0) return -ENODEV; - BUG_ON(gnttab_resume()); + if (gnttab_resume() < 0) + return -ENODEV; for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) gnttab_list[i] = i + 1; diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index d3f37e636d..935ec0a5eb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -997,6 +997,14 @@ static int __init xenbus_probe_init(void) device_register(&xenbus_frontend.dev); device_register(&xenbus_backend.dev); + /* + * The supervisor_mode_kernel feature only allows a single + * domain so there is no need to initialise event channels + * etc. + */ + if (xen_feature(XENFEAT_supervisor_mode_kernel)) + return -ENODEV; + /* * Domain0 doesn't have a store_evtchn or store_mfn yet. */ From 68b564efee06fa8a5118004d8d78b2c0a20b5096 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 12:03:42 +0100 Subject: [PATCH 039/151] Various softirq cleanups: 1. Make __softirq_pending a long, since PPC borrows the file hardirq.h from us and they only do atomic ops on longs. 2. do_softirq() explicitly takes a void param list. 3. Remove idle_timestamp field from irq_cpustat. It's unused and lets us simplify the idle loop a little bit. Part 1 based on a patch from Hollis Blanchard at IBM. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 11 ++++------- xen/common/softirq.c | 5 +++-- xen/include/asm-x86/hardirq.h | 3 +-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 8cb91ead4d..ab5b697953 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -79,15 +79,12 @@ void idle_loop(void) for ( ; ; ) { - irq_stat[cpu].idle_timestamp = jiffies; + page_scrub_schedule_work(); - while ( !softirq_pending(cpu) ) - { - page_scrub_schedule_work(); - default_idle(); - } + default_idle(); - do_softirq(); + if ( softirq_pending(cpu) ) + do_softirq(); } } diff --git a/xen/common/softirq.c b/xen/common/softirq.c index 5a7cd2dabc..f8a2c3780c 100644 --- a/xen/common/softirq.c +++ b/xen/common/softirq.c @@ -21,9 +21,10 @@ irq_cpustat_t irq_stat[NR_CPUS]; static softirq_handler softirq_handlers[NR_SOFTIRQS]; -asmlinkage void do_softirq() +asmlinkage void do_softirq(void) { - unsigned int i, pending, cpu = smp_processor_id(); + unsigned int i, cpu = smp_processor_id(); + unsigned long pending; pending = softirq_pending(cpu); ASSERT(pending != 0); diff --git a/xen/include/asm-x86/hardirq.h b/xen/include/asm-x86/hardirq.h index 59e90e2b47..c426fdea07 100644 --- a/xen/include/asm-x86/hardirq.h +++ b/xen/include/asm-x86/hardirq.h @@ -5,10 +5,9 @@ #include typedef struct { - unsigned int __softirq_pending; + unsigned long __softirq_pending; unsigned int __local_irq_count; unsigned int __nmi_count; - unsigned long idle_timestamp; } __cacheline_aligned irq_cpustat_t; #include /* Standard mappings for irq_cpustat_t above */ From f8253f9f488a40360cbd57d2d2efbf2ebc0671a3 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 13:51:19 +0100 Subject: [PATCH 040/151] Currently, xm & xend allow an XAUTHORITY to be specified in the config file. If that is not specified, then xm will pass the XAUTHORITY environment variable back to xend instead. This is not sufficient, since it is possible that XAUTHORITY is not set at all. This doesn't cause a problem for most X apps, because xlib will use the fall-back of $HOME/.Xauthority. But the viewer is started from xend, which almost certainly doesn't have a reasonable HOME variable. We fix this by always passing some value for XAUTHORITY. In order of preference, that value is: 1. Use the value from the config file, if specified. 2. Use the value from the XAUTHORITY env variable, if set. 3. Use $HOME/.Xauthority, if HOME is set. 4. Look up the user's home directory via getpwuid, and append "/.Xauthority" Signed-off-by: Charles Coffing --- tools/python/xen/xm/create.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index adfd6f1f42..2933af5e4f 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -864,7 +864,14 @@ def parseCommandLine(argv): gopts.vals.display = os.getenv("DISPLAY") if not gopts.vals.xauthority: - gopts.vals.xauthority = os.getenv("XAUTHORITY") + xauth = os.getenv("XAUTHORITY") + if not xauth: + home = os.getenv("HOME") + if not home: + import posix, pwd + home = pwd.getpwuid(posix.getuid())[5] + xauth = home + "/.Xauthority" + gopts.vals.xauthority = xauth # Process remaining args as config variables. for arg in args: From e5829dcbe18cb47ca3c55b589289bbb67dd41213 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 15:34:52 +0100 Subject: [PATCH 041/151] Plumb network vif credit-based rate limiting thorugh xenbus and xend into xm guest config files. A new vif parameter 'rate' is supported, with an optional time window paremeter for specifying granularity of credit replenishment. The default window is 50ms. For example: 'rate=10Mb/s' 'rate=250KB/s' 'rate=1MB/s@20ms' From: Chris Clark Signed-off-by: Keir Fraser --- .../drivers/xen/netback/common.h | 1 - .../drivers/xen/netback/interface.c | 19 ---- .../drivers/xen/netback/xenbus.c | 43 ++++++++- tools/python/xen/xend/server/netif.py | 90 ++++++++++++++++++- tools/python/xen/xm/create.py | 2 +- 5 files changed, 130 insertions(+), 25 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/common.h b/linux-2.6-xen-sparse/drivers/xen/netback/common.h index ab52a03f07..e328b63e54 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h @@ -97,7 +97,6 @@ typedef struct netif_st { #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) -void netif_creditlimit(netif_t *netif); void netif_disconnect(netif_t *netif); netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]); diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index 79944d6440..be96a6d3ac 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -293,25 +293,6 @@ void free_netif(netif_t *netif) schedule_work(&netif->free_work); } -void netif_creditlimit(netif_t *netif) -{ -#if 0 - /* Set the credit limit (reset remaining credit to new limit). */ - netif->credit_bytes = creditlimit->credit_bytes; - netif->remaining_credit = creditlimit->credit_bytes; - netif->credit_usec = creditlimit->period_usec; - - if (netif->status == CONNECTED) { - /* - * Schedule work so that any packets waiting under previous - * credit limit are dealt with (acts as a replenishment point). - */ - netif->credit_timeout.expires = jiffies; - netif_schedule_work(netif); - } -#endif -} - void netif_disconnect(netif_t *netif) { switch (netif->status) { diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index ea9a02e28e..d270f099c4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -233,9 +233,44 @@ static void frontend_changed(struct xenbus_device *dev, static void maybe_connect(struct backend_info *be) { - if (be->netif != NULL && be->frontend_state == XenbusStateConnected) { + if (be->netif && (be->frontend_state == XenbusStateConnected)) connect(be); - } +} + +static void xen_net_read_rate(struct xenbus_device *dev, + unsigned long *bytes, unsigned long *usec) +{ + char *s, *e; + unsigned long b, u; + char *ratestr; + + /* Default to unlimited bandwidth. */ + *bytes = ~0UL; + *usec = 0; + + ratestr = xenbus_read(XBT_NULL, dev->nodename, "rate", NULL); + if (IS_ERR(ratestr)) + return; + + s = ratestr; + b = simple_strtoul(s, &e, 10); + if ((s == e) || (*e != ',')) + goto fail; + + s = e + 1; + u = simple_strtoul(s, &e, 10); + if ((s == e) || (*e != '\0')) + goto fail; + + *bytes = b; + *usec = u; + + kfree(ratestr); + return; + + fail: + WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n"); + kfree(ratestr); } @@ -254,6 +289,10 @@ static void connect(struct backend_info *be) return; } + xen_net_read_rate(dev, &be->netif->credit_bytes, + &be->netif->credit_usec); + be->netif->remaining_credit = be->netif->credit_bytes; + xenbus_switch_state(dev, XenbusStateConnected); } diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 028bbf3989..94016e3628 100644 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -22,6 +22,7 @@ import os import random +import re from xen.xend import sxp from xen.xend import XendRoot @@ -50,6 +51,86 @@ def randomMAC(): random.randint(0x00, 0xff) ] return ':'.join(map(lambda x: "%02x" % x, mac)) +rate_re = re.compile("^([0-9]+)([GMK]?)([Bb])/s(@([0-9]+)([mu]?)s)?$") + +def parseRate(ratestr): + """if parsing fails this will return default of unlimited rate""" + bytes_per_interval = 0xffffffffL # 0xffffffff # big default + interval_usecs = 0L # disabled + + m = rate_re.match(ratestr) + if m: + bytes_per_sec = long(m.group(1)) + + if m.group(2) == 'G': + bytes_per_sec *= 1000 * 1000 * 1000 + elif m.group(2) == 'M': + bytes_per_sec *= 1000 * 1000 + elif m.group(2) == 'K': + bytes_per_sec *= 1000 + + if m.group(3) == 'b': + bytes_per_sec /= 8 + + if m.group(5) is None: + interval_usecs = 50000L # 50ms default + else: + interval_usecs = long(m.group(5)) + if m.group(6) == '': + interval_usecs *= 1000 * 1000 + elif m.group(6) == 'm': + interval_usecs *= 1000 + + bytes_per_interval = (bytes_per_sec * interval_usecs) / 1000000L + + # overflow / underflow checking: default to unlimited rate + if bytes_per_interval == 0 or bytes_per_interval > 0xffffffffL or \ + interval_usecs == 0 or interval_usecs > 0xffffffffL: + bytes_per_interval = 0xffffffffL + interval_usecs = 0L + + return "%lu,%lu" % (bytes_per_interval, interval_usecs) + + +write_rate_G_re = re.compile('^([0-9]+)000000000(B/s@[0-9]+us)$') +write_rate_M_re = re.compile('^([0-9]+)000000(B/s@[0-9]+us)$') +write_rate_K_re = re.compile('^([0-9]+)000(B/s@[0-9]+us)$') +write_rate_s_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000000us$') +write_rate_m_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000us$') + +def formatRate(rate): + (bytes_per_interval, interval_usecs) = map(long, rate.split(',')) + + if interval_usecs != 0: + bytes_per_second = (bytes_per_interval * 1000 * 1000) / interval_usecs + else: + bytes_per_second = 0xffffffffL + + ratestr = "%uB/s@%uus" % (bytes_per_second, interval_usecs) + + # look for '000's + m = write_rate_G_re.match(ratestr) + if m: + ratestr = m.group(1) + "G" + m.group(2) + else: + m = write_rate_M_re.match(ratestr) + if m: + ratestr = m.group(1) + "M" + m.group(2) + else: + m = write_rate_K_re.match(ratestr) + if m: + ratestr = m.group(1) + "K" + m.group(2) + + m = write_rate_s_re.match(ratestr) + if m: + ratestr = m.group(1) + "s" + else: + m = write_rate_m_re.match(ratestr) + if m: + ratestr = m.group(1) + "ms" + + return ratestr + class NetifController(DevController): """Network interface controller. Handles all network devices for a domain. @@ -75,6 +156,7 @@ class NetifController(DevController): bridge = sxp.child_value(config, 'bridge') mac = sxp.child_value(config, 'mac') vifname = sxp.child_value(config, 'vifname') + rate = sxp.child_value(config, 'rate') ipaddr = _get_config_ipaddr(config) devid = self.allocateDeviceID() @@ -98,6 +180,8 @@ class NetifController(DevController): back['bridge'] = bridge if vifname: back['vifname'] = vifname + if rate: + back['rate'] = parseRate(rate) return (devid, back, front) @@ -107,8 +191,8 @@ class NetifController(DevController): result = DevController.configuration(self, devid) - (script, ip, bridge, mac, typ, vifname) = self.readBackend( - devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname') + (script, ip, bridge, mac, typ, vifname, rate) = self.readBackend( + devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname', 'rate') if script: result.append(['script', @@ -125,5 +209,7 @@ class NetifController(DevController): result.append(['type', typ]) if vifname: result.append(['vifname', vifname]) + if rate: + result.append(['rate', formatRate(rate)]) return result diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 2933af5e4f..6da9ed3711 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -552,7 +552,7 @@ def configure_vifs(config_devs, vals): def f(k): if k not in ['backend', 'bridge', 'ip', 'mac', 'script', 'type', - 'vifname']: + 'vifname', 'rate']: err('Invalid vif option: ' + k) config_vif.append([k, d[k]]) From 05c8070bb4eac07ff52203ef090b8881bd56560b Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Fri, 31 Mar 2006 17:44:26 +0100 Subject: [PATCH 042/151] Fix do_IRQ high bit masking. Instead of setting the highest bit (which isn't easily done on native x86_64), negate the interrupt vector stored in orig_{e,r}ax. Also add patch for native build. Signed-off-by: Christian Limpach --- .../arch/i386/kernel/entry-xen.S | 4 +- .../arch/i386/kernel/irq-xen.c | 2 +- .../arch/x86_64/kernel/entry-xen.S | 2 +- .../arch/x86_64/kernel/irq-xen.c | 2 +- .../drivers/xen/core/evtchn.c | 6 +- .../x86-increase-interrupt-vector-range.patch | 107 ++++++++++++++++++ 6 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 patches/linux-2.6.16/x86-increase-interrupt-vector-range.patch diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S index c1784979e3..072172cda7 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S @@ -461,7 +461,7 @@ vector=0 ENTRY(irq_entries_start) .rept NR_IRQS ALIGN -1: pushl 0x80000000+$vector +1: pushl $~(vector) jmp common_interrupt .data .long 1b @@ -478,7 +478,7 @@ common_interrupt: #define BUILD_INTERRUPT(name, nr) \ ENTRY(name) \ - pushl 0x80000000+$nr; \ + pushl $~(nr); \ SAVE_ALL \ movl %esp,%eax; \ call smp_/**/name; \ diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c index b1d8634bd6..b4a38e4d92 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c @@ -54,7 +54,7 @@ static union irq_ctx *softirq_ctx[NR_CPUS]; fastcall unsigned int do_IRQ(struct pt_regs *regs) { /* high bit used in ret_from_ code */ - int irq = regs->orig_eax & __IRQ_MASK(BITS_PER_LONG - 1); + int irq = ~regs->orig_eax; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; u32 *isp; diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S index 604365dec3..2930d58da2 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S @@ -584,7 +584,7 @@ retint_kernel: */ .macro apicinterrupt num,func INTR_FRAME - pushq 0x8000000000000000+$\num + pushq $~(\num) CFI_ADJUST_CFA_OFFSET 8 interrupt \func jmp error_entry diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c index 663e890c94..268f8cd6dc 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c @@ -97,7 +97,7 @@ skip: asmlinkage unsigned int do_IRQ(struct pt_regs *regs) { /* high bit used in ret_from_ code */ - int irq = regs->orig_rax & __IRQ_MASK(BITS_PER_LONG - 1); + unsigned irq = ~regs->orig_rax; exit_idle(); irq_enter(); diff --git a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c index 6dee25cab7..820ce89069 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c @@ -170,9 +170,9 @@ static inline void exit_idle(void) {} #include #define IRQ_REG orig_rax #endif -#define do_IRQ(irq, regs) do { \ - (regs)->IRQ_REG = (irq) | (1UL << (BITS_PER_LONG - 1)); \ - do_IRQ((regs)); \ +#define do_IRQ(irq, regs) do { \ + (regs)->IRQ_REG = ~(irq); \ + do_IRQ((regs)); \ } while (0) #endif diff --git a/patches/linux-2.6.16/x86-increase-interrupt-vector-range.patch b/patches/linux-2.6.16/x86-increase-interrupt-vector-range.patch new file mode 100644 index 0000000000..c79abfc274 --- /dev/null +++ b/patches/linux-2.6.16/x86-increase-interrupt-vector-range.patch @@ -0,0 +1,107 @@ +Subject: Increase x86 interrupt vector range + +Remove the limit of 256 interrupt vectors by changing the value +stored in orig_{e,r}ax to be the negated interrupt vector. +The orig_{e,r}ax needs to be < 0 to allow the signal code to +distinguish between return from interrupt and return from syscall. +With this change applied, NR_IRQS can be > 256. + +Signed-off-by: Christian Limpach +--- + arch/i386/kernel/entry.S | 4 ++-- + arch/i386/kernel/irq.c | 4 ++-- + arch/x86_64/kernel/entry.S | 2 +- + arch/x86_64/kernel/irq.c | 4 ++-- + arch/x86_64/kernel/smp.c | 4 ++-- + include/asm-x86_64/hw_irq.h | 2 +- + 6 files changed, 10 insertions(+), 10 deletions(-) + +diff -r 7d239c83edea arch/i386/kernel/entry.S +--- a/arch/i386/kernel/entry.S Mon Mar 20 06:00:20 2006 +0000 ++++ b/arch/i386/kernel/entry.S Fri Mar 31 17:01:35 2006 +0100 +@@ -406,7 +406,7 @@ ENTRY(irq_entries_start) + ENTRY(irq_entries_start) + .rept NR_IRQS + ALIGN +-1: pushl $vector-256 ++1: pushl $~(vector) + jmp common_interrupt + .data + .long 1b +@@ -423,7 +423,7 @@ common_interrupt: + + #define BUILD_INTERRUPT(name, nr) \ + ENTRY(name) \ +- pushl $nr-256; \ ++ pushl $~(nr); \ + SAVE_ALL \ + movl %esp,%eax; \ + call smp_/**/name; \ +diff -r 7d239c83edea arch/i386/kernel/irq.c +--- a/arch/i386/kernel/irq.c Mon Mar 20 06:00:20 2006 +0000 ++++ b/arch/i386/kernel/irq.c Fri Mar 31 17:01:35 2006 +0100 +@@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPU + */ + fastcall unsigned int do_IRQ(struct pt_regs *regs) + { +- /* high bits used in ret_from_ code */ +- int irq = regs->orig_eax & 0xff; ++ /* high bit used in ret_from_ code */ ++ int irq = ~regs->orig_eax; + #ifdef CONFIG_4KSTACKS + union irq_ctx *curctx, *irqctx; + u32 *isp; +diff -r 7d239c83edea arch/x86_64/kernel/entry.S +--- a/arch/x86_64/kernel/entry.S Mon Mar 20 06:00:20 2006 +0000 ++++ b/arch/x86_64/kernel/entry.S Fri Mar 31 17:01:35 2006 +0100 +@@ -609,7 +609,7 @@ retint_kernel: + */ + .macro apicinterrupt num,func + INTR_FRAME +- pushq $\num-256 ++ pushq $~(\num) + CFI_ADJUST_CFA_OFFSET 8 + interrupt \func + jmp ret_from_intr +diff -r 7d239c83edea arch/x86_64/kernel/irq.c +--- a/arch/x86_64/kernel/irq.c Mon Mar 20 06:00:20 2006 +0000 ++++ b/arch/x86_64/kernel/irq.c Fri Mar 31 17:01:35 2006 +0100 +@@ -96,8 +96,8 @@ skip: + */ + asmlinkage unsigned int do_IRQ(struct pt_regs *regs) + { +- /* high bits used in ret_from_ code */ +- unsigned irq = regs->orig_rax & 0xff; ++ /* high bit used in ret_from_ code */ ++ unsigned irq = ~regs->orig_rax; + + exit_idle(); + irq_enter(); +diff -r 7d239c83edea arch/x86_64/kernel/smp.c +--- a/arch/x86_64/kernel/smp.c Mon Mar 20 06:00:20 2006 +0000 ++++ b/arch/x86_64/kernel/smp.c Fri Mar 31 17:01:35 2006 +0100 +@@ -135,10 +135,10 @@ asmlinkage void smp_invalidate_interrupt + + cpu = smp_processor_id(); + /* +- * orig_rax contains the interrupt vector - 256. ++ * orig_rax contains the negated interrupt vector. + * Use that to determine where the sender put the data. + */ +- sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START; ++ sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START; + f = &per_cpu(flush_state, sender); + + if (!cpu_isset(cpu, f->flush_cpumask)) +diff -r 7d239c83edea include/asm-x86_64/hw_irq.h +--- a/include/asm-x86_64/hw_irq.h Mon Mar 20 06:00:20 2006 +0000 ++++ b/include/asm-x86_64/hw_irq.h Fri Mar 31 17:01:35 2006 +0100 +@@ -127,7 +127,7 @@ __asm__( \ + __asm__( \ + "\n.p2align\n" \ + "IRQ" #nr "_interrupt:\n\t" \ +- "push $" #nr "-256 ; " \ ++ "push $~(" #nr ") ; " \ + "jmp common_interrupt"); + + #if defined(CONFIG_X86_IO_APIC) From 5a3908ddfd454561546ddf9be0bf9f03ed276578 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:20:10 +0100 Subject: [PATCH 043/151] Add new boot parameter 'lowmem_emergency_pool' which creates an emergency pool of pages below 4GB (i.e., in Xen's DMA pool) which will ever be used to satisfy normal allocation requests. This is particularly useful in an i386 PAE environment to ensure that pages will always be available for allocation as page-table base directories. Usage, for example (to reserve 16MB): lowmem_emergency_pool=16M In a PAE environment, each reserved megabyte guarantees you should be able to create up to 256 processes (counted across all guests). 16MB means you're good for 4096 processes. Signed-off-by: Keir Fraser --- xen/common/page_alloc.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 4dff2f3679..763dafd75c 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -42,6 +42,20 @@ static char opt_badpage[100] = ""; string_param("badpage", opt_badpage); +/* + * Amount of memory to reserve in a low-memory (<4GB) pool for specific + * allocation requests. Ordinary requests will not fall back to the + * lowmem emergency pool. + */ +static unsigned long lowmem_emergency_pool_pages; +static void parse_lowmem_emergency_pool(char *s) +{ + unsigned long long bytes; + bytes = parse_size_and_unit(s); + lowmem_emergency_pool_pages = bytes >> PAGE_SHIFT; +} +custom_param("lowmem_emergency_pool", parse_lowmem_emergency_pool); + #define round_pgdown(_p) ((_p)&PAGE_MASK) #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) @@ -514,7 +528,15 @@ struct page_info *alloc_domheap_pages( ASSERT(!in_irq()); if ( !(flags & ALLOC_DOM_DMA) ) + { pg = alloc_heap_pages(MEMZONE_DOM, order); + /* Failure? Then check if we can fall back to the DMA pool. */ + if ( unlikely(pg == NULL) && + ((order > MAX_ORDER) || + (avail[MEMZONE_DMADOM] < + (lowmem_emergency_pool_pages + (1UL << order)))) ) + return NULL; + } if ( pg == NULL ) if ( (pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL ) @@ -657,7 +679,17 @@ void free_domheap_pages(struct page_info *pg, unsigned int order) unsigned long avail_domheap_pages(void) { - return avail[MEMZONE_DOM] + avail[MEMZONE_DMADOM]; + unsigned long avail_nrm, avail_dma; + + avail_nrm = avail[MEMZONE_DOM]; + + avail_dma = avail[MEMZONE_DMADOM]; + if ( avail_dma > lowmem_emergency_pool_pages ) + avail_dma -= lowmem_emergency_pool_pages; + else + avail_dma = 0; + + return avail_nrm + avail_dma; } From 17e838d026118840e044a1fd2799671fe02915e5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:37:36 +0100 Subject: [PATCH 044/151] [IA64] Include features header in xenbus_probe and build features.c Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile | 2 +- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile index 7a35e75b42..a2d0f650bd 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile +++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/coreMakefile @@ -10,7 +10,7 @@ $(obj)/vmlinux.lds.S: @ln -fsn $(srctree)/arch/$(XENARCH)/kernel/vmlinux.lds.S $@ -obj-y := gnttab.o +obj-y := gnttab.o features.o obj-$(CONFIG_PROC_FS) += xen_proc.o ifeq ($(ARCH),ia64) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 935ec0a5eb..db1492d050 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "xenbus_comms.h" From 76d1c06d0996af696fddddaeb04025426e0db5fe Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:39:31 +0100 Subject: [PATCH 045/151] Minor minios traps.c fix for x86/64. Signed-off-by: Aravindh Puthiyaparambil --- extras/mini-os/traps.c | 53 ++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/extras/mini-os/traps.c b/extras/mini-os/traps.c index 43d2dca40e..e11192040b 100644 --- a/extras/mini-os/traps.c +++ b/extras/mini-os/traps.c @@ -4,6 +4,7 @@ #include #include #include +#include /* * These are assembler stubs in entry.S. @@ -31,6 +32,8 @@ void machine_check(void); void dump_regs(struct pt_regs *regs) { + printk("Thread: %s\n", current->name); +#ifdef __i386__ printk("EIP: %x, EFLAGS %x.\n", regs->eip, regs->eflags); printk("EBX: %08x ECX: %08x EDX: %08x\n", regs->ebx, regs->ecx, regs->edx); @@ -40,9 +43,22 @@ void dump_regs(struct pt_regs *regs) regs->xds, regs->xes, regs->orig_eax, regs->eip); printk("CS: %04x EFLAGS: %08x esp: %08x ss: %04x\n", regs->xcs, regs->eflags, regs->esp, regs->xss); - -} - +#else + printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip); + printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", + regs->ss, regs->rsp, regs->eflags); + printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", + regs->rax, regs->rbx, regs->rcx); + printk("RDX: %016lx RSI: %016lx RDI: %016lx\n", + regs->rdx, regs->rsi, regs->rdi); + printk("RBP: %016lx R08: %016lx R09: %016lx\n", + regs->rbp, regs->r8, regs->r9); + printk("R10: %016lx R11: %016lx R12: %016lx\n", + regs->r10, regs->r11, regs->r12); + printk("R13: %016lx R14: %016lx R15: %016lx\n", + regs->r13, regs->r14, regs->r15); +#endif +} static void do_trap(int trapnr, char *str, struct pt_regs * regs, unsigned long error_code) { @@ -110,36 +126,17 @@ void do_page_fault(struct pt_regs *regs, unsigned long error_code) printk("Page fault at linear address %p, regs %p, code %lx\n", addr, regs, error_code); dump_regs(regs); -#ifdef __x86_64__ - /* FIXME: _PAGE_PSE */ - { - unsigned long *tab = (unsigned long *)start_info.pt_base; - unsigned long page; - - printk("Pagetable walk from %p:\n", tab); - - page = tab[l4_table_offset(addr)]; - tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); - printk(" L4 = %p (%p)\n", page, tab); - - page = tab[l3_table_offset(addr)]; - tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); - printk(" L3 = %p (%p)\n", page, tab); - - page = tab[l2_table_offset(addr)]; - tab = to_virt(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT); - printk(" L2 = %p (%p)\n", page, tab); - - page = tab[l1_table_offset(addr)]; - printk(" L1 = %p\n", page); - } -#endif + page_walk(addr); do_exit(); } void do_general_protection(struct pt_regs *regs, long error_code) { - printk("GPF %p, error_code=%lx\n", regs, error_code); +#ifdef __i386__ + printk("GPF eip: %p, error_code=%lx\n", regs->eip, error_code); +#else + printk("GPF rip: %p, error_code=%lx\n", regs->rip, error_code); +#endif dump_regs(regs); do_exit(); } From 75a5d014e3899c4b0457f72e2e22a0c58bcaa087 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:40:54 +0100 Subject: [PATCH 046/151] [SVM] Do not update seg.base in realmode while obtaining the io addr for ins/outs. Signed-off-by: Tom Woller --- xen/arch/x86/hvm/svm/svm.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 77ba3f8089..bc2e743df4 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1163,16 +1163,12 @@ static unsigned int check_for_null_selector(struct vmcb_struct *vmcb, seg = vmcb->ds; break; default: - if (dir == IOREQ_READ) + if (dir == IOREQ_READ) /* IN/INS instruction? */ seg = vmcb->es; else seg = vmcb->ds; } - /* In real Mode */ - if (real) - seg.base = seg.sel << 4; - if (base) *base = seg.base; From 85c024b331ec621ac4761812392bb08614a2e163 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:49:42 +0100 Subject: [PATCH 047/151] Fix makefiles for hvmloader and vmxassist for FC5 on x86_64 systems. In FC5, gcc has issues with the command lines used to build hvmloader and vmxassist. Basically, the compiler doesn't like the combination of -m64 and -m32. As these are 32 bit apps, and intended to be, take a modified approach and simply define XEN_TARGET_ARCH for 32 bits. This cleans up the command line and builds the images correctly. From: Ben Thomas Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/Makefile | 4 ++-- tools/firmware/vmxassist/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile index ff95836e90..5a821f7dcb 100644 --- a/tools/firmware/hvmloader/Makefile +++ b/tools/firmware/hvmloader/Makefile @@ -21,6 +21,7 @@ # External CFLAGS can do more harm than good. CFLAGS := +XEN_TARGET_ARCH = x86_32 XEN_ROOT = ../../.. include $(XEN_ROOT)/Config.mk @@ -38,8 +39,7 @@ CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector) CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector-all) OBJCOPY = objcopy -CFLAGS += $(DEFINES) -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float -CFLAGS += -m32 -march=i686 +CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR) all: hvmloader diff --git a/tools/firmware/vmxassist/Makefile b/tools/firmware/vmxassist/Makefile index aabd32cc1a..85c9fff581 100644 --- a/tools/firmware/vmxassist/Makefile +++ b/tools/firmware/vmxassist/Makefile @@ -21,6 +21,7 @@ # External CFLAGS can do more harm than good. CFLAGS := +XEN_TARGET_ARCH = x86_32 XEN_ROOT = ../../.. include $(XEN_ROOT)/Config.mk @@ -37,8 +38,7 @@ CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector-all) CPP = cpp -P OBJCOPY = objcopy -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0 -CFLAGS += $(DEFINES) -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float -CFLAGS += -m32 -march=i686 +CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float LDFLAGS = -m elf_i386 OBJECTS = head.o trap.o vm86.o setup.o util.o From 840ac8df5ad05ef8472daa6692676d363edbc2a2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:50:58 +0100 Subject: [PATCH 048/151] Changed deprecated "set-vcpus" to "vcpu-set" in the xm man page. Signed-off-by: Charles Coffing --- docs/man/xm.pod.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1 index 18b055d5be..d6e3697abe 100644 --- a/docs/man/xm.pod.1 +++ b/docs/man/xm.pod.1 @@ -360,7 +360,7 @@ your Linux Kernel sources. Moves a domain out of the paused state. This will allow a previously paused domain to now be eligible for scheduling by the Xen hypervisor. -=item B I I +=item B I I Enables the I virtual CPUs for the domain in question. Like mem-set, this command can only allocate up to the maximum virtual @@ -370,8 +370,8 @@ If the I is smaller than the current number of active VCPUs, the highest number VCPUs will be hotplug removed. This may be important for pinning purposes. -Attempting to set-vcpus to a number larger than the initially -configured VCPU count is an error. Trying to set-vcpus to < 1 will be +Attempting to set the VCPUs to a number larger than the initially +configured VCPU count is an error. Trying to set VCPUs to < 1 will be quietly ignored. =item B I<[domain-id]> From d057bf8506f83d7648754b4fc6844a78710f2b98 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 10:52:47 +0100 Subject: [PATCH 049/151] When dom0 fails to balloon enough memory to allow a new domain to start, an exception is thrown. The test that decides which exception to throw is backwards, resulting in strange error messages. The attached patch fixes the problem. Signed-off-by: Charles Coffing --- tools/python/xen/xend/balloon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/balloon.py b/tools/python/xen/xend/balloon.py index 56c0e75e56..63f1f7eb42 100644 --- a/tools/python/xen/xend/balloon.py +++ b/tools/python/xen/xend/balloon.py @@ -152,7 +152,7 @@ def free(required): 'I cannot release any more. I need %d MiB but ' 'only have %d.') % (need_mem, free_mem)) - elif new_alloc >= dom0_min_mem: + elif new_alloc < dom0_min_mem: raise VmError( ('I need %d MiB, but dom0_min_mem is %d and shrinking to ' '%d MiB would leave only %d MiB free.') % From 97c44fa2f3486940b29b07f854855b18906fe69c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 11:08:50 +0100 Subject: [PATCH 050/151] Rename sched_op->sched_op_compat and sched_op_new->sched_op after Christian's interface cleanup. Signed-off-by: Keir Fraser --- xen/arch/ia64/vmx/vmx_hypercall.c | 6 +++--- xen/arch/ia64/vmx/vmx_ivt.S | 2 +- xen/arch/ia64/vmx/vmx_support.c | 2 +- xen/arch/ia64/xen/hypercall.c | 4 ++-- xen/arch/x86/hvm/io.c | 4 ++-- xen/arch/x86/x86_32/entry.S | 22 +++++++++++----------- xen/arch/x86/x86_64/entry.S | 22 +++++++++++----------- xen/common/schedule.c | 4 ++-- xen/include/public/sched.h | 6 +++--- xen/include/xen/hypercall.h | 7 ++++++- 10 files changed, 42 insertions(+), 37 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index 4d35fea5d0..d07b7334e6 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -35,7 +35,7 @@ #include #include -extern long do_sched_op(int cmd, unsigned long arg); +extern long do_sched_op_compat(int cmd, unsigned long arg); extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr); void hyper_not_support(void) @@ -83,13 +83,13 @@ void hyper_dom_mem_op(void) } -void hyper_sched_op(void) +void hyper_sched_op_compat(void) { VCPU *vcpu=current; u64 r32,r33,ret; vcpu_get_gr_nat(vcpu,16,&r32); vcpu_get_gr_nat(vcpu,17,&r33); - ret=do_sched_op(r32,r33); + ret=do_sched_op_compat(r32,r33); vcpu_set_gr(vcpu, 8, ret, 0); vmx_vcpu_increment_iip(vcpu); diff --git a/xen/arch/ia64/vmx/vmx_ivt.S b/xen/arch/ia64/vmx/vmx_ivt.S index 71c22496cf..6bad61d067 100644 --- a/xen/arch/ia64/vmx/vmx_ivt.S +++ b/xen/arch/ia64/vmx/vmx_ivt.S @@ -1125,7 +1125,7 @@ hyper_call_table: data8 hyper_not_support //hyper_stack_switch data8 hyper_not_support //hyper_set_callbacks data8 hyper_not_support //hyper_fpu_taskswitch /* 5 */ - data8 hyper_sched_op + data8 hyper_sched_op_compat data8 hyper_dom0_op data8 hyper_not_support //hyper_set_debugreg data8 hyper_not_support //hyper_get_debugreg diff --git a/xen/arch/ia64/vmx/vmx_support.c b/xen/arch/ia64/vmx/vmx_support.c index 7e353be6c6..e5829817e3 100644 --- a/xen/arch/ia64/vmx/vmx_support.c +++ b/xen/arch/ia64/vmx/vmx_support.c @@ -43,7 +43,7 @@ void vmx_wait_io(void) do { if (!test_bit(port, &d->shared_info->evtchn_pending[0])) - do_sched_op(SCHEDOP_block, 0); + do_sched_op_compat(SCHEDOP_block, 0); /* Unblocked when some event is coming. Clear pending indication * immediately if deciding to go for io assist diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index f4d9d4e17e..971007cbf7 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -38,7 +38,7 @@ hypercall_t ia64_hypercall_table[] = (hypercall_t)do_ni_hypercall, /* do_stack_switch */ (hypercall_t)do_ni_hypercall, /* do_set_callbacks */ (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch */ /* 5 */ - (hypercall_t)do_ni_hypercall, /* do_sched_op */ + (hypercall_t)do_ni_hypercall, /* do_sched_op_compat */ (hypercall_t)do_dom0_op, (hypercall_t)do_ni_hypercall, /* do_set_debugreg */ (hypercall_t)do_ni_hypercall, /* do_get_debugreg */ @@ -160,7 +160,7 @@ fw_hypercall (struct pt_regs *regs) } else { pal_halt_light_count++; - do_sched_op(SCHEDOP_yield, 0); + do_sched_op_compat(SCHEDOP_yield, 0); } regs->r8 = 0; regs->r9 = 0; diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 26339a0a74..893dd68ce5 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -713,7 +713,7 @@ void hvm_wait_io(void) if ( !test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) break; - do_sched_op(SCHEDOP_block, 0); + do_sched_op_compat(SCHEDOP_block, 0); } /* @@ -743,7 +743,7 @@ void hvm_safe_block(void) if ( test_bit(port, &d->shared_info->evtchn_pending[0]) ) break; - do_sched_op(SCHEDOP_block, 0); + do_sched_op_compat(SCHEDOP_block, 0); } /* Reflect pending event in selector and master flags. */ diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 86c609ce07..ff2a7991f3 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -579,6 +579,13 @@ ENTRY(setup_vm86_frame) addl $16,%esp ret +do_arch_sched_op_compat: + # Ensure we return success even if we return via schedule_tail() + xorl %eax,%eax + GET_GUEST_REGS(%ecx) + movl %eax,UREGS_eax(%ecx) + jmp do_sched_op_compat + do_arch_sched_op: # Ensure we return success even if we return via schedule_tail() xorl %eax,%eax @@ -586,13 +593,6 @@ do_arch_sched_op: movl %eax,UREGS_eax(%ecx) jmp do_sched_op -do_arch_sched_op_new: - # Ensure we return success even if we return via schedule_tail() - xorl %eax,%eax - GET_GUEST_REGS(%ecx) - movl %eax,UREGS_eax(%ecx) - jmp do_sched_op_new - .data ENTRY(exception_table) @@ -624,7 +624,7 @@ ENTRY(hypercall_table) .long do_stack_switch .long do_set_callbacks .long do_fpu_taskswitch /* 5 */ - .long do_arch_sched_op + .long do_arch_sched_op_compat .long do_dom0_op .long do_set_debugreg .long do_get_debugreg @@ -647,7 +647,7 @@ ENTRY(hypercall_table) .long do_mmuext_op .long do_acm_op .long do_nmi_op - .long do_arch_sched_op_new + .long do_arch_sched_op .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -659,7 +659,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_stack_switch */ .byte 4 /* do_set_callbacks */ .byte 1 /* do_fpu_taskswitch */ /* 5 */ - .byte 2 /* do_arch_sched_op */ + .byte 2 /* do_arch_sched_op_compat */ .byte 1 /* do_dom0_op */ .byte 2 /* do_set_debugreg */ .byte 1 /* do_get_debugreg */ @@ -682,7 +682,7 @@ ENTRY(hypercall_args_table) .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ .byte 2 /* do_nmi_op */ - .byte 2 /* do_arch_sched_op_new */ + .byte 2 /* do_arch_sched_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index c5249e1d79..6176188a85 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -488,6 +488,13 @@ nmi_in_hypervisor_mode: call do_nmi jmp ret_from_intr +do_arch_sched_op_compat: + # Ensure we return success even if we return via schedule_tail() + xorl %eax,%eax + GET_GUEST_REGS(%r10) + movq %rax,UREGS_rax(%r10) + jmp do_sched_op_compat + do_arch_sched_op: # Ensure we return success even if we return via schedule_tail() xorl %eax,%eax @@ -495,13 +502,6 @@ do_arch_sched_op: movq %rax,UREGS_rax(%r10) jmp do_sched_op -do_arch_sched_op_new: - # Ensure we return success even if we return via schedule_tail() - xorl %eax,%eax - GET_GUEST_REGS(%r10) - movq %rax,UREGS_rax(%r10) - jmp do_sched_op_new - .data ENTRY(exception_table) @@ -533,7 +533,7 @@ ENTRY(hypercall_table) .quad do_stack_switch .quad do_set_callbacks .quad do_fpu_taskswitch /* 5 */ - .quad do_arch_sched_op + .quad do_arch_sched_op_compat .quad do_dom0_op .quad do_set_debugreg .quad do_get_debugreg @@ -556,7 +556,7 @@ ENTRY(hypercall_table) .quad do_mmuext_op .quad do_acm_op .quad do_nmi_op - .quad do_arch_sched_op_new + .quad do_arch_sched_op .rept NR_hypercalls-((.-hypercall_table)/8) .quad do_ni_hypercall .endr @@ -568,7 +568,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_stack_switch */ .byte 3 /* do_set_callbacks */ .byte 1 /* do_fpu_taskswitch */ /* 5 */ - .byte 2 /* do_arch_sched_op */ + .byte 2 /* do_arch_sched_op_compat */ .byte 1 /* do_dom0_op */ .byte 2 /* do_set_debugreg */ .byte 1 /* do_get_debugreg */ @@ -591,7 +591,7 @@ ENTRY(hypercall_args_table) .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ .byte 2 /* do_nmi_op */ - .byte 2 /* do_arch_sched_op_new */ + .byte 2 /* do_arch_sched_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 9eaa29847f..4ab5d7d879 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -332,7 +332,7 @@ static long do_yield(void) return 0; } -long do_sched_op(int cmd, unsigned long arg) +long do_sched_op_compat(int cmd, unsigned long arg) { long ret = 0; @@ -365,7 +365,7 @@ long do_sched_op(int cmd, unsigned long arg) return ret; } -long do_sched_op_new(int cmd, GUEST_HANDLE(void) arg) +long do_sched_op(int cmd, GUEST_HANDLE(void) arg) { long ret = 0; diff --git a/xen/include/public/sched.h b/xen/include/public/sched.h index bebdb1c594..28e86c0d76 100644 --- a/xen/include/public/sched.h +++ b/xen/include/public/sched.h @@ -13,17 +13,17 @@ /* * The prototype for this hypercall is: - * long sched_op_new(int cmd, void *arg) + * long sched_op(int cmd, void *arg) * @cmd == SCHEDOP_??? (scheduler operation). * @arg == Operation-specific extra argument(s), as described below. * - * **NOTE**: - * Versions of Xen prior to 3.0.2 provide only the following legacy version + * Versions of Xen prior to 3.0.2 provided only the following legacy version * of this hypercall, supporting only the commands yield, block and shutdown: * long sched_op(int cmd, unsigned long arg) * @cmd == SCHEDOP_??? (scheduler operation). * @arg == 0 (SCHEDOP_yield and SCHEDOP_block) * == SHUTDOWN_* code (SCHEDOP_shutdown) + * This legacy version is available to new guests as sched_op_compat(). */ /* diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h index 23f9b48e92..cb8b9610ff 100644 --- a/xen/include/xen/hypercall.h +++ b/xen/include/xen/hypercall.h @@ -18,10 +18,15 @@ do_ni_hypercall( void); extern long -do_sched_op( +do_sched_op_compat( int cmd, unsigned long arg); +extern long +do_sched_op( + int cmd, + GUEST_HANDLE(void) arg); + extern long do_dom0_op( GUEST_HANDLE(dom0_op_t) u_dom0_op); From 9cf21925de2dee4365e83fd0c18b13aef621ae41 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 1 Apr 2006 14:59:12 +0100 Subject: [PATCH 051/151] This patch fixes several issues related to vmxassist: 1) AP bring up; 2) RHEL4 IA32e installation; 3) SLES10 IA32e installation; Signed-off-by: Xin Li --- tools/firmware/vmxassist/Makefile | 12 ++-- tools/firmware/vmxassist/trap.S | 1 + tools/firmware/vmxassist/util.c | 1 - tools/firmware/vmxassist/vm86.c | 94 ++++++++++++++++++------------- tools/firmware/vmxassist/vm86.h | 1 - 5 files changed, 63 insertions(+), 46 deletions(-) diff --git a/tools/firmware/vmxassist/Makefile b/tools/firmware/vmxassist/Makefile index 85c9fff581..17b13b2be2 100644 --- a/tools/firmware/vmxassist/Makefile +++ b/tools/firmware/vmxassist/Makefile @@ -53,25 +53,25 @@ vmxassist.bin: vmxassist.ld $(OBJECTS) dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync rm -f vmxassist.tmp -head.o: machine.h head.S +head.o: machine.h vm86.h head.S $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c head.S -trap.o: machine.h offsets.h trap.S +trap.o: machine.h vm86.h offsets.h trap.S $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c trap.S -vm86.o: machine.h vm86.c +vm86.o: machine.h vm86.h vm86.c $(CC) $(CFLAGS) -c vm86.c -setup.o: machine.h setup.c +setup.o: machine.h vm86.h setup.c $(CC) $(CFLAGS) -c setup.c -util.o: machine.h util.c +util.o: machine.h vm86.h util.c $(CC) $(CFLAGS) -c util.c offsets.h: gen ./gen > offsets.h -gen: gen.c +gen: vm86.h gen.c $(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c clean: diff --git a/tools/firmware/vmxassist/trap.S b/tools/firmware/vmxassist/trap.S index e4294e88c2..468da0a5db 100644 --- a/tools/firmware/vmxassist/trap.S +++ b/tools/firmware/vmxassist/trap.S @@ -18,6 +18,7 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ #include "machine.h" +#include "vm86.h" #include "offsets.h" /* diff --git a/tools/firmware/vmxassist/util.c b/tools/firmware/vmxassist/util.c index 9e9f86cb12..0181fe702c 100644 --- a/tools/firmware/vmxassist/util.c +++ b/tools/firmware/vmxassist/util.c @@ -18,7 +18,6 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ #include -#include #include "util.h" #include "machine.h" diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c index f9e8ae3753..e18efc1c64 100644 --- a/tools/firmware/vmxassist/vm86.c +++ b/tools/firmware/vmxassist/vm86.c @@ -34,7 +34,7 @@ #define SEG_FS 0x0040 #define SEG_GS 0x0080 -unsigned prev_eip = 0; +static unsigned prev_eip = 0; enum vm86_mode mode = 0; #ifdef DEBUG @@ -50,23 +50,41 @@ char *states[] = { static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; #endif /* DEBUG */ -unsigned +static unsigned address(struct regs *regs, unsigned seg, unsigned off) { unsigned long long entry; - unsigned addr; + unsigned seg_base, seg_limit; + unsigned entry_low, entry_high; - if (seg == 0) - return off; + if (seg == 0) { + if (mode == VM86_REAL || mode == VM86_REAL_TO_PROTECTED) + return off; + else + panic("segment is zero, but not in real mode!\n"); + } - if (seg > oldctx.gdtr_limit) + if (mode == VM86_REAL || seg > oldctx.gdtr_limit || + (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg)) return ((seg & 0xFFFF) << 4) + off; entry = ((unsigned long long *) oldctx.gdtr_base)[seg >> 3]; - addr = (((entry >> (56-24)) & 0xFF000000) | - ((entry >> (32-16)) & 0x00FF0000) | - ((entry >> ( 16)) & 0x0000FFFF)) + off; - return addr; + entry_high = entry >> 32; + entry_low = entry & 0xFFFFFFFF; + + seg_base = (entry_high & 0xFF000000) | ((entry >> 16) & 0xFFFFFF); + seg_limit = (entry_high & 0xF0000) | (entry_low & 0xFFFF); + + if (entry_high & 0x8000 && + ((entry_high & 0x800000 && off >> 12 <= seg_limit) || + (!(entry_high & 0x800000) && off <= seg_limit))) + return seg_base + off; + + panic("should never reach here in function address():\n\t" + "entry=0x%08x%08x, mode=%d, seg=0x%08x, offset=0x%08x\n", + entry_high, entry_low, mode, seg, off); + + return 0; } #ifdef DEBUG @@ -194,7 +212,7 @@ fetch8(struct regs *regs) return read8(addr); } -unsigned +static unsigned getreg32(struct regs *regs, int r) { switch (r & 7) { @@ -210,13 +228,13 @@ getreg32(struct regs *regs, int r) return ~0; } -unsigned +static unsigned getreg16(struct regs *regs, int r) { return MASK16(getreg32(regs, r)); } -unsigned +static unsigned getreg8(struct regs *regs, int r) { switch (r & 7) { @@ -232,7 +250,7 @@ getreg8(struct regs *regs, int r) return ~0; } -void +static void setreg32(struct regs *regs, int r, unsigned v) { switch (r & 7) { @@ -247,13 +265,13 @@ setreg32(struct regs *regs, int r, unsigned v) } } -void +static void setreg16(struct regs *regs, int r, unsigned v) { setreg32(regs, r, (getreg32(regs, r) & ~0xFFFF) | MASK16(v)); } -void +static void setreg8(struct regs *regs, int r, unsigned v) { v &= 0xFF; @@ -269,7 +287,7 @@ setreg8(struct regs *regs, int r, unsigned v) } } -unsigned +static unsigned segment(unsigned prefix, struct regs *regs, unsigned seg) { if (prefix & SEG_ES) @@ -287,7 +305,7 @@ segment(unsigned prefix, struct regs *regs, unsigned seg) return seg; } -unsigned +static unsigned sib(struct regs *regs, int mod, unsigned byte) { unsigned scale = (byte >> 6) & 3; @@ -319,7 +337,7 @@ sib(struct regs *regs, int mod, unsigned byte) /* * Operand (modrm) decode */ -unsigned +static unsigned operand(unsigned prefix, struct regs *regs, unsigned modrm) { int mod, disp = 0, seg; @@ -418,7 +436,7 @@ operand(unsigned prefix, struct regs *regs, unsigned modrm) /* * Load new IDT */ -int +static int lidt(struct regs *regs, unsigned prefix, unsigned modrm) { unsigned eip = regs->eip - 3; @@ -438,7 +456,7 @@ lidt(struct regs *regs, unsigned prefix, unsigned modrm) /* * Load new GDT */ -int +static int lgdt(struct regs *regs, unsigned prefix, unsigned modrm) { unsigned eip = regs->eip - 3; @@ -458,7 +476,7 @@ lgdt(struct regs *regs, unsigned prefix, unsigned modrm) /* * Modify CR0 either through an lmsw instruction. */ -int +static int lmsw(struct regs *regs, unsigned prefix, unsigned modrm) { unsigned eip = regs->eip - 3; @@ -481,7 +499,7 @@ lmsw(struct regs *regs, unsigned prefix, unsigned modrm) * We need to handle moves that address memory beyond the 64KB segment * limit that VM8086 mode enforces. */ -int +static int movr(struct regs *regs, unsigned prefix, unsigned opc) { unsigned eip = regs->eip - 1; @@ -546,7 +564,7 @@ movr(struct regs *regs, unsigned prefix, unsigned opc) /* * Move to and from a control register. */ -int +static int movcr(struct regs *regs, unsigned prefix, unsigned opc) { unsigned eip = regs->eip - 2; @@ -618,7 +636,7 @@ static inline void set_eflags_ZF(unsigned mask, unsigned v1, struct regs *regs) * We need to handle cmp opcodes that address memory beyond the 64KB * segment limit that VM8086 mode enforces. */ -int +static int cmp(struct regs *regs, unsigned prefix, unsigned opc) { unsigned eip = regs->eip - 1; @@ -658,7 +676,7 @@ cmp(struct regs *regs, unsigned prefix, unsigned opc) * We need to handle test opcodes that address memory beyond the 64KB * segment limit that VM8086 mode enforces. */ -int +static int test(struct regs *regs, unsigned prefix, unsigned opc) { unsigned eip = regs->eip - 1; @@ -691,7 +709,7 @@ test(struct regs *regs, unsigned prefix, unsigned opc) * We need to handle pop opcodes that address memory beyond the 64KB * segment limit that VM8086 mode enforces. */ -int +static int pop(struct regs *regs, unsigned prefix, unsigned opc) { unsigned eip = regs->eip - 1; @@ -721,7 +739,7 @@ pop(struct regs *regs, unsigned prefix, unsigned opc) /* * Emulate a segment load in protected mode */ -int +static int load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes *arbytes) { unsigned long long entry; @@ -768,7 +786,7 @@ load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes /* * Transition to protected mode */ -void +static void protected_mode(struct regs *regs) { regs->eflags &= ~(EFLAGS_TF|EFLAGS_VM); @@ -842,7 +860,7 @@ protected_mode(struct regs *regs) /* * Start real-mode emulation */ -void +static void real_mode(struct regs *regs) { regs->eflags |= EFLAGS_VM | 0x02; @@ -935,7 +953,7 @@ set_mode(struct regs *regs, enum vm86_mode newmode) TRACE((regs, 0, states[mode])); } -void +static void jmpl(struct regs *regs, int prefix) { unsigned n = regs->eip; @@ -963,7 +981,7 @@ jmpl(struct regs *regs, int prefix) panic("jmpl"); } -void +static void retl(struct regs *regs, int prefix) { unsigned cs, eip; @@ -990,7 +1008,7 @@ retl(struct regs *regs, int prefix) panic("retl"); } -void +static void interrupt(struct regs *regs, int n) { TRACE((regs, 0, "external interrupt %d", n)); @@ -1008,7 +1026,7 @@ interrupt(struct regs *regs, int n) * interrupt vectors. The following simple state machine catches * these attempts and rewrites them. */ -int +static int outbyte(struct regs *regs, unsigned prefix, unsigned opc) { static char icw2[2] = { 0 }; @@ -1059,7 +1077,7 @@ outbyte(struct regs *regs, unsigned prefix, unsigned opc) return 1; } -int +static int inbyte(struct regs *regs, unsigned prefix, unsigned opc) { int port; @@ -1086,7 +1104,7 @@ enum { OPC_INVALID, OPC_EMULATED }; * a small subset of the opcodes, and not all opcodes are implemented for each * of the four modes we can operate in. */ -int +static int opcode(struct regs *regs) { unsigned eip = regs->eip; @@ -1246,7 +1264,7 @@ opcode(struct regs *regs) if ((mode == VM86_REAL_TO_PROTECTED) || (mode == VM86_PROTECTED_TO_REAL)) { retl(regs, prefix); - return OPC_EMULATED; + return OPC_INVALID; } goto invalid; @@ -1284,7 +1302,7 @@ opcode(struct regs *regs) if ((mode == VM86_REAL_TO_PROTECTED) || (mode == VM86_PROTECTED_TO_REAL)) { jmpl(regs, prefix); - return OPC_EMULATED; + return OPC_INVALID; } goto invalid; diff --git a/tools/firmware/vmxassist/vm86.h b/tools/firmware/vmxassist/vm86.h index d9798bce7e..0c04dc6e73 100644 --- a/tools/firmware/vmxassist/vm86.h +++ b/tools/firmware/vmxassist/vm86.h @@ -58,7 +58,6 @@ extern struct vmx_assist_context oldctx; extern struct vmx_assist_context newctx; extern void emulate(struct regs *); -extern void interrupt(struct regs *, int); extern void dump_regs(struct regs *); extern void trace(struct regs *, int, char *, ...); From 8adde1d0c5aa2783455226fec6cd1b679dcaecab Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sun, 2 Apr 2006 09:48:04 +0100 Subject: [PATCH 052/151] Define __XEN_INTERFACE_VERSION__ when building Xen. Signed-off-by: Keir Fraser --- xen/include/public/xen-compat.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/xen/include/public/xen-compat.h b/xen/include/public/xen-compat.h index 67af72b344..c4f235095d 100644 --- a/xen/include/public/xen-compat.h +++ b/xen/include/public/xen-compat.h @@ -9,10 +9,20 @@ #ifndef __XEN_PUBLIC_XEN_COMPAT_H__ #define __XEN_PUBLIC_XEN_COMPAT_H__ -#ifndef __XEN_INTERFACE_VERSION__ +#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030101 + +#if defined(__XEN__) +/* Xen is built with matching headers and implements the latest interface. */ +#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__ +#elif !defined(__XEN_INTERFACE_VERSION__) +/* Guests which do not specify a version get the legacy interface. */ #define __XEN_INTERFACE_VERSION__ 0x00000000 #endif +#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__ +#error "These header files do not support the requested interface version." +#endif + #if __XEN_INTERFACE_VERSION__ < 0x00030101 #undef __HYPERVISOR_sched_op #define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat From 10daa80b938a274eec3e471ad8891ffcb49d065b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sun, 2 Apr 2006 09:49:17 +0100 Subject: [PATCH 053/151] Enable HYPERVISOR_sched_op() and HYPERVISOR_sched_opt_compat() for ia64. Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/hypercall.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 971007cbf7..286f1a42ff 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -38,7 +38,7 @@ hypercall_t ia64_hypercall_table[] = (hypercall_t)do_ni_hypercall, /* do_stack_switch */ (hypercall_t)do_ni_hypercall, /* do_set_callbacks */ (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch */ /* 5 */ - (hypercall_t)do_ni_hypercall, /* do_sched_op_compat */ + (hypercall_t)do_sched_op_compat, (hypercall_t)do_dom0_op, (hypercall_t)do_ni_hypercall, /* do_set_debugreg */ (hypercall_t)do_ni_hypercall, /* do_get_debugreg */ @@ -61,7 +61,7 @@ hypercall_t ia64_hypercall_table[] = (hypercall_t)do_ni_hypercall, /* do_mmuext_op */ (hypercall_t)do_ni_hypercall, /* do_acm_op */ (hypercall_t)do_ni_hypercall, /* do_nmi_op */ - (hypercall_t)do_ni_hypercall, /* */ + (hypercall_t)do_sched_op, (hypercall_t)do_ni_hypercall, /* */ /* 30 */ (hypercall_t)do_ni_hypercall /* */ }; @@ -70,6 +70,11 @@ static int xen_hypercall (struct pt_regs *regs) { switch (regs->r2) { + case __HYPERVISOR_sched_op_compat: + regs->r8 = do_sched_op_compat((int) regs->r14, + (unsigned long) regs->r15); + break; + case __HYPERVISOR_dom0_op: regs->r8 = do_dom0_op(guest_handle_from_ptr(regs->r14, dom0_op_t)); @@ -117,6 +122,11 @@ xen_hypercall (struct pt_regs *regs) regs->r8 = do_multicall(guest_handle_from_ptr(regs->r14, multicall_entry_t), (unsigned int) regs->r15); break; + case __HYPERVISOR_sched_op: + regs->r8 = do_sched_op((int) regs->r14, + guest_handle_from_ptr(regs->r15, void)); + break; + default: printf("unknown xen hypercall %lx\n", regs->r2); regs->r8 = do_ni_hypercall(); From 0c48c2080d16c59c41ce24bc0ade4f03fbf200e0 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sun, 2 Apr 2006 16:16:53 +0100 Subject: [PATCH 054/151] Make checksum handling in the virtual network drivers more robust. Largely this involves making the logic symmetrical: for example, not only should netfront be able to tell netback that a packet has an empty protocol checksum field, but the reverse must also be true. Another change is that the drivers only advertise IP checksum offload functionality. There is currently no information propagated across the device channel about the offset of the protocol-specific checksum field. Therefore it is not safe to defer checksum calculation for protocols the remote end may not understand -- it will end up dropping having to drop the packet. Yet another change is to allow netback to disable tx checksum offload, just as we already could for netfront. Currently there is no support for disabling rx checksum offload -- that would seem to require some way of propagating the checksum-offload advertisement (or lack of it) across the device channel, as it really ought to be the transmitter that acts on it. Thanks to Ian Jackson for pointing out some of the problems with our checksum-offload handling. Several of the changes here are due to his comments. Signed-off-by: Keir Fraser --- .../drivers/xen/netback/interface.c | 11 +++++++- .../drivers/xen/netback/loopback.c | 27 +++++++++---------- .../drivers/xen/netback/netback.c | 25 ++++++++++------- .../drivers/xen/netfront/netfront.c | 15 +++++++++-- linux-2.6-xen-sparse/include/linux/skbuff.h | 4 +-- linux-2.6-xen-sparse/net/core/dev.c | 4 +-- linux-2.6-xen-sparse/net/core/skbuff.c | 2 +- 7 files changed, 56 insertions(+), 32 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index be96a6d3ac..5c3cbc75d9 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -31,6 +31,7 @@ */ #include "common.h" +#include #include static void __netif_up(netif_t *netif) @@ -71,6 +72,12 @@ static int net_close(struct net_device *dev) return 0; } +static struct ethtool_ops network_ethtool_ops = +{ + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, +}; + netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]) { int err = 0, i; @@ -101,7 +108,9 @@ netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]) dev->get_stats = netif_be_get_stats; dev->open = net_open; dev->stop = net_close; - dev->features = NETIF_F_NO_CSUM; + dev->features = NETIF_F_IP_CSUM; + + SET_ETHTOOL_OPS(dev, &network_ethtool_ops); /* Disable queuing. */ dev->tx_queue_len = 0; diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c index e9f354a837..870b4aa2a6 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c @@ -100,10 +100,10 @@ static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Defer checksum calculation. */ skb->proto_csum_blank = 1; /* Must be a local packet: assert its integrity. */ - skb->proto_csum_valid = 1; + skb->proto_data_valid = 1; } - skb->ip_summed = skb->proto_csum_valid ? + skb->ip_summed = skb->proto_data_valid ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE; skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */ @@ -121,6 +121,12 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev) return &np->stats; } +static struct ethtool_ops network_ethtool_ops = +{ + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, +}; + static void loopback_construct(struct net_device *dev, struct net_device *lo) { struct net_private *np = netdev_priv(dev); @@ -134,7 +140,11 @@ static void loopback_construct(struct net_device *dev, struct net_device *lo) dev->tx_queue_len = 0; - dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX; + dev->features = (NETIF_F_HIGHDMA | + NETIF_F_LLTX | + NETIF_F_IP_CSUM); + + SET_ETHTOOL_OPS(dev, &network_ethtool_ops); /* * We do not set a jumbo MTU on the interface. Otherwise the network @@ -147,12 +157,6 @@ static void loopback_construct(struct net_device *dev, struct net_device *lo) /*dev->mtu = 16*1024;*/ } -static struct ethtool_ops network_ethtool_ops = -{ - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, -}; - static int __init make_loopback(int i) { struct net_device *dev1, *dev2; @@ -172,11 +176,6 @@ static int __init make_loopback(int i) loopback_construct(dev1, dev2); loopback_construct(dev2, dev1); - dev1->features |= NETIF_F_NO_CSUM; - dev2->features |= NETIF_F_IP_CSUM; - - SET_ETHTOOL_OPS(dev2, &network_ethtool_ops); - /* * Initialise a dummy MAC address for the 'dummy backend' interface. We * choose the numerically largest non-broadcast address to prevent the diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index 41d4bf90d2..d9f259ce26 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -171,7 +171,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->len + hlen); BUG_ON(ret); nskb->dev = skb->dev; - nskb->proto_csum_valid = skb->proto_csum_valid; + nskb->proto_data_valid = skb->proto_data_valid; dev_kfree_skb(skb); skb = nskb; } @@ -213,7 +213,7 @@ static void net_rx_action(unsigned long unused) { netif_t *netif = NULL; s8 status; - u16 size, id, irq; + u16 size, id, irq, flags; multicall_entry_t *mcl; mmu_update_t *mmu; gnttab_transfer_t *gop; @@ -328,10 +328,14 @@ static void net_rx_action(unsigned long unused) } irq = netif->irq; id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id; + flags = 0; + if (skb->ip_summed == CHECKSUM_HW) + flags |= NETRXF_csum_blank; + if (skb->proto_data_valid) + flags |= NETRXF_data_validated; if (make_rx_response(netif, id, status, (unsigned long)skb->data & ~PAGE_MASK, - size, skb->proto_csum_valid ? - NETRXF_data_validated : 0) && + size, flags) && (rx_notify[irq] == 0)) { rx_notify[irq] = 1; notify_list[notify_nr++] = irq; @@ -654,12 +658,13 @@ static void net_tx_action(unsigned long unused) skb->dev = netif->dev; skb->protocol = eth_type_trans(skb, skb->dev); - /* - * No checking needed on localhost, but remember the field is - * blank. - */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->proto_csum_valid = 1; + if (txreq.flags & NETTXF_data_validated) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->proto_data_valid = 1; + } else { + skb->ip_summed = CHECKSUM_NONE; + skb->proto_data_valid = 0; + } skb->proto_csum_blank = !!(txreq.flags & NETTXF_csum_blank); netif->stats.rx_bytes += txreq.size; diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 6c7b82f789..1f2ee99e58 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -696,7 +696,12 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) tx->gref = np->grant_tx_ref[id] = ref; tx->offset = (unsigned long)skb->data & ~PAGE_MASK; tx->size = skb->len; - tx->flags = (skb->ip_summed == CHECKSUM_HW) ? NETTXF_csum_blank : 0; + + tx->flags = 0; + if (skb->ip_summed == CHECKSUM_HW) + tx->flags |= NETTXF_csum_blank; + if (skb->proto_data_valid) + tx->flags |= NETTXF_data_validated; np->tx.req_prod_pvt = i + 1; RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify); @@ -811,8 +816,14 @@ static int netif_poll(struct net_device *dev, int *pbudget) skb->len = rx->status; skb->tail = skb->data + skb->len; - if (rx->flags & NETRXF_data_validated) + if (rx->flags & NETRXF_data_validated) { skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->proto_data_valid = 1; + } else { + skb->ip_summed = CHECKSUM_NONE; + skb->proto_data_valid = 0; + } + skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank); np->stats.rx_packets++; np->stats.rx_bytes += rx->status; diff --git a/linux-2.6-xen-sparse/include/linux/skbuff.h b/linux-2.6-xen-sparse/include/linux/skbuff.h index 0d2052865f..911eb6d045 100644 --- a/linux-2.6-xen-sparse/include/linux/skbuff.h +++ b/linux-2.6-xen-sparse/include/linux/skbuff.h @@ -189,7 +189,7 @@ enum { * @local_df: allow local fragmentation * @cloned: Head may be cloned (check refcnt to be sure) * @nohdr: Payload reference only, must not modify header - * @proto_csum_valid: Protocol csum validated since arriving at localhost + * @proto_data_valid: Protocol data validated since arriving at localhost * @proto_csum_blank: Protocol csum must be added before leaving localhost * @pkt_type: Packet class * @fclone: skbuff clone status @@ -271,7 +271,7 @@ struct sk_buff { ipvs_property:1; #else ipvs_property:1, - proto_csum_valid:1, + proto_data_valid:1, proto_csum_blank:1; #endif __be16 protocol; diff --git a/linux-2.6-xen-sparse/net/core/dev.c b/linux-2.6-xen-sparse/net/core/dev.c index 30baa344b7..7a98ceb658 100644 --- a/linux-2.6-xen-sparse/net/core/dev.c +++ b/linux-2.6-xen-sparse/net/core/dev.c @@ -1649,12 +1649,12 @@ int netif_receive_skb(struct sk_buff *skb) #ifdef CONFIG_XEN switch (skb->ip_summed) { case CHECKSUM_UNNECESSARY: - skb->proto_csum_valid = 1; + skb->proto_data_valid = 1; break; case CHECKSUM_HW: /* XXX Implement me. */ default: - skb->proto_csum_valid = 0; + skb->proto_data_valid = 0; break; } #endif diff --git a/linux-2.6-xen-sparse/net/core/skbuff.c b/linux-2.6-xen-sparse/net/core/skbuff.c index dadc9cfa93..d00e58e216 100644 --- a/linux-2.6-xen-sparse/net/core/skbuff.c +++ b/linux-2.6-xen-sparse/net/core/skbuff.c @@ -428,7 +428,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) n->cloned = 1; n->nohdr = 0; #ifdef CONFIG_XEN - C(proto_csum_valid); + C(proto_data_valid); C(proto_csum_blank); #endif C(pkt_type); From d3cf31ddb2d9be1098236472401185786c0f42e4 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Mon, 3 Apr 2006 14:34:20 +0100 Subject: [PATCH 055/151] Handle failure to register the xen store event channel instead of just not initialising xenbus/store when the supervisor_mode_kernel feature flag is enabled. When initialising grant tables only -ENOSYS is a valid reason to fail so BUG_ON anything else like we did prior to changeset 9498. Signed-off-by: Ian Campbell --- .../drivers/xen/core/gnttab.c | 6 +-- .../drivers/xen/xenbus/xenbus_probe.c | 41 +++++++++++-------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c index fa12e701d4..71da6c4df9 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c @@ -395,10 +395,10 @@ gnttab_resume(void) setup.frame_list = frames; rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); - if (rc < 0) - return rc; + if (rc == -ENOSYS) + return -ENOSYS; - BUG_ON(setup.status); + BUG_ON(rc || setup.status); #ifndef __ia64__ if (shared == NULL) { diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index db1492d050..e9c8315856 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -984,6 +984,7 @@ static int xsd_port_read(char *page, char **start, off_t off, static int __init xenbus_probe_init(void) { int err = 0, dom0; + unsigned long page = 0; DPRINTK(""); @@ -992,19 +993,9 @@ static int __init xenbus_probe_init(void) return -ENODEV; } - /* Register ourselves with the kernel bus & device subsystems */ + /* Register ourselves with the kernel bus subsystem */ bus_register(&xenbus_frontend.bus); bus_register(&xenbus_backend.bus); - device_register(&xenbus_frontend.dev); - device_register(&xenbus_backend.dev); - - /* - * The supervisor_mode_kernel feature only allows a single - * domain so there is no need to initialise event channels - * etc. - */ - if (xen_feature(XENFEAT_supervisor_mode_kernel)) - return -ENODEV; /* * Domain0 doesn't have a store_evtchn or store_mfn yet. @@ -1012,11 +1003,7 @@ static int __init xenbus_probe_init(void) dom0 = (xen_start_info->store_evtchn == 0); if (dom0) { - - unsigned long page; evtchn_op_t op = { 0 }; - int ret; - /* Allocate page. */ page = get_zeroed_page(GFP_KERNEL); @@ -1032,8 +1019,10 @@ static int __init xenbus_probe_init(void) op.u.alloc_unbound.dom = DOMID_SELF; op.u.alloc_unbound.remote_dom = 0; - ret = HYPERVISOR_event_channel_op(&op); - BUG_ON(ret); + err = HYPERVISOR_event_channel_op(&op); + if (err == -ENOSYS) + goto err; + BUG_ON(err); xen_start_info->store_evtchn = op.u.alloc_unbound.port; /* And finally publish the above info in /proc/xen */ @@ -1056,13 +1045,29 @@ static int __init xenbus_probe_init(void) if (err) { printk(KERN_WARNING "XENBUS: Error initializing xenstore comms: %i\n", err); - return err; + goto err; } + /* Register ourselves with the kernel device subsystem */ + device_register(&xenbus_frontend.dev); + device_register(&xenbus_backend.dev); + if (!dom0) xenbus_probe(NULL); return 0; + + err: + if (page) + free_page(page); + + /* + * Do not unregister the xenbus front/backend buses here. The + * buses must exist because front/backend drivers will use + * them when they are registered. + */ + + return err; } postcore_initcall(xenbus_probe_init); From 5e8883cc8c7075e3c1b03c50016f433153ea9c01 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 3 Apr 2006 15:52:58 +0100 Subject: [PATCH 056/151] Added tag 3.0.2-branched for changeset d0d3fef37685be264a7f52201f8ef44c030daad3 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 78c6645d6c..b097c216b9 100644 --- a/.hgtags +++ b/.hgtags @@ -14,3 +14,4 @@ fb875591fd72e15c31879c0e9034d99b80225595 RELEASE-2.0.4 3d330e41f41ce1bc118c02346e18949ad5d67f6b split-1.1 c8fdb0caa77b429cf47f9707926e83947778cb48 RELEASE-3.0.0 af0573e9e5258db0a9d28aa954dd302ddd2c2d23 3.0.2-rc +d0d3fef37685be264a7f52201f8ef44c030daad3 3.0.2-branched From f55976facfbc63f0c8619070a5b2be32a915a67a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 3 Apr 2006 16:35:06 +0100 Subject: [PATCH 057/151] Remove send_IPI_all, send_IPI_allbutself and send_IPI_self shortcutting IPI functions. They're either unused or used so frequently that we may as well simplify things and always use send_IPI_mask. Signed-off-by: Keir Fraser --- xen/arch/x86/genapic/default.c | 18 ---- xen/arch/x86/smp.c | 97 ++++++--------------- xen/include/asm-x86/genapic.h | 4 - xen/include/asm-x86/mach-bigsmp/mach_ipi.h | 14 --- xen/include/asm-x86/mach-default/mach_ipi.h | 40 --------- xen/include/asm-x86/mach-es7000/mach_ipi.h | 13 --- xen/include/asm-x86/mach-generic/mach_ipi.h | 2 - xen/include/asm-x86/mach-summit/mach_ipi.h | 14 --- 8 files changed, 26 insertions(+), 176 deletions(-) diff --git a/xen/arch/x86/genapic/default.c b/xen/arch/x86/genapic/default.c index 88853e0290..d84cf41141 100644 --- a/xen/arch/x86/genapic/default.c +++ b/xen/arch/x86/genapic/default.c @@ -18,15 +18,6 @@ #include #include -#ifdef CONFIG_HOTPLUG_CPU -#define DEFAULT_SEND_IPI (1) -#else -#define DEFAULT_SEND_IPI (0) -#endif - -int no_broadcast = DEFAULT_SEND_IPI; -integer_param("no_ipi_broadcast", no_broadcast); - /* should be called last. */ static __init int probe_default(void) { @@ -34,12 +25,3 @@ static __init int probe_default(void) } struct genapic apic_default = APIC_INIT("default", probe_default); - -static int __init print_ipi_mode(void) -{ - if (genapic == &apic_default) - printk("Using IPI %sShortcut mode\n", - no_broadcast ? "No-" : ""); - return 0; -} -__initcall(print_ipi_mode); diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index fc0a545883..18240da6f5 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * Some notes on x86 processor bugs affecting SMP operation: @@ -74,38 +75,6 @@ static inline int __prepare_ICR2 (unsigned int mask) return SET_APIC_DEST_FIELD(mask); } -void __send_IPI_shortcut(unsigned int shortcut, int vector) -{ - /* - * Subtle. In the case of the 'never do double writes' workaround - * we have to lock out interrupts to be safe. As we don't care - * of the value read we use an atomic rmw access to avoid costly - * cli/sti. Otherwise we use an even cheaper single atomic write - * to the APIC. - */ - unsigned int cfg; - - /* - * Wait for idle. - */ - apic_wait_icr_idle(); - - /* - * No need to touch the target chip field - */ - cfg = __prepare_ICR(shortcut, vector); - - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); -} - -void send_IPI_self(int vector) -{ - __send_IPI_shortcut(APIC_DEST_SELF, vector); -} - static inline void check_IPI_mask(cpumask_t cpumask) { /* @@ -116,9 +85,6 @@ static inline void check_IPI_mask(cpumask_t cpumask) ASSERT(!cpus_empty(cpumask)); } -/* - * This is only used on smaller machines. - */ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) { unsigned long mask = cpus_addr(cpumask)[0]; @@ -168,36 +134,33 @@ inline void send_IPI_mask_sequence(cpumask_t mask, int vector) local_irq_save(flags); - for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) { - if (cpu_isset(query_cpu, mask)) { + for_each_cpu_mask( query_cpu, mask ) + { + /* + * Wait for idle. + */ + apic_wait_icr_idle(); - /* - * Wait for idle. - */ - apic_wait_icr_idle(); + /* + * prepare target chip field + */ + cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu)); + apic_write_around(APIC_ICR2, cfg); - /* - * prepare target chip field - */ - cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu)); - apic_write_around(APIC_ICR2, cfg); - - /* - * program the ICR - */ - cfg = __prepare_ICR(0, vector); + /* + * program the ICR + */ + cfg = __prepare_ICR(0, vector); - /* - * Send the IPI. The write to APIC_ICR fires this off. - */ - apic_write_around(APIC_ICR, cfg); - } + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); } + local_irq_restore(flags); } -#include - static spinlock_t flush_lock = SPIN_LOCK_UNLOCKED; static cpumask_t flush_cpumask; static unsigned long flush_va; @@ -241,20 +204,12 @@ void __flush_tlb_mask(cpumask_t mask, unsigned long va) /* Call with no locks held and interrupts enabled (e.g., softirq context). */ void new_tlbflush_clock_period(void) { - ASSERT(local_irq_is_enabled()); - + cpumask_t allbutself; + /* Flush everyone else. We definitely flushed just before entry. */ - if ( num_online_cpus() > 1 ) - { - spin_lock(&flush_lock); - flush_cpumask = cpu_online_map; - flush_va = FLUSHVA_ALL; - send_IPI_allbutself(INVALIDATE_TLB_VECTOR); - cpu_clear(smp_processor_id(), flush_cpumask); - while ( !cpus_empty(flush_cpumask) ) - cpu_relax(); - spin_unlock(&flush_lock); - } + allbutself = cpu_online_map; + cpu_clear(smp_processor_id(), allbutself); + __flush_tlb_mask(allbutself, FLUSHVA_ALL); /* No need for atomicity: we are the only possible updater. */ ASSERT(tlbflush_clock == 0); diff --git a/xen/include/asm-x86/genapic.h b/xen/include/asm-x86/genapic.h index e7c1356dcb..2c7fa476f3 100644 --- a/xen/include/asm-x86/genapic.h +++ b/xen/include/asm-x86/genapic.h @@ -54,8 +54,6 @@ struct genapic { /* ipi */ void (*send_IPI_mask)(cpumask_t mask, int vector); - void (*send_IPI_allbutself)(int vector); - void (*send_IPI_all)(int vector); }; #define APICFUNC(x) .x = x @@ -85,8 +83,6 @@ struct genapic { APICFUNC(cpu_mask_to_apicid), \ APICFUNC(acpi_madt_oem_check), \ APICFUNC(send_IPI_mask), \ - APICFUNC(send_IPI_allbutself), \ - APICFUNC(send_IPI_all), \ APICFUNC(enable_apic_mode), \ APICFUNC(phys_pkg_id), \ } diff --git a/xen/include/asm-x86/mach-bigsmp/mach_ipi.h b/xen/include/asm-x86/mach-bigsmp/mach_ipi.h index 9404c535b7..c487589d94 100644 --- a/xen/include/asm-x86/mach-bigsmp/mach_ipi.h +++ b/xen/include/asm-x86/mach-bigsmp/mach_ipi.h @@ -8,18 +8,4 @@ static inline void send_IPI_mask(cpumask_t mask, int vector) send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) -{ - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); - - if (!cpus_empty(mask)) - send_IPI_mask(mask, vector); -} - -static inline void send_IPI_all(int vector) -{ - send_IPI_mask(cpu_online_map, vector); -} - #endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-default/mach_ipi.h b/xen/include/asm-x86/mach-default/mach_ipi.h index a1d0072e36..069f16cede 100644 --- a/xen/include/asm-x86/mach-default/mach_ipi.h +++ b/xen/include/asm-x86/mach-default/mach_ipi.h @@ -2,50 +2,10 @@ #define __ASM_MACH_IPI_H void send_IPI_mask_bitmask(cpumask_t mask, int vector); -void __send_IPI_shortcut(unsigned int shortcut, int vector); - -extern int no_broadcast; static inline void send_IPI_mask(cpumask_t mask, int vector) { send_IPI_mask_bitmask(mask, vector); } -static inline void __local_send_IPI_allbutself(int vector) -{ - if (no_broadcast) { - cpumask_t mask = cpu_online_map; - - cpu_clear(smp_processor_id(), mask); - send_IPI_mask(mask, vector); - } else - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector); -} - -static inline void __local_send_IPI_all(int vector) -{ - if (no_broadcast) - send_IPI_mask(cpu_online_map, vector); - else - __send_IPI_shortcut(APIC_DEST_ALLINC, vector); -} - -static inline void send_IPI_allbutself(int vector) -{ - /* - * if there are no other CPUs in the system then we get an APIC send - * error if we try to broadcast, thus avoid sending IPIs in this case. - */ - if (!(num_online_cpus() > 1)) - return; - - __local_send_IPI_allbutself(vector); - return; -} - -static inline void send_IPI_all(int vector) -{ - __local_send_IPI_all(vector); -} - #endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-es7000/mach_ipi.h b/xen/include/asm-x86/mach-es7000/mach_ipi.h index 5e61bd220b..c487589d94 100644 --- a/xen/include/asm-x86/mach-es7000/mach_ipi.h +++ b/xen/include/asm-x86/mach-es7000/mach_ipi.h @@ -8,17 +8,4 @@ static inline void send_IPI_mask(cpumask_t mask, int vector) send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) -{ - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); - if (!cpus_empty(mask)) - send_IPI_mask(mask, vector); -} - -static inline void send_IPI_all(int vector) -{ - send_IPI_mask(cpu_online_map, vector); -} - #endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-generic/mach_ipi.h b/xen/include/asm-x86/mach-generic/mach_ipi.h index 441b0fe3ed..06bfd75100 100644 --- a/xen/include/asm-x86/mach-generic/mach_ipi.h +++ b/xen/include/asm-x86/mach-generic/mach_ipi.h @@ -4,7 +4,5 @@ #include #define send_IPI_mask (genapic->send_IPI_mask) -#define send_IPI_allbutself (genapic->send_IPI_allbutself) -#define send_IPI_all (genapic->send_IPI_all) #endif diff --git a/xen/include/asm-x86/mach-summit/mach_ipi.h b/xen/include/asm-x86/mach-summit/mach_ipi.h index 9404c535b7..c487589d94 100644 --- a/xen/include/asm-x86/mach-summit/mach_ipi.h +++ b/xen/include/asm-x86/mach-summit/mach_ipi.h @@ -8,18 +8,4 @@ static inline void send_IPI_mask(cpumask_t mask, int vector) send_IPI_mask_sequence(mask, vector); } -static inline void send_IPI_allbutself(int vector) -{ - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); - - if (!cpus_empty(mask)) - send_IPI_mask(mask, vector); -} - -static inline void send_IPI_all(int vector) -{ - send_IPI_mask(cpu_online_map, vector); -} - #endif /* __ASM_MACH_IPI_H */ From 4b233c874995b8094af311962df7a1fc999595e7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 3 Apr 2006 17:47:42 +0100 Subject: [PATCH 058/151] Clean up subarch 'mach-foo' header files. No need for subarch apicdef.h and ipi.h can be much simplified. Signed-off-by: Keir Fraser --- xen/arch/x86/genapic/bigsmp.c | 9 +-- xen/arch/x86/genapic/default.c | 9 +-- xen/arch/x86/genapic/es7000.c | 10 ++-- xen/arch/x86/genapic/probe.c | 5 -- xen/arch/x86/genapic/summit.c | 9 +-- xen/arch/x86/smp.c | 4 +- xen/include/asm-x86/apicdef.h | 3 + xen/include/asm-x86/genapic.h | 10 +--- .../asm-x86/mach-bigsmp/mach_apicdef.h | 11 ---- xen/include/asm-x86/mach-bigsmp/mach_ipi.h | 11 ---- xen/include/asm-x86/mach-default/mach_apic.h | 1 - .../asm-x86/mach-default/mach_apicdef.h | 11 ---- xen/include/asm-x86/mach-default/mach_ipi.h | 11 ---- .../mach_mpspec.h | 0 .../asm-x86/mach-es7000/mach_apicdef.h | 11 ---- .../asm-x86/mach-es7000/mach_wakecpu.h | 58 ------------------- .../asm-x86/mach-generic/mach_apicdef.h | 10 ---- xen/include/asm-x86/mach-generic/mach_ipi.h | 8 --- .../asm-x86/mach-summit/mach_apicdef.h | 11 ---- xen/include/asm-x86/mach-summit/mach_ipi.h | 11 ---- .../asm-x86/{mach-es7000 => }/mach_ipi.h | 8 +-- xen/include/asm-x86/smp.h | 5 -- 22 files changed, 32 insertions(+), 194 deletions(-) delete mode 100644 xen/include/asm-x86/mach-bigsmp/mach_apicdef.h delete mode 100644 xen/include/asm-x86/mach-bigsmp/mach_ipi.h delete mode 100644 xen/include/asm-x86/mach-default/mach_apicdef.h delete mode 100644 xen/include/asm-x86/mach-default/mach_ipi.h rename xen/include/asm-x86/{mach-generic => mach-default}/mach_mpspec.h (100%) delete mode 100644 xen/include/asm-x86/mach-es7000/mach_apicdef.h delete mode 100644 xen/include/asm-x86/mach-es7000/mach_wakecpu.h delete mode 100644 xen/include/asm-x86/mach-generic/mach_apicdef.h delete mode 100644 xen/include/asm-x86/mach-generic/mach_ipi.h delete mode 100644 xen/include/asm-x86/mach-summit/mach_apicdef.h delete mode 100644 xen/include/asm-x86/mach-summit/mach_ipi.h rename xen/include/asm-x86/{mach-es7000 => }/mach_ipi.h (52%) diff --git a/xen/arch/x86/genapic/bigsmp.c b/xen/arch/x86/genapic/bigsmp.c index 61b594a409..4338e5765e 100644 --- a/xen/arch/x86/genapic/bigsmp.c +++ b/xen/arch/x86/genapic/bigsmp.c @@ -2,7 +2,6 @@ * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. * Drives the local APIC in "clustered mode". */ -#define APIC_DEFINITION 1 #include #include #include @@ -14,9 +13,8 @@ #include #include #include +#include #include -#include -#include #include static int dmi_bigsmp; /* can be set by dmi scanners */ @@ -52,4 +50,7 @@ static __init int probe_bigsmp(void) return dmi_bigsmp; } -struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); +struct genapic apic_bigsmp = { + APIC_INIT("bigsmp", probe_bigsmp), + .send_ipi_mask = send_IPI_mask_sequence +}; diff --git a/xen/arch/x86/genapic/default.c b/xen/arch/x86/genapic/default.c index d84cf41141..a7403922bb 100644 --- a/xen/arch/x86/genapic/default.c +++ b/xen/arch/x86/genapic/default.c @@ -1,12 +1,10 @@ /* * Default generic APIC driver. This handles upto 8 CPUs. */ -#define APIC_DEFINITION 1 #include #include #include #include -#include #include #include #include @@ -14,8 +12,8 @@ #include #include #include +#include #include -#include #include /* should be called last. */ @@ -24,4 +22,7 @@ static __init int probe_default(void) return 1; } -struct genapic apic_default = APIC_INIT("default", probe_default); +struct genapic apic_default = { + APIC_INIT("default", probe_default), + .send_ipi_mask = send_IPI_mask_bitmask +}; diff --git a/xen/arch/x86/genapic/es7000.c b/xen/arch/x86/genapic/es7000.c index 05e94b0f04..37c959bf4c 100644 --- a/xen/arch/x86/genapic/es7000.c +++ b/xen/arch/x86/genapic/es7000.c @@ -1,7 +1,6 @@ /* * APIC driver for the Unisys ES7000 chipset. */ -#define APIC_DEFINITION 1 #include #include #include @@ -14,11 +13,9 @@ #include #include #include -#include +#include #include -#include #include -#include static __init int probe_es7000(void) { @@ -26,4 +23,7 @@ static __init int probe_es7000(void) return 0; } -struct genapic apic_es7000 = APIC_INIT("es7000", probe_es7000); +struct genapic apic_es7000 = { + APIC_INIT("es7000", probe_es7000), + .send_ipi_mask = send_IPI_mask_sequence +}; diff --git a/xen/arch/x86/genapic/probe.c b/xen/arch/x86/genapic/probe.c index cddde7a459..4b1d375b1d 100644 --- a/xen/arch/x86/genapic/probe.c +++ b/xen/arch/x86/genapic/probe.c @@ -103,8 +103,3 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) } return 0; } - -int hard_smp_processor_id(void) -{ - return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); -} diff --git a/xen/arch/x86/genapic/summit.c b/xen/arch/x86/genapic/summit.c index 28a47f09de..acf191acfc 100644 --- a/xen/arch/x86/genapic/summit.c +++ b/xen/arch/x86/genapic/summit.c @@ -1,7 +1,6 @@ /* * APIC driver for the IBM "Summit" chipset. */ -#define APIC_DEFINITION 1 #include #include #include @@ -13,9 +12,8 @@ #include #include #include +#include #include -#include -#include #include static __init int probe_summit(void) @@ -24,4 +22,7 @@ static __init int probe_summit(void) return 0; } -struct genapic apic_summit = APIC_INIT("summit", probe_summit); +struct genapic apic_summit = { + APIC_INIT("summit", probe_summit), + .send_ipi_mask = send_IPI_mask_sequence +}; diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index 18240da6f5..f94ad00517 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -20,8 +20,8 @@ #include #include #include +#include #include -#include /* * Some notes on x86 processor bugs affecting SMP operation: @@ -119,7 +119,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) local_irq_restore(flags); } -inline void send_IPI_mask_sequence(cpumask_t mask, int vector) +void send_IPI_mask_sequence(cpumask_t mask, int vector) { unsigned long cfg, flags; unsigned int query_cpu; diff --git a/xen/include/asm-x86/apicdef.h b/xen/include/asm-x86/apicdef.h index 402b2a9da5..81bb2b84cb 100644 --- a/xen/include/asm-x86/apicdef.h +++ b/xen/include/asm-x86/apicdef.h @@ -11,6 +11,9 @@ #define APIC_DEFAULT_PHYS_BASE 0xfee00000 #define APIC_ID 0x20 +#define APIC_ID_MASK (0xFFu<<24) +#define GET_APIC_ID(x) (((x)>>24)&0xFFu) +#define SET_APIC_ID(x) (((x)<<24)) #define APIC_LVR 0x30 #define APIC_LVR_MASK 0xFF00FF #define GET_APIC_VERSION(x) ((x)&0xFF) diff --git a/xen/include/asm-x86/genapic.h b/xen/include/asm-x86/genapic.h index 2c7fa476f3..751e1dfc28 100644 --- a/xen/include/asm-x86/genapic.h +++ b/xen/include/asm-x86/genapic.h @@ -49,16 +49,15 @@ struct genapic { char *productid); int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); - unsigned (*get_apic_id)(unsigned long x); unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); /* ipi */ - void (*send_IPI_mask)(cpumask_t mask, int vector); + void (*send_ipi_mask)(cpumask_t mask, int vector); }; #define APICFUNC(x) .x = x -#define APIC_INIT(aname, aprobe) { \ +#define APIC_INIT(aname, aprobe) \ .name = aname, \ .probe = aprobe, \ .int_delivery_mode = INT_DELIVERY_MODE, \ @@ -79,13 +78,10 @@ struct genapic { APICFUNC(apicid_to_cpu_present), \ APICFUNC(check_phys_apicid_present), \ APICFUNC(mps_oem_check), \ - APICFUNC(get_apic_id), \ APICFUNC(cpu_mask_to_apicid), \ APICFUNC(acpi_madt_oem_check), \ - APICFUNC(send_IPI_mask), \ APICFUNC(enable_apic_mode), \ - APICFUNC(phys_pkg_id), \ - } + APICFUNC(phys_pkg_id) extern struct genapic *genapic; diff --git a/xen/include/asm-x86/mach-bigsmp/mach_apicdef.h b/xen/include/asm-x86/mach-bigsmp/mach_apicdef.h deleted file mode 100644 index 4842ed8ba2..0000000000 --- a/xen/include/asm-x86/mach-bigsmp/mach_apicdef.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xFF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif diff --git a/xen/include/asm-x86/mach-bigsmp/mach_ipi.h b/xen/include/asm-x86/mach-bigsmp/mach_ipi.h deleted file mode 100644 index c487589d94..0000000000 --- a/xen/include/asm-x86/mach-bigsmp/mach_ipi.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H - -void send_IPI_mask_sequence(cpumask_t mask, int vector); - -static inline void send_IPI_mask(cpumask_t mask, int vector) -{ - send_IPI_mask_sequence(mask, vector); -} - -#endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-default/mach_apic.h b/xen/include/asm-x86/mach-default/mach_apic.h index b1c76fe27b..c673ae24bb 100644 --- a/xen/include/asm-x86/mach-default/mach_apic.h +++ b/xen/include/asm-x86/mach-default/mach_apic.h @@ -1,7 +1,6 @@ #ifndef __ASM_MACH_APIC_H #define __ASM_MACH_APIC_H -#include #include #define APIC_DFR_VALUE (APIC_DFR_FLAT) diff --git a/xen/include/asm-x86/mach-default/mach_apicdef.h b/xen/include/asm-x86/mach-default/mach_apicdef.h deleted file mode 100644 index db8c9237e0..0000000000 --- a/xen/include/asm-x86/mach-default/mach_apicdef.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif diff --git a/xen/include/asm-x86/mach-default/mach_ipi.h b/xen/include/asm-x86/mach-default/mach_ipi.h deleted file mode 100644 index 069f16cede..0000000000 --- a/xen/include/asm-x86/mach-default/mach_ipi.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H - -void send_IPI_mask_bitmask(cpumask_t mask, int vector); - -static inline void send_IPI_mask(cpumask_t mask, int vector) -{ - send_IPI_mask_bitmask(mask, vector); -} - -#endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-generic/mach_mpspec.h b/xen/include/asm-x86/mach-default/mach_mpspec.h similarity index 100% rename from xen/include/asm-x86/mach-generic/mach_mpspec.h rename to xen/include/asm-x86/mach-default/mach_mpspec.h diff --git a/xen/include/asm-x86/mach-es7000/mach_apicdef.h b/xen/include/asm-x86/mach-es7000/mach_apicdef.h deleted file mode 100644 index 4842ed8ba2..0000000000 --- a/xen/include/asm-x86/mach-es7000/mach_apicdef.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xFF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif diff --git a/xen/include/asm-x86/mach-es7000/mach_wakecpu.h b/xen/include/asm-x86/mach-es7000/mach_wakecpu.h deleted file mode 100644 index d43e0b6235..0000000000 --- a/xen/include/asm-x86/mach-es7000/mach_wakecpu.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __ASM_MACH_WAKECPU_H -#define __ASM_MACH_WAKECPU_H - -/* - * This file copes with machines that wakeup secondary CPUs by the - * INIT, INIT, STARTUP sequence. - */ - -#ifdef CONFIG_ES7000_CLUSTERED_APIC -#define WAKE_SECONDARY_VIA_MIP -#else -#define WAKE_SECONDARY_VIA_INIT -#endif - -#ifdef WAKE_SECONDARY_VIA_MIP -extern int es7000_start_cpu(int cpu, unsigned long eip); -static inline int -wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) -{ - int boot_error = 0; - boot_error = es7000_start_cpu(phys_apicid, start_eip); - return boot_error; -} -#endif - -#define TRAMPOLINE_LOW maddr_to_virt(0x467) -#define TRAMPOLINE_HIGH maddr_to_virt(0x469) - -#define boot_cpu_apicid boot_cpu_physical_apicid - -static inline void wait_for_init_deassert(atomic_t *deassert) -{ -#ifdef WAKE_SECONDARY_VIA_INIT - while (!atomic_read(deassert)); -#endif - return; -} - -/* Nothing to do for most platforms, since cleared by the INIT cycle */ -static inline void smp_callin_clear_local_apic(void) -{ -} - -static inline void store_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - -static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) -{ -} - -#if APIC_DEBUG - #define inquire_remote_apic(apicid) __inquire_remote_apic(apicid) -#else - #define inquire_remote_apic(apicid) {} -#endif - -#endif /* __ASM_MACH_WAKECPU_H */ diff --git a/xen/include/asm-x86/mach-generic/mach_apicdef.h b/xen/include/asm-x86/mach-generic/mach_apicdef.h deleted file mode 100644 index 78eada8442..0000000000 --- a/xen/include/asm-x86/mach-generic/mach_apicdef.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _GENAPIC_MACH_APICDEF_H -#define _GENAPIC_MACH_APICDEF_H 1 - -#ifndef APIC_DEFINITION -#include - -#define GET_APIC_ID (genapic->get_apic_id) -#endif - -#endif diff --git a/xen/include/asm-x86/mach-generic/mach_ipi.h b/xen/include/asm-x86/mach-generic/mach_ipi.h deleted file mode 100644 index 06bfd75100..0000000000 --- a/xen/include/asm-x86/mach-generic/mach_ipi.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _MACH_IPI_H -#define _MACH_IPI_H 1 - -#include - -#define send_IPI_mask (genapic->send_IPI_mask) - -#endif diff --git a/xen/include/asm-x86/mach-summit/mach_apicdef.h b/xen/include/asm-x86/mach-summit/mach_apicdef.h deleted file mode 100644 index 4842ed8ba2..0000000000 --- a/xen/include/asm-x86/mach-summit/mach_apicdef.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_APICDEF_H -#define __ASM_MACH_APICDEF_H - -static inline unsigned get_apic_id(unsigned long x) -{ - return (((x)>>24)&0xFF); -} - -#define GET_APIC_ID(x) get_apic_id(x) - -#endif diff --git a/xen/include/asm-x86/mach-summit/mach_ipi.h b/xen/include/asm-x86/mach-summit/mach_ipi.h deleted file mode 100644 index c487589d94..0000000000 --- a/xen/include/asm-x86/mach-summit/mach_ipi.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H - -void send_IPI_mask_sequence(cpumask_t mask, int vector); - -static inline void send_IPI_mask(cpumask_t mask, int vector) -{ - send_IPI_mask_sequence(mask, vector); -} - -#endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/mach-es7000/mach_ipi.h b/xen/include/asm-x86/mach_ipi.h similarity index 52% rename from xen/include/asm-x86/mach-es7000/mach_ipi.h rename to xen/include/asm-x86/mach_ipi.h index c487589d94..20936c8df0 100644 --- a/xen/include/asm-x86/mach-es7000/mach_ipi.h +++ b/xen/include/asm-x86/mach_ipi.h @@ -1,11 +1,11 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H +#include + +void send_IPI_mask_bitmask(cpumask_t mask, int vector); void send_IPI_mask_sequence(cpumask_t mask, int vector); -static inline void send_IPI_mask(cpumask_t mask, int vector) -{ - send_IPI_mask_sequence(mask, vector); -} +#define send_IPI_mask (genapic->send_ipi_mask) #endif /* __ASM_MACH_IPI_H */ diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h index f05c5feb0e..f23b915873 100644 --- a/xen/include/asm-x86/smp.h +++ b/xen/include/asm-x86/smp.h @@ -74,16 +74,11 @@ static inline int num_booting_cpus(void) #ifdef CONFIG_X86_LOCAL_APIC -#ifdef APIC_DEFINITION -extern int hard_smp_processor_id(void); -#else -#include static inline int hard_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID)); } -#endif static __inline int logical_smp_processor_id(void) { From 6daae768eb961c0d1acaf0d809cfa20f17cce59e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 3 Apr 2006 17:48:39 +0100 Subject: [PATCH 059/151] Remove some dead code from the consoled client. Signed-off-by: Anthony Liguori --- tools/console/client/main.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tools/console/client/main.c b/tools/console/client/main.c index aba35ec2c6..a43ee26463 100644 --- a/tools/console/client/main.c +++ b/tools/console/client/main.c @@ -36,7 +36,6 @@ #include #include -#include "xenctrl.h" #include "xs.h" #define ESCAPE_CHARACTER 0x1d @@ -92,7 +91,7 @@ static void restore_term(int fd, struct termios *old) tcsetattr(fd, TCSAFLUSH, old); } -static int console_loop(int xc_handle, domid_t domid, int fd) +static int console_loop(int fd) { int ret; @@ -161,7 +160,6 @@ int main(int argc, char **argv) { struct termios attr; int domid; - int xc_handle; char *sopt = "h"; int ch; int opt_ind=0; @@ -206,11 +204,6 @@ int main(int argc, char **argv) err(errno, "Could not contact XenStore"); } - xc_handle = xc_interface_open(); - if (xc_handle == -1) { - err(errno, "xc_interface_open()"); - } - signal(SIGTERM, sighandler); path = xs_get_domain_path(xs, domid); @@ -260,7 +253,7 @@ int main(int argc, char **argv) free(path); init_term(STDIN_FILENO, &attr); - console_loop(xc_handle, domid, spty); + console_loop(spty); restore_term(STDIN_FILENO, &attr); return 0; From d2a5e52e8c2b74eb2e6cc317b1add7941416c90d Mon Sep 17 00:00:00 2001 From: "tkuik@tkuik-lnx2.cisco.com" Date: Mon, 3 Apr 2006 18:23:00 +0100 Subject: [PATCH 060/151] Allow a domain other than Domain-0 to be a backend. Signed-off-by: Tim Kuik tkuik@cisco.com --- tools/python/xen/xend/server/DevController.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 6faadeb24e..0424e89ed7 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -85,6 +85,13 @@ class DevController: front) import xen.xend.XendDomain + xd = xen.xend.XendDomain.instance() + backdom_name = sxp.child_value(config, 'backend') + if backdom_name is None: + backdom = xen.xend.XendDomain.PRIV_DOMAIN + else: + bd = xd.domain_lookup_by_name_nr(backdom_name) + backdom = bd.getDomid() count = 0 while True: t = xstransact() @@ -112,9 +119,13 @@ class DevController: t.mkdir(backpath) t.set_permissions(backpath, - {'dom': xen.xend.XendDomain.PRIV_DOMAIN }, + {'dom': backdom }, {'dom' : self.vm.getDomid(), 'read' : True }) + t.mkdir(frontpath) + t.set_permissions(frontpath, + {'dom': self.vm.getDomid()}, + {'dom': backdom, 'read': True}) t.write2(frontpath, front) t.write2(backpath, back) From ea0ce2d4397e1efba60b7f30d422a6649036f266 Mon Sep 17 00:00:00 2001 From: "mip@xencore04.1virtual.net" Date: Mon, 3 Apr 2006 18:28:54 +0100 Subject: [PATCH 061/151] Improve pygrub error reporting when opening ext2 fs is not possible As reported in the thread: http://lists.xensource.com/archives/html/xen-users/2006-03/msg00721.html, pygrub does not open ext2 file systems in partitioned images or sub partitions on e.g. CentOS/RHEL 4, because e2fsprogs ext2fs_open does not support an offset into the file to be opened. With this patch, the error is correctly reported instead of a generic "unable to open file" (and leaving the user searching in the dark). Signed-off-by: Michael Paesold --- tools/pygrub/src/fsys/ext2/ext2module.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/pygrub/src/fsys/ext2/ext2module.c b/tools/pygrub/src/fsys/ext2/ext2module.c index decf1ad652..63d20f2983 100644 --- a/tools/pygrub/src/fsys/ext2/ext2module.c +++ b/tools/pygrub/src/fsys/ext2/ext2module.c @@ -213,7 +213,9 @@ ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs) int flags = 0, superblock = 0, offset = 0, err; unsigned int block_size = 0; ext2_filsys efs; +#ifdef HAVE_EXT2FS_OPEN2 char offsetopt[30]; +#endif if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", kwlist, &name, &flags, &superblock, @@ -225,19 +227,24 @@ ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs) return NULL; } +#ifdef HAVE_EXT2FS_OPEN2 if (offset != 0) { snprintf(offsetopt, 29, "offset=%d", offset); } -#ifdef HAVE_EXT2FS_OPEN2 err = ext2fs_open2(name, offsetopt, flags, superblock, block_size, unix_io_manager, &efs); #else + if (offset != 0) { + PyErr_SetString(PyExc_ValueError, "offset argument not supported"); + return NULL; + } + err = ext2fs_open(name, flags, superblock, block_size, unix_io_manager, &efs); #endif if (err) { - PyErr_SetString(PyExc_ValueError, "unable to open file"); + PyErr_SetString(PyExc_ValueError, "unable to open filesystem"); return NULL; } From 15b869518465e5d3682336e04129e8a4021dc19a Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 3 Apr 2006 18:32:43 +0100 Subject: [PATCH 062/151] The attached patch fixes a race condition that occurs if after the backend has been removed there are still requests pending. This patch flushed all the pending requests. Signed-off-by: Stefan Berger --- linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index 14d6feb75e..6e118e7b24 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -55,6 +55,7 @@ static int tpmback_remove(struct xenbus_device *dev) be->backend_watch.node = NULL; } if (be->tpmif) { + vtpm_release_packets(be->tpmif, 0); tpmif_put(be->tpmif); be->tpmif = NULL; } From d0263f0fa43f5fc7855cf4ba5687f58f670ced06 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 3 Apr 2006 18:39:21 +0100 Subject: [PATCH 063/151] Fix cpus string parsing, wrt use of ^ to remove elements. Patch from Satoshi Uchida . Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomainInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 43f96e3d3c..1fc9137e40 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -333,7 +333,7 @@ def parseConfig(config): else: # remove this element from the list if c[0] == '^': - cpus = [x for x in cpus if x != int(c[1])] + cpus = [x for x in cpus if x != int(c[1:])] else: cpus.append(int(c)) From 2df295f268c5a84b08f9d2733836b5e8f82da205 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 3 Apr 2006 23:57:42 +0100 Subject: [PATCH 064/151] Lookup backend by name _or_id_. This is important for domain 0, for example! Signed-off-by: Ewan Mellor --- tools/python/xen/xend/server/DevController.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 0424e89ed7..71c54596f5 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -90,7 +90,7 @@ class DevController: if backdom_name is None: backdom = xen.xend.XendDomain.PRIV_DOMAIN else: - bd = xd.domain_lookup_by_name_nr(backdom_name) + bd = xd.domain_lookup_by_name_or_id_nr(backdom_name) backdom = bd.getDomid() count = 0 while True: From af37573f2c64cec3f5330f8fe7c39a1aa29737ff Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 09:53:53 +0100 Subject: [PATCH 065/151] Build a few more common network options into the i386 -xen kernel. Signed-off-by: Keir Fraser --- buildconfigs/linux-defconfig_xen_x86_32 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index a1c6741c96..bce7cf92c2 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -292,11 +292,11 @@ CONFIG_NET=y # Networking options # # CONFIG_NETDEBUG is not set -CONFIG_PACKET=m +CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_UNIX=m +CONFIG_UNIX=y CONFIG_XFRM=y -CONFIG_XFRM_USER=m +CONFIG_XFRM_USER=y CONFIG_NET_KEY=m CONFIG_INET=y CONFIG_IP_MULTICAST=y From c0693d2c6e8800a274b280220254c42eafd2aecd Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Tue, 4 Apr 2006 11:08:20 +0100 Subject: [PATCH 066/151] Workaround bug in xmlrpclib's string escaping. That library outputs invalid UTF-8 if given a string containing high-bit characters, so instead pass in Unicode strings, for which the escaping is correct. This fixes a bug seen when the dmesg of a machine contains high bit characters, but I'm sure there are other ways in which it might be triggered. Signed-off-by: Ewan Mellor --- tools/python/xen/util/xmlrpclib2.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index c0f769f6f2..65aa49ced5 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -20,6 +20,8 @@ An enhanced XML-RPC client/server interface for Python. """ +import types + from httplib import HTTPConnection, HTTP from xmlrpclib import Transport from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler @@ -77,6 +79,15 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): else: response = self._dispatch(method, params) + # Convert strings to unicode strings so that they are escaped + # properly by xmlrpclib. We use latin-1 here, but any + # ASCII-compatible scheme would do -- we just care about getting + # the bytes across the wire. + # Any message handler that actually cares about the charset in + # use should be returning Unicode strings. + if isinstance(response, types.StringType): + response = unicode(response, 'iso-8859-1') + response = (response,) response = xmlrpclib.dumps(response, methodresponse=1, From 295b4af4a1d4869f6b9990c4312a4397bf9429d3 Mon Sep 17 00:00:00 2001 From: "sos22@douglas.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 14:04:32 +0100 Subject: [PATCH 067/151] fix mfn check of gnttab_transfer(). Signed-off-by: Steven Smith, sos22@cam.ac.uk From: Isaku Yamahata --- xen/common/grant_table.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index a45e87a99d..3c2b46ccf0 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -618,8 +618,10 @@ gnttab_transfer( return -EFAULT; } + mfn = gmfn_to_mfn(d, gop.mfn); + /* Check the passed page frame for basic validity. */ - if ( unlikely(!mfn_valid(gop.mfn)) ) + if ( unlikely(!mfn_valid(mfn)) ) { DPRINTK("gnttab_transfer: out-of-range %lx\n", (unsigned long)gop.mfn); @@ -627,7 +629,6 @@ gnttab_transfer( goto copyback; } - mfn = gmfn_to_mfn(d, gop.mfn); page = mfn_to_page(mfn); if ( unlikely(IS_XEN_HEAP_FRAME(page)) ) { From c8a220e4f7659f1824ee6c4e426aed745468f59c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 15:00:41 +0100 Subject: [PATCH 068/151] Simplify the Xen genapic code. Many genapic hooks have been replaced with unconditional static 'sane' implementations. Functions relating to interrupt/IPI delivery have been grouped into two sets: physical delivery and logical-flat delivery. All subarchitectures use physical delivery except the basic default subarchitecture. The main behavioural changes are: 1. Summit no longer uses logical-clustered delivery mode 2. Physical mode no longer makes any pretence to set the LDR sanely. We never deliver interrupts in logical mode so this really should not matter. 3. Sanity checking of phys_cpu_present_map is enabled for all subarchitectures. Really we should have a sane set of APIC IDs in the system, as we rely on them for physical delivery mode. 4. We enable 'bigsmp' mode on any system with more than eight CPUs. The previous xAPIC check was unnecessary, since our bigsmp mode uses physical delivery, not logical-clustered. This all obviously needs testing on some big systems. Signed-off-by: Keir Fraser --- xen/arch/x86/apic.c | 6 +- xen/arch/x86/cpu/common.c | 11 ++ xen/arch/x86/genapic/Makefile | 1 + xen/arch/x86/genapic/bigsmp.c | 8 +- xen/arch/x86/genapic/default.c | 4 +- xen/arch/x86/genapic/delivery.c | 68 +++++++ xen/arch/x86/genapic/es7000.c | 4 +- xen/arch/x86/genapic/summit.c | 4 +- xen/arch/x86/io_apic.c | 6 +- xen/arch/x86/mpparse.c | 27 +-- xen/arch/x86/nmi.c | 4 +- xen/arch/x86/smp.c | 26 +-- xen/arch/x86/smpboot.c | 2 +- xen/arch/x86/x86_32/entry.S | 2 +- xen/include/asm-x86/apicdef.h | 1 + xen/include/asm-x86/genapic.h | 81 ++++---- xen/include/asm-x86/ipi.h | 8 + xen/include/asm-x86/mach-bigsmp/mach_apic.h | 138 ------------- xen/include/asm-x86/mach-default/mach_apic.h | 110 ----------- xen/include/asm-x86/mach-es7000/mach_apic.h | 185 ------------------ xen/include/asm-x86/mach-generic/mach_apic.h | 79 ++++++-- xen/include/asm-x86/mach-summit/mach_apic.h | 167 ---------------- .../asm-x86/mach-summit/mach_mpparse.h | 2 - xen/include/asm-x86/mach_ipi.h | 11 -- 24 files changed, 232 insertions(+), 723 deletions(-) create mode 100644 xen/arch/x86/genapic/delivery.c create mode 100644 xen/include/asm-x86/ipi.h delete mode 100644 xen/include/asm-x86/mach-bigsmp/mach_apic.h delete mode 100644 xen/include/asm-x86/mach-default/mach_apic.h delete mode 100644 xen/include/asm-x86/mach-es7000/mach_apic.h delete mode 100644 xen/include/asm-x86/mach-summit/mach_apic.h delete mode 100644 xen/include/asm-x86/mach_ipi.h diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 31da2fdbd5..a2a955bdc6 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -657,9 +657,10 @@ void __init init_apic_mappings(void) * zeroes page to simulate the local APIC and another * one for the IO-APIC. */ - if (!smp_found_config && detect_init_APIC()) + if (!smp_found_config && detect_init_APIC()) { apic_phys = __pa(alloc_xenheap_page()); - else + memset(__va(apic_phys), 0, PAGE_SIZE); + } else apic_phys = mp_lapic_addr; set_fixmap_nocache(FIX_APIC_BASE, apic_phys); @@ -693,6 +694,7 @@ void __init init_apic_mappings(void) } else { fake_ioapic_page: ioapic_phys = __pa(alloc_xenheap_page()); + memset(__va(ioapic_phys), 0, PAGE_SIZE); } set_fixmap_nocache(idx, ioapic_phys); apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n", diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index beae3f5925..cfcae8cb85 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -427,6 +427,17 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_HT +/* cpuid returns the value latched in the HW at reset, not the APIC ID + * register's value. For any box whose BIOS changes APIC IDs, like + * clustered APIC systems, we must use hard_smp_processor_id. + * + * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. + */ +static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) +{ + return hard_smp_processor_id() >> index_msb; +} + void __devinit detect_ht(struct cpuinfo_x86 *c) { u32 eax, ebx, ecx, edx; diff --git a/xen/arch/x86/genapic/Makefile b/xen/arch/x86/genapic/Makefile index 4220d8f7fe..ea51ead30a 100644 --- a/xen/arch/x86/genapic/Makefile +++ b/xen/arch/x86/genapic/Makefile @@ -2,6 +2,7 @@ include $(BASEDIR)/Rules.mk obj-y += bigsmp.o obj-y += default.o +obj-y += delivery.o obj-y += es7000.o obj-y += es7000plat.o obj-y += probe.o diff --git a/xen/arch/x86/genapic/bigsmp.c b/xen/arch/x86/genapic/bigsmp.c index 4338e5765e..ae714a8282 100644 --- a/xen/arch/x86/genapic/bigsmp.c +++ b/xen/arch/x86/genapic/bigsmp.c @@ -1,7 +1,3 @@ -/* - * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. - * Drives the local APIC in "clustered mode". - */ #include #include #include @@ -13,8 +9,6 @@ #include #include #include -#include -#include #include static int dmi_bigsmp; /* can be set by dmi scanners */ @@ -52,5 +46,5 @@ static __init int probe_bigsmp(void) struct genapic apic_bigsmp = { APIC_INIT("bigsmp", probe_bigsmp), - .send_ipi_mask = send_IPI_mask_sequence + GENAPIC_PHYS }; diff --git a/xen/arch/x86/genapic/default.c b/xen/arch/x86/genapic/default.c index a7403922bb..0e766937fc 100644 --- a/xen/arch/x86/genapic/default.c +++ b/xen/arch/x86/genapic/default.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include /* should be called last. */ @@ -24,5 +22,5 @@ static __init int probe_default(void) struct genapic apic_default = { APIC_INIT("default", probe_default), - .send_ipi_mask = send_IPI_mask_bitmask + GENAPIC_FLAT }; diff --git a/xen/arch/x86/genapic/delivery.c b/xen/arch/x86/genapic/delivery.c new file mode 100644 index 0000000000..e343220f73 --- /dev/null +++ b/xen/arch/x86/genapic/delivery.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + + +/* + * LOGICAL FLAT DELIVERY MODE (multicast via bitmask to <= 8 logical APIC IDs). + */ + +void init_apic_ldr_flat(void) +{ + unsigned long val; + + apic_write_around(APIC_DFR, APIC_DFR_FLAT); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); + apic_write_around(APIC_LDR, val); +} + +void clustered_apic_check_flat(void) +{ + printk("Enabling APIC mode: Flat. Using %d I/O APICs\n", nr_ioapics); +} + +cpumask_t target_cpus_flat(void) +{ + return cpu_online_map; +} + +unsigned int cpu_mask_to_apicid_flat(cpumask_t cpumask) +{ + return cpus_addr(cpumask)[0]; +} + + +/* + * PHYSICAL DELIVERY MODE (unicast to physical APIC IDs). + */ + +void init_apic_ldr_phys(void) +{ + unsigned long val; + apic_write_around(APIC_DFR, APIC_DFR_FLAT); + /* A dummy logical ID should be fine. We only deliver in phys mode. */ + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + apic_write_around(APIC_LDR, val); +} + +void clustered_apic_check_phys(void) +{ + printk("Enabling APIC mode: Phys. Using %d I/O APICs\n", nr_ioapics); +} + +cpumask_t target_cpus_phys(void) +{ + /* IRQs will get bound more accurately later. */ + return cpumask_of_cpu(0); +} + +unsigned int cpu_mask_to_apicid_phys(cpumask_t cpumask) +{ + /* As we are using single CPU as destination, pick only one CPU here */ + return cpu_physical_id(first_cpu(cpumask)); +} diff --git a/xen/arch/x86/genapic/es7000.c b/xen/arch/x86/genapic/es7000.c index 37c959bf4c..09228f7dea 100644 --- a/xen/arch/x86/genapic/es7000.c +++ b/xen/arch/x86/genapic/es7000.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include static __init int probe_es7000(void) @@ -25,5 +23,5 @@ static __init int probe_es7000(void) struct genapic apic_es7000 = { APIC_INIT("es7000", probe_es7000), - .send_ipi_mask = send_IPI_mask_sequence + GENAPIC_PHYS }; diff --git a/xen/arch/x86/genapic/summit.c b/xen/arch/x86/genapic/summit.c index acf191acfc..837a5ad85d 100644 --- a/xen/arch/x86/genapic/summit.c +++ b/xen/arch/x86/genapic/summit.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include static __init int probe_summit(void) @@ -24,5 +22,5 @@ static __init int probe_summit(void) struct genapic apic_summit = { APIC_INIT("summit", probe_summit), - .send_ipi_mask = send_IPI_mask_sequence + GENAPIC_PHYS }; diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index e71603c125..18d8ed961c 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -1736,8 +1736,10 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) spin_unlock_irqrestore(&ioapic_lock, flags); /* Sanity check */ - if (reg_00.bits.ID != apic_id) - panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); + if (reg_00.bits.ID != apic_id) { + printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic); + return -1; + } } apic_printk(APIC_VERBOSE, KERN_INFO diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c index 2df055f33a..3a53d91fd8 100644 --- a/xen/arch/x86/mpparse.c +++ b/xen/arch/x86/mpparse.c @@ -35,7 +35,7 @@ /* Have we found an MP table */ int smp_found_config; -unsigned int __initdata maxcpus = NR_CPUS; +unsigned int __devinitdata maxcpus = NR_CPUS; #ifdef CONFIG_HOTPLUG_CPU #define CPU_HOTPLUG_ENABLED (1) @@ -226,16 +226,11 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m) num_processors++; if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) { - switch (boot_cpu_data.x86_vendor) { - case X86_VENDOR_INTEL: - if (!APIC_XAPIC(ver)) { - def_to_bigsmp = 0; - break; - } - /* If P4 and above fall through */ - case X86_VENDOR_AMD: - def_to_bigsmp = 1; - } + /* + * No need for processor or APIC checks: physical delivery + * (bigsmp) mode should always work. + */ + def_to_bigsmp = 1; } bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; } @@ -916,6 +911,7 @@ void __init mp_register_ioapic ( u32 gsi_base) { int idx = 0; + int tmpid; if (nr_ioapics >= MAX_IO_APICS) { printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " @@ -936,9 +932,14 @@ void __init mp_register_ioapic ( set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 < 15)) - mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id); + tmpid = io_apic_get_unique_id(idx, id); else - mp_ioapics[idx].mpc_apicid = id; + tmpid = id; + if (tmpid == -1) { + nr_ioapics--; + return; + } + mp_ioapics[idx].mpc_apicid = tmpid; mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); /* diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index 0ba9a9e826..fe869222dc 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -431,14 +431,14 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs) */ static void do_nmi_trigger(unsigned char key) { - u32 id = apic_read(APIC_ID); + u32 id = GET_APIC_ID(apic_read(APIC_ID)); printk("Triggering NMI on APIC ID %x\n", id); local_irq_disable(); apic_wait_icr_idle(); apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); - apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_INT_ASSERT); + apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_PHYSICAL); local_irq_enable(); } diff --git a/xen/arch/x86/smp.c b/xen/arch/x86/smp.c index f94ad00517..60d0f3d78e 100644 --- a/xen/arch/x86/smp.c +++ b/xen/arch/x86/smp.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include /* @@ -67,7 +67,7 @@ static inline int __prepare_ICR (unsigned int shortcut, int vector) { - return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; + return APIC_DM_FIXED | shortcut | vector; } static inline int __prepare_ICR2 (unsigned int mask) @@ -85,7 +85,7 @@ static inline void check_IPI_mask(cpumask_t cpumask) ASSERT(!cpus_empty(cpumask)); } -void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) +void send_IPI_mask_flat(cpumask_t cpumask, int vector) { unsigned long mask = cpus_addr(cpumask)[0]; unsigned long cfg; @@ -99,18 +99,18 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) * Wait for idle. */ apic_wait_icr_idle(); - + /* * prepare target chip field */ cfg = __prepare_ICR2(mask); apic_write_around(APIC_ICR2, cfg); - + /* * program the ICR */ - cfg = __prepare_ICR(0, vector); - + cfg = __prepare_ICR(0, vector) | APIC_DEST_LOGICAL; + /* * Send the IPI. The write to APIC_ICR fires this off. */ @@ -119,7 +119,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector) local_irq_restore(flags); } -void send_IPI_mask_sequence(cpumask_t mask, int vector) +void send_IPI_mask_phys(cpumask_t mask, int vector) { unsigned long cfg, flags; unsigned int query_cpu; @@ -140,18 +140,18 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector) * Wait for idle. */ apic_wait_icr_idle(); - + /* * prepare target chip field */ - cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu)); + cfg = __prepare_ICR2(cpu_physical_id(query_cpu)); apic_write_around(APIC_ICR2, cfg); - + /* * program the ICR */ - cfg = __prepare_ICR(0, vector); - + cfg = __prepare_ICR(0, vector) | APIC_DEST_PHYSICAL; + /* * Send the IPI. The write to APIC_ICR fires this off. */ diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 3a35ca339e..8cb7345bc3 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -1094,7 +1094,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID)) continue; - if (!check_apicid_present(bit)) + if (!check_apicid_present(apicid)) continue; if (max_cpus <= cpucount+1) continue; diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index ff2a7991f3..b19796bbac 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -561,7 +561,7 @@ defer_nmi: testl $APIC_ICR_BUSY,%ebx jnz 1b # __send_IPI_shortcut(APIC_DEST_SELF, TRAP_deferred_nmi) - movl $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_LOGICAL | \ + movl $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_PHYSICAL | \ TRAP_deferred_nmi),%ss:APIC_ICR(%eax) jmp restore_all_xen #endif /* !CONFIG_X86_SUPERVISOR_MODE_KERNEL */ diff --git a/xen/include/asm-x86/apicdef.h b/xen/include/asm-x86/apicdef.h index 81bb2b84cb..272ed8c08c 100644 --- a/xen/include/asm-x86/apicdef.h +++ b/xen/include/asm-x86/apicdef.h @@ -62,6 +62,7 @@ #define APIC_INT_ASSERT 0x04000 #define APIC_ICR_BUSY 0x01000 #define APIC_DEST_LOGICAL 0x00800 +#define APIC_DEST_PHYSICAL 0x00000 #define APIC_DM_FIXED 0x00000 #define APIC_DM_LOWEST 0x00100 #define APIC_DM_SMI 0x00200 diff --git a/xen/include/asm-x86/genapic.h b/xen/include/asm-x86/genapic.h index 751e1dfc28..210ff6ee2d 100644 --- a/xen/include/asm-x86/genapic.h +++ b/xen/include/asm-x86/genapic.h @@ -21,27 +21,6 @@ struct genapic { char *name; int (*probe)(void); - int (*apic_id_registered)(void); - cpumask_t (*target_cpus)(void); - int int_delivery_mode; - int int_dest_mode; - int ESR_DISABLE; - int apic_destination_logical; - unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); - unsigned long (*check_apicid_present)(int apicid); - int no_balance_irq; - void (*init_apic_ldr)(void); - physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); - - void (*clustered_apic_check)(void); - int (*apicid_to_node)(int logical_apicid); - int (*cpu_to_logical_apicid)(int cpu); - int (*cpu_present_to_apicid)(int mps_cpu); - physid_mask_t (*apicid_to_cpu_present)(int phys_apicid); - int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); - void (*enable_apic_mode)(void); - u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb); - /* When one of the next two hooks returns 1 the genapic is switched to this. Essentially they are additional probe functions. */ @@ -49,10 +28,14 @@ struct genapic { char *productid); int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); + /* Interrupt delivery parameters ('physical' vs. 'logical flat'). */ + int int_delivery_mode; + int int_dest_mode; + void (*init_apic_ldr)(void); + void (*clustered_apic_check)(void); + cpumask_t (*target_cpus)(void); unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); - - /* ipi */ - void (*send_ipi_mask)(cpumask_t mask, int vector); + void (*send_IPI_mask)(cpumask_t mask, int vector); }; #define APICFUNC(x) .x = x @@ -60,29 +43,37 @@ struct genapic { #define APIC_INIT(aname, aprobe) \ .name = aname, \ .probe = aprobe, \ - .int_delivery_mode = INT_DELIVERY_MODE, \ - .int_dest_mode = INT_DEST_MODE, \ - .no_balance_irq = NO_BALANCE_IRQ, \ - .ESR_DISABLE = esr_disable, \ - .apic_destination_logical = APIC_DEST_LOGICAL, \ - APICFUNC(apic_id_registered), \ - APICFUNC(target_cpus), \ - APICFUNC(check_apicid_used), \ - APICFUNC(check_apicid_present), \ - APICFUNC(init_apic_ldr), \ - APICFUNC(ioapic_phys_id_map), \ - APICFUNC(clustered_apic_check), \ - APICFUNC(apicid_to_node), \ - APICFUNC(cpu_to_logical_apicid), \ - APICFUNC(cpu_present_to_apicid), \ - APICFUNC(apicid_to_cpu_present), \ - APICFUNC(check_phys_apicid_present), \ APICFUNC(mps_oem_check), \ - APICFUNC(cpu_mask_to_apicid), \ - APICFUNC(acpi_madt_oem_check), \ - APICFUNC(enable_apic_mode), \ - APICFUNC(phys_pkg_id) + APICFUNC(acpi_madt_oem_check) extern struct genapic *genapic; +void init_apic_ldr_flat(void); +void clustered_apic_check_flat(void); +cpumask_t target_cpus_flat(void); +unsigned int cpu_mask_to_apicid_flat(cpumask_t cpumask); +void send_IPI_mask_flat(cpumask_t mask, int vector); +#define GENAPIC_FLAT \ + .int_delivery_mode = dest_LowestPrio, \ + .int_dest_mode = 1 /* logical delivery */, \ + .init_apic_ldr = init_apic_ldr_flat, \ + .clustered_apic_check = clustered_apic_check_flat, \ + .target_cpus = target_cpus_flat, \ + .cpu_mask_to_apicid = cpu_mask_to_apicid_flat, \ + .send_IPI_mask = send_IPI_mask_flat + +void init_apic_ldr_phys(void); +void clustered_apic_check_phys(void); +cpumask_t target_cpus_phys(void); +unsigned int cpu_mask_to_apicid_phys(cpumask_t cpumask); +void send_IPI_mask_phys(cpumask_t mask, int vector); +#define GENAPIC_PHYS \ + .int_delivery_mode = dest_Fixed, \ + .int_dest_mode = 0 /* physical delivery */, \ + .init_apic_ldr = init_apic_ldr_phys, \ + .clustered_apic_check = clustered_apic_check_phys, \ + .target_cpus = target_cpus_phys, \ + .cpu_mask_to_apicid = cpu_mask_to_apicid_phys, \ + .send_IPI_mask = send_IPI_mask_phys + #endif diff --git a/xen/include/asm-x86/ipi.h b/xen/include/asm-x86/ipi.h new file mode 100644 index 0000000000..da8c94031f --- /dev/null +++ b/xen/include/asm-x86/ipi.h @@ -0,0 +1,8 @@ +#ifndef __ASM_IPI_H +#define __ASM_IPI_H + +#include + +#define send_IPI_mask (genapic->send_IPI_mask) + +#endif /* __ASM_IPI_H */ diff --git a/xen/include/asm-x86/mach-bigsmp/mach_apic.h b/xen/include/asm-x86/mach-bigsmp/mach_apic.h deleted file mode 100644 index 4a591053ba..0000000000 --- a/xen/include/asm-x86/mach-bigsmp/mach_apic.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - - -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu]) -#define esr_disable (1) - -static inline int apic_id_registered(void) -{ - return (1); -} - -/* Round robin the irqs amoung the online cpus */ -static inline cpumask_t target_cpus(void) -{ - static unsigned long cpu = NR_CPUS; - do { - if (cpu >= NR_CPUS) - cpu = first_cpu(cpu_online_map); - else - cpu = next_cpu(cpu, cpu_online_map); - } while (cpu >= NR_CPUS); - return cpumask_of_cpu(cpu); -} - -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0 -#define TARGET_CPUS (target_cpus()) -#define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target proc */ -#define NO_BALANCE_IRQ (0) -#define WAKE_SECONDARY_VIA_INIT - - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return (0); -} - -static inline unsigned long check_apicid_present(int bit) -{ - return (1); -} - -static inline unsigned long calculate_ldr(int cpu) -{ - unsigned long val, id; - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - id = xapic_phys_to_log_apicid(cpu); - val |= SET_APIC_LOGICAL_ID(id); - return val; -} - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LDR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write_around(APIC_LDR, val); -} - -static inline void clustered_apic_check(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Physflat", nr_ioapics); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return (0); -} - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < NR_CPUS) - return (int) bios_cpu_apicid[mps_cpu]; - - return BAD_APICID; -} - -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) -{ - return physid_mask_of_physid(phys_apicid); -} - -extern u8 cpu_2_logical_apicid[]; -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - if (cpu >= NR_CPUS) - return BAD_APICID; - return cpu_physical_id(cpu); -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xFFL); -} - -static inline void enable_apic_mode(void) -{ -} - -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return (1); -} - -/* As we are using single CPU as destination, pick only one CPU here */ -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - int cpu; - int apicid; - - cpu = first_cpu(cpumask); - apicid = cpu_to_logical_apicid(cpu); - return apicid; -} - -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-default/mach_apic.h b/xen/include/asm-x86/mach-default/mach_apic.h deleted file mode 100644 index c673ae24bb..0000000000 --- a/xen/include/asm-x86/mach-default/mach_apic.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -#include - -#define APIC_DFR_VALUE (APIC_DFR_FLAT) - -static inline cpumask_t target_cpus(void) -{ -#ifdef CONFIG_SMP - return cpu_online_map; -#else - return cpumask_of_cpu(0); -#endif -} -#define TARGET_CPUS (target_cpus()) - -#define NO_BALANCE_IRQ (0) -#define esr_disable (0) - -#define INT_DELIVERY_MODE dest_LowestPrio -#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return physid_isset(apicid, bitmap); -} - -static inline unsigned long check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LDR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void init_apic_ldr(void) -{ - unsigned long val; - - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); - apic_write_around(APIC_LDR, val); -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) -{ - return phys_map; -} - -static inline void clustered_apic_check(void) -{ - printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Flat", nr_ioapics); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return 0; -} - -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - return 1 << cpu; -} - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < get_physical_broadcast()) - return mps_cpu; - else - return BAD_APICID; -} - -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) -{ - return physid_mask_of_physid(phys_apicid); -} - -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); -} - -static inline int apic_id_registered(void) -{ - return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map); -} - -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - return cpus_addr(cpumask)[0]; -} - -static inline void enable_apic_mode(void) -{ -} - -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-es7000/mach_apic.h b/xen/include/asm-x86/mach-es7000/mach_apic.h deleted file mode 100644 index 86264f01bd..0000000000 --- a/xen/include/asm-x86/mach-es7000/mach_apic.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu]) -#define esr_disable (1) - -static inline int apic_id_registered(void) -{ - return (1); -} - -static inline cpumask_t target_cpus(void) -{ -#if defined CONFIG_ES7000_CLUSTERED_APIC - return CPU_MASK_ALL; -#else - return cpumask_of_cpu(smp_processor_id()); -#endif -} -#define TARGET_CPUS (target_cpus()) - -#if defined CONFIG_ES7000_CLUSTERED_APIC -#define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -#define INT_DELIVERY_MODE (dest_LowestPrio) -#define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */ -#define NO_BALANCE_IRQ (1) -#undef WAKE_SECONDARY_VIA_INIT -#define WAKE_SECONDARY_VIA_MIP -#else -#define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target procs */ -#define NO_BALANCE_IRQ (0) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0x0 -#define WAKE_SECONDARY_VIA_INIT -#endif - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} -static inline unsigned long check_apicid_present(int bit) -{ - return physid_isset(bit, phys_cpu_present_map); -} - -#define apicid_cluster(apicid) (apicid & 0xF0) - -static inline unsigned long calculate_ldr(int cpu) -{ - unsigned long id; - id = xapic_phys_to_log_apicid(cpu); - return (SET_APIC_LOGICAL_ID(id)); -} - -/* - * Set up the logical destination ID. - * - * Intel recommends to set DFR, LdR and TPR before enabling - * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel - * document number 292116). So here it goes... - */ -static inline void init_apic_ldr(void) -{ - unsigned long val; - int cpu = smp_processor_id(); - - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); - apic_write_around(APIC_LDR, val); -} - -extern void es7000_sw_apic(void); -static inline void enable_apic_mode(void) -{ - es7000_sw_apic(); - return; -} - -extern int apic_version [MAX_APICS]; -static inline void clustered_apic_check(void) -{ - int apic = bios_cpu_apicid[smp_processor_id()]; - printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", - (apic_version[apic] == 0x14) ? - "Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return 0; -} - - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (!mps_cpu) - return boot_cpu_physical_apicid; - else if (mps_cpu < NR_CPUS) - return (int) bios_cpu_apicid[mps_cpu]; - else - return BAD_APICID; -} - -static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) -{ - static int id = 0; - physid_mask_t mask; - mask = physid_mask_of_physid(id); - ++id; - return mask; -} - -extern u8 cpu_2_logical_apicid[]; -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - if (cpu >= NR_CPUS) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xff); -} - -extern unsigned int boot_cpu_physical_apicid; -static inline int check_phys_apicid_present(int cpu_physical_apicid) -{ - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); - return (1); -} - -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - int num_bits_set; - int cpus_found = 0; - int cpu; - int apicid; - - num_bits_set = cpus_weight(cpumask); - /* Return id to all */ - if (num_bits_set == NR_CPUS) -#if defined CONFIG_ES7000_CLUSTERED_APIC - return 0xFF; -#else - return cpu_to_logical_apicid(0); -#endif - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. - */ - cpu = first_cpu(cpumask); - apicid = cpu_to_logical_apicid(cpu); - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ - printk ("%s: Not a valid mask!\n",__FUNCTION__); -#if defined CONFIG_ES7000_CLUSTERED_APIC - return 0xFF; -#else - return cpu_to_logical_apicid(0); -#endif - } - apicid = new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return cpuid_apic >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-generic/mach_apic.h b/xen/include/asm-x86/mach-generic/mach_apic.h index 1e0f6b9435..1d3ed4dc67 100644 --- a/xen/include/asm-x86/mach-generic/mach_apic.h +++ b/xen/include/asm-x86/mach-generic/mach_apic.h @@ -2,28 +2,40 @@ #define __ASM_MACH_APIC_H #include +#include -#define esr_disable (genapic->ESR_DISABLE) -#define NO_BALANCE_IRQ (genapic->no_balance_irq) +/* ESR was originally disabled in Linux for NUMA-Q. Do we really need to? */ +#define esr_disable (0) + +/* The following are dependent on APIC delivery mode (logical vs. physical). */ #define INT_DELIVERY_MODE (genapic->int_delivery_mode) #define INT_DEST_MODE (genapic->int_dest_mode) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL (genapic->apic_destination_logical) #define TARGET_CPUS (genapic->target_cpus()) -#define apic_id_registered (genapic->apic_id_registered) #define init_apic_ldr (genapic->init_apic_ldr) -#define ioapic_phys_id_map (genapic->ioapic_phys_id_map) #define clustered_apic_check (genapic->clustered_apic_check) -#define apicid_to_node (genapic->apicid_to_node) -#define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) -#define cpu_present_to_apicid (genapic->cpu_present_to_apicid) -#define apicid_to_cpu_present (genapic->apicid_to_cpu_present) -#define check_apicid_present (genapic->check_apicid_present) -#define check_phys_apicid_present (genapic->check_phys_apicid_present) -#define check_apicid_used (genapic->check_apicid_used) #define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) -#define enable_apic_mode (genapic->enable_apic_mode) -#define phys_pkg_id (genapic->phys_pkg_id) + +extern void es7000_sw_apic(void); +static inline void enable_apic_mode(void) +{ + es7000_sw_apic(); + return; +} + +/* No sane NUMA support right now. We should parse ACPI SRAT. */ +static inline int apicid_to_node(int logical_apicid) +{ + return 0; +} + +extern u8 bios_cpu_apicid[]; +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (mps_cpu < NR_CPUS) + return (int)bios_cpu_apicid[mps_cpu]; + else + return BAD_APICID; +} static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *translation_record) @@ -47,4 +59,41 @@ static inline int multi_timer_check(int apic, int irq) extern void generic_bigsmp_probe(void); +/* + * The following functions based around phys_cpu_present_map are disabled in + * some i386 Linux subarchitectures, and in x86_64 'cluster' genapic mode. I'm + * really not sure why, since all local APICs should have distinct physical + * IDs, and we need to know what they are. + */ +static inline int apic_id_registered(void) +{ + return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), + phys_cpu_present_map); +} + +static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) +{ + return phys_map; +} + +static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) +{ + return physid_isset(apicid, bitmap); +} + +static inline unsigned long check_apicid_present(int apicid) +{ + return physid_isset(apicid, phys_cpu_present_map); +} + +static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) +{ + return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); +} + +static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) +{ + return physid_mask_of_physid(phys_apicid); +} + #endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-summit/mach_apic.h b/xen/include/asm-x86/mach-summit/mach_apic.h deleted file mode 100644 index 3ba02dc276..0000000000 --- a/xen/include/asm-x86/mach-summit/mach_apic.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef __ASM_MACH_APIC_H -#define __ASM_MACH_APIC_H - -#include -#include - -#define esr_disable (1) -#define NO_BALANCE_IRQ (0) - -/* In clustered mode, the high nibble of APIC ID is a cluster number. - * The low nibble is a 4-bit bitmap. */ -#define XAPIC_DEST_CPUS_SHIFT 4 -#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) -#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) - -#define APIC_DFR_VALUE (APIC_DFR_CLUSTER) - -static inline cpumask_t target_cpus(void) -{ - /* CPU_MASK_ALL (0xff) has undefined behaviour with - * dest_LowestPrio mode logical clustered apic interrupt routing - * Just start on cpu 0. IRQ balancing will spread load - */ - return cpumask_of_cpu(0); -} -#define TARGET_CPUS (target_cpus()) - -#define INT_DELIVERY_MODE (dest_LowestPrio) -#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ - -static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) -{ - return 0; -} - -/* we don't use the phys_cpu_present_map to indicate apicid presence */ -static inline unsigned long check_apicid_present(int bit) -{ - return 1; -} - -#define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) - -extern u8 bios_cpu_apicid[]; -extern u8 cpu_2_logical_apicid[]; - -static inline void init_apic_ldr(void) -{ - unsigned long val, id; - int i, count; - u8 lid; - u8 my_id = (u8)hard_smp_processor_id(); - u8 my_cluster = (u8)apicid_cluster(my_id); - - /* Create logical APIC IDs by counting CPUs already in cluster. */ - for (count = 0, i = NR_CPUS; --i >= 0; ) { - lid = cpu_2_logical_apicid[i]; - if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster) - ++count; - } - /* We only have a 4 wide bitmap in cluster mode. If a deranged - * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ - BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); - id = my_cluster | (1UL << count); - apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - val |= SET_APIC_LOGICAL_ID(id); - apic_write_around(APIC_LDR, val); -} - -static inline int apic_id_registered(void) -{ - return 1; -} - -static inline void clustered_apic_check(void) -{ - printk("Enabling APIC mode: Summit. Using %d I/O APICs\n", - nr_ioapics); -} - -static inline int apicid_to_node(int logical_apicid) -{ - return logical_apicid >> 5; /* 2 clusterids per CEC */ -} - -/* Mapping from cpu number to logical apicid */ -static inline int cpu_to_logical_apicid(int cpu) -{ - if (cpu >= NR_CPUS) - return BAD_APICID; - return (int)cpu_2_logical_apicid[cpu]; -} - -static inline int cpu_present_to_apicid(int mps_cpu) -{ - if (mps_cpu < NR_CPUS) - return (int)bios_cpu_apicid[mps_cpu]; - else - return BAD_APICID; -} - -static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_id_map) -{ - /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0x0F); -} - -static inline physid_mask_t apicid_to_cpu_present(int apicid) -{ - return physid_mask_of_physid(0); -} - -static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) -{ - return 1; -} - -static inline void enable_apic_mode(void) -{ -} - -static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) -{ - int num_bits_set; - int cpus_found = 0; - int cpu; - int apicid; - - num_bits_set = cpus_weight(cpumask); - /* Return id to all */ - if (num_bits_set == NR_CPUS) - return (int) 0xFF; - /* - * The cpus in the mask must all be on the apic cluster. If are not - * on the same apicid cluster return default value of TARGET_CPUS. - */ - cpu = first_cpu(cpumask); - apicid = cpu_to_logical_apicid(cpu); - while (cpus_found < num_bits_set) { - if (cpu_isset(cpu, cpumask)) { - int new_apicid = cpu_to_logical_apicid(cpu); - if (apicid_cluster(apicid) != - apicid_cluster(new_apicid)){ - printk ("%s: Not a valid mask!\n",__FUNCTION__); - return 0xFF; - } - apicid = apicid | new_apicid; - cpus_found++; - } - cpu++; - } - return apicid; -} - -/* cpuid returns the value latched in the HW at reset, not the APIC ID - * register's value. For any box whose BIOS changes APIC IDs, like - * clustered APIC systems, we must use hard_smp_processor_id. - * - * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. - */ -static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb) -{ - return hard_smp_processor_id() >> index_msb; -} - -#endif /* __ASM_MACH_APIC_H */ diff --git a/xen/include/asm-x86/mach-summit/mach_mpparse.h b/xen/include/asm-x86/mach-summit/mach_mpparse.h index a951babe1d..3553af2fa3 100644 --- a/xen/include/asm-x86/mach-summit/mach_mpparse.h +++ b/xen/include/asm-x86/mach-summit/mach_mpparse.h @@ -1,8 +1,6 @@ #ifndef __ASM_MACH_MPPARSE_H #define __ASM_MACH_MPPARSE_H -#include - extern int use_cyclone; #ifdef CONFIG_X86_SUMMIT_NUMA diff --git a/xen/include/asm-x86/mach_ipi.h b/xen/include/asm-x86/mach_ipi.h deleted file mode 100644 index 20936c8df0..0000000000 --- a/xen/include/asm-x86/mach_ipi.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_MACH_IPI_H -#define __ASM_MACH_IPI_H - -#include - -void send_IPI_mask_bitmask(cpumask_t mask, int vector); -void send_IPI_mask_sequence(cpumask_t mask, int vector); - -#define send_IPI_mask (genapic->send_ipi_mask) - -#endif /* __ASM_MACH_IPI_H */ From b9d11c5788280ab4530648d8cfcf8b4bbc32ea20 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 15:05:17 +0100 Subject: [PATCH 069/151] HVM patch to add pio IOREQ_WRITE OVERLAP/REPZ support in hvm io.c hvm_pio_assist(). Also, cleaned up a bit of duplicate code in the functions. Simple guest tests (ide pio) pass now for overlapped/rep write operations. Signed-off-by: Tom Woller Signed-off-by: Mats Petersson --- xen/arch/x86/hvm/io.c | 55 ++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 893dd68ce5..fd9ff611df 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -365,29 +365,42 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p, unsigned long old_eax; int sign = p->df ? -1 : 1; - if (p->dir == IOREQ_WRITE) { - if (p->pdata_valid) { + if (p->pdata_valid || (mmio_opp->flags & OVERLAP)) { + if (mmio_opp->flags & REPZ) + regs->ecx -= p->count; + if (p->dir == IOREQ_READ) { + regs->edi += sign * p->count * p->size; + + if (mmio_opp->flags & OVERLAP) { + /* + * If we are doing in IN and it's overlapping a page boundary, + * we need to copy the data back to user's page with hvm_copy. + * Note that overlap * can only be set with paging enabled, so + * we don't need to worry about * real-mode stuff. + */ + unsigned long addr; + { + /* + * We completely ignore segment registers here - + * it's not a good idea. We also may use upper bits + * in edi when in 16-bit real/protected mode. + * We really need to get the actual address back from + * the arch-dependant HVM portion. + */ + struct vcpu *v = current; + if (hvm_realmode(v)) + __hvm_bug(regs); + } + addr = regs->edi; + if (sign > 0) + addr -= p->size; + hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); + } + } else regs->esi += sign * p->count * p->size; - if (mmio_opp->flags & REPZ) - regs->ecx -= p->count; - } + } else { - if (mmio_opp->flags & OVERLAP) { - unsigned long addr; - - regs->edi += sign * p->count * p->size; - if (mmio_opp->flags & REPZ) - regs->ecx -= p->count; - - addr = regs->edi; - if (sign > 0) - addr -= p->size; - hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); - } else if (p->pdata_valid) { - regs->edi += sign * p->count * p->size; - if (mmio_opp->flags & REPZ) - regs->ecx -= p->count; - } else { + if (p->dir == IOREQ_READ) { old_eax = regs->eax; switch (p->size) { case 1: From c82d714c9c5f9a5f924e21f06c436d8794c3eca4 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 15:06:38 +0100 Subject: [PATCH 070/151] With the standard (XEN) prefix and the setting of 8 words per line, stack dumps on i386 came out at 81 characters per line. The change to xen/arch/x86/traps.c makes this 80 (without changing the look on the screen), and the change to xen/drivers/char/console.c arranges for soft line breaks not getting duplicated by hard line breaks, so displaying 80 characters per line doesn't result in a subsequent blank line. From: Jan Beulich Signed-off-by: Keir Fraser --- xen/arch/x86/traps.c | 14 +++++++------- xen/drivers/char/console.c | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 95e44db6d9..2856f75a0c 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -138,13 +138,13 @@ static void show_guest_stack(struct cpu_user_regs *regs) if ( vm86_mode(regs) ) { stack = (unsigned long *)((regs->ss << 4) + (regs->esp & 0xffff)); - printk("Guest stack trace from ss:sp = %04x:%04x (VM86)\n ", + printk("Guest stack trace from ss:sp = %04x:%04x (VM86)\n ", regs->ss, (uint16_t)(regs->esp & 0xffff)); } else { stack = (unsigned long *)regs->esp; - printk("Guest stack trace from "__OP"sp=%p:\n ", stack); + printk("Guest stack trace from "__OP"sp=%p:\n ", stack); } for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) @@ -160,8 +160,8 @@ static void show_guest_stack(struct cpu_user_regs *regs) break; } if ( (i != 0) && ((i % stack_words_per_line) == 0) ) - printk("\n "); - printk("%p ", _p(addr)); + printk("\n "); + printk(" %p", _p(addr)); stack++; } if ( i == 0 ) @@ -257,16 +257,16 @@ void show_stack(struct cpu_user_regs *regs) if ( guest_mode(regs) ) return show_guest_stack(regs); - printk("Xen stack trace from "__OP"sp=%p:\n ", stack); + printk("Xen stack trace from "__OP"sp=%p:\n ", stack); for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) { if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 ) break; if ( (i != 0) && ((i % stack_words_per_line) == 0) ) - printk("\n "); + printk("\n "); addr = *stack++; - printk("%p ", _p(addr)); + printk(" %p", _p(addr)); } if ( i == 0 ) printk("Stack empty."); diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index dc06857007..2755f5e46b 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -200,10 +200,11 @@ static void putchar_console(int c) } else { + if ( xpos >= COLUMNS ) + put_newline(); video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF; video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE; - if ( ++xpos >= COLUMNS ) - put_newline(); + ++xpos; } } From 28efb2481ff9523f1f4acb02219cf54d6594ada5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Apr 2006 15:20:12 +0100 Subject: [PATCH 071/151] We had reports of reboot not working on certain machines (specifically Compaq/HP notebooks), where Linux already has code to deal with that. Apparently that code was either deleted during the original port or got added to Linux after the original port was done. Anyway, this patch adds the respective Linux code (slightly adjusted) to deal with the same systems in Xen. From: Jan Beulich Signed-off-by: Keir Fraser --- xen/arch/x86/Makefile | 1 + xen/arch/x86/domain.c | 82 ---------- xen/arch/x86/shutdown.c | 342 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+), 82 deletions(-) create mode 100644 xen/arch/x86/shutdown.c diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index c7a2e6ae1d..dee62f224a 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -30,6 +30,7 @@ obj-y += nmi.o obj-y += physdev.o obj-y += rwlock.o obj-y += setup.o +obj-y += shutdown.o obj-y += smp.o obj-y += smpboot.o obj-y += string.o diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index ab5b697953..a4e52139bd 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -41,10 +41,6 @@ #include #include -/* opt_noreboot: If true, machine will need manual reset on error. */ -static int opt_noreboot = 0; -boolean_param("noreboot", opt_noreboot); - struct percpu_ctxt { struct vcpu *curr_vcpu; unsigned int dirty_segment_mask; @@ -99,84 +95,6 @@ void startup_cpu_idle_loop(void) reset_stack_and_jump(idle_loop); } -static long no_idt[2]; -static int reboot_mode; - -static inline void kb_wait(void) -{ - int i; - - for ( i = 0; i < 0x10000; i++ ) - if ( (inb_p(0x64) & 0x02) == 0 ) - break; -} - -void __attribute__((noreturn)) __machine_halt(void *unused) -{ - for ( ; ; ) - safe_halt(); -} - -void machine_halt(void) -{ - watchdog_disable(); - console_start_sync(); - smp_call_function(__machine_halt, NULL, 1, 0); - __machine_halt(NULL); -} - -void machine_restart(char * __unused) -{ - int i; - - if ( opt_noreboot ) - { - printk("Reboot disabled on cmdline: require manual reset\n"); - machine_halt(); - } - - watchdog_disable(); - console_start_sync(); - - local_irq_enable(); - - /* Ensure we are the boot CPU. */ - if ( GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid ) - { - smp_call_function((void *)machine_restart, NULL, 1, 0); - for ( ; ; ) - safe_halt(); - } - - /* - * Stop all CPUs and turn off local APICs and the IO-APIC, so - * other OSs see a clean IRQ state. - */ - smp_send_stop(); - disable_IO_APIC(); - hvm_disable(); - - /* Rebooting needs to touch the page at absolute address 0. */ - *((unsigned short *)__va(0x472)) = reboot_mode; - - for ( ; ; ) - { - /* Pulse the keyboard reset line. */ - for ( i = 0; i < 100; i++ ) - { - kb_wait(); - udelay(50); - outb(0xfe,0x64); /* pulse reset low */ - udelay(50); - } - - /* That didn't work - force a triple fault.. */ - __asm__ __volatile__("lidt %0": "=m" (no_idt)); - __asm__ __volatile__("int3"); - } -} - - void dump_pageframe_info(struct domain *d) { struct page_info *page; diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c new file mode 100644 index 0000000000..e3cd61085a --- /dev/null +++ b/xen/arch/x86/shutdown.c @@ -0,0 +1,342 @@ +/****************************************************************************** + * arch/x86/shutdown.c + * + * x86-specific shutdown handling. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* opt_noreboot: If true, machine will need manual reset on error. */ +static int opt_noreboot = 0; +boolean_param("noreboot", opt_noreboot); + +/* reboot_str: comma-separated list of reboot options. */ +static char __initdata reboot_str[10] = ""; +string_param("reboot", reboot_str); + +static long no_idt[2]; +static int reboot_mode; + +static inline void kb_wait(void) +{ + int i; + + for ( i = 0; i < 0x10000; i++ ) + if ( (inb_p(0x64) & 0x02) == 0 ) + break; +} + +void __attribute__((noreturn)) __machine_halt(void *unused) +{ + for ( ; ; ) + safe_halt(); +} + +void machine_halt(void) +{ + watchdog_disable(); + console_start_sync(); + smp_call_function(__machine_halt, NULL, 1, 0); + __machine_halt(NULL); +} + +#ifdef __i386__ + +static int reboot_thru_bios; + +/* The following code and data reboots the machine by switching to real + mode and jumping to the BIOS reset entry point, as if the CPU has + really been reset. The previous version asked the keyboard + controller to pulse the CPU reset line, which is more thorough, but + doesn't work with at least one type of 486 motherboard. It is easy + to stop this code working; hence the copious comments. */ + +static unsigned long long +real_mode_gdt_entries [3] = +{ + 0x0000000000000000ULL, /* Null descriptor */ + 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ + 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ +}; + +static const struct +{ + unsigned short size __attribute__ ((packed)); + unsigned long long * base __attribute__ ((packed)); +} +real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries }, +real_mode_idt = { 0x3ff, NULL }; + + +/* This is 16-bit protected mode code to disable paging and the cache, + switch to real mode and jump to the BIOS reset code. + + The instruction that switches to real mode by writing to CR0 must be + followed immediately by a far jump instruction, which set CS to a + valid value for real mode, and flushes the prefetch queue to avoid + running instructions that have already been decoded in protected + mode. + + Clears all the flags except ET, especially PG (paging), PE + (protected-mode enable) and TS (task switch for coprocessor state + save). Flushes the TLB after paging has been disabled. Sets CD and + NW, to disable the cache on a 486, and invalidates the cache. This + is more like the state of a 486 after reset. I don't know if + something else should be done for other chips. + + More could be done here to set up the registers as if a CPU reset had + occurred; hopefully real BIOSs don't assume much. */ + +static const unsigned char real_mode_switch [] = +{ + 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */ + 0x66, 0x83, 0xe0, 0x11, /* andl $0x00000011,%eax */ + 0x66, 0x0d, 0x00, 0x00, 0x00, 0x60, /* orl $0x60000000,%eax */ + 0x0f, 0x22, 0xc0, /* movl %eax,%cr0 */ + 0x0f, 0x22, 0xd8, /* movl %eax,%cr3 */ + 0x0f, 0x20, 0xc2, /* movl %cr0,%edx */ + 0x66, 0x81, 0xe2, 0x00, 0x00, 0x00, 0x60, /* andl $0x60000000,%edx */ + 0x74, 0x02, /* jz f */ + 0x0f, 0x09, /* wbinvd */ + 0x24, 0x10, /* f: andb $0x10,al */ + 0x0f, 0x22, 0xc0 /* movl %eax,%cr0 */ +}; +#define MAX_LENGTH 0x40 +static const unsigned char jump_to_bios [] = +{ + 0xea, 0xf0, 0xff, 0x00, 0xf0 /* ljmp $0xf000,$0xfff0 */ +}; + +/* + * Switch to real mode and then execute the code + * specified by the code and length parameters. + * We assume that length will aways be less that MAX_LENGTH! + */ +void machine_real_restart(const unsigned char *code, unsigned length) +{ + local_irq_disable(); + + /* Write zero to CMOS register number 0x0f, which the BIOS POST + routine will recognize as telling it to do a proper reboot. (Well + that's what this book in front of me says -- it may only apply to + the Phoenix BIOS though, it's not clear). At the same time, + disable NMIs by setting the top bit in the CMOS address register, + as we're about to do peculiar things to the CPU. */ + + spin_lock(&rtc_lock); + CMOS_WRITE(0x00, 0x8f); + spin_unlock(&rtc_lock); + + /* Identity-map virtual address zero. */ + + map_pages_to_xen(0, 0, 1, __PAGE_HYPERVISOR|MAP_SMALL_PAGES); + set_current(idle_vcpu[0]); + write_ptbase(idle_vcpu[0]); + + /* For the switch to real mode, copy some code to low memory. It has + to be in the first 64k because it is running in 16-bit mode, and it + has to have the same physical and virtual address, because it turns + off paging. Copy it near the end of the first page, out of the way + of BIOS variables. */ + + memcpy((void *)(PAGE_SIZE - sizeof(real_mode_switch) - MAX_LENGTH), + real_mode_switch, sizeof(real_mode_switch)); + memcpy((void *)(PAGE_SIZE - MAX_LENGTH), code, length); + + /* Set up the IDT for real mode. */ + + __asm__ __volatile__("lidt %0": : "m" (real_mode_idt)); + + /* Set up a GDT from which we can load segment descriptors for real + mode. The GDT is not used in real mode; it is just needed here to + prepare the descriptors. */ + + __asm__ __volatile__("lgdt %0": : "m" (real_mode_gdt)); + + /* Load the data segment registers, and thus the descriptors ready for + real mode. The base address of each segment is 0x100, 16 times the + selector value being loaded here. This is so that the segment + registers don't have to be reloaded after switching to real mode: + the values are consistent for real mode operation already. */ + + __asm__ __volatile__ ("\tmov %0,%%ds\n" + "\tmov %0,%%es\n" + "\tmov %0,%%fs\n" + "\tmov %0,%%gs\n" + "\tmov %0,%%ss" + : + : "r" (0x0010)); + + /* Jump to the 16-bit code that we copied earlier. It disables paging + and the cache, switches to real mode, and jumps to the BIOS reset + entry point. */ + + __asm__ __volatile__ ("ljmp $0x0008,%0" + : + : "i" ((void *)(PAGE_SIZE - + sizeof(real_mode_switch) - + MAX_LENGTH))); +} + +#else /* __x86_64__ */ + +#define machine_real_restart(x, y) +#define reboot_thru_bios 0 + +#endif + +void machine_restart(char * __unused) +{ + int i; + + if ( opt_noreboot ) + { + printk("Reboot disabled on cmdline: require manual reset\n"); + machine_halt(); + } + + watchdog_disable(); + console_start_sync(); + + local_irq_enable(); + + /* Ensure we are the boot CPU. */ + if ( GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid ) + { + smp_call_function((void *)machine_restart, NULL, 1, 0); + for ( ; ; ) + safe_halt(); + } + + /* + * Stop all CPUs and turn off local APICs and the IO-APIC, so + * other OSs see a clean IRQ state. + */ + smp_send_stop(); + disable_IO_APIC(); + hvm_disable(); + + /* Rebooting needs to touch the page at absolute address 0. */ + *((unsigned short *)__va(0x472)) = reboot_mode; + + if (reboot_thru_bios <= 0) + { + for ( ; ; ) + { + /* Pulse the keyboard reset line. */ + for ( i = 0; i < 100; i++ ) + { + kb_wait(); + udelay(50); + outb(0xfe,0x64); /* pulse reset low */ + udelay(50); + } + + /* That didn't work - force a triple fault.. */ + __asm__ __volatile__("lidt %0": "=m" (no_idt)); + __asm__ __volatile__("int3"); + } + } + machine_real_restart(jump_to_bios, sizeof(jump_to_bios)); +} + +#ifndef reboot_thru_bios +static int __init set_bios_reboot(struct dmi_system_id *d) +{ + if ( !reboot_thru_bios ) + { + reboot_thru_bios = 1; + printk("%s series board detected. " + "Selecting BIOS-method for reboots.\n", d->ident); + } + return 0; +} + +static struct dmi_system_id __initdata reboot_dmi_table[] = { + { /* Handle problems with rebooting on Dell 1300's */ + .callback = set_bios_reboot, + .ident = "Dell PowerEdge 1300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"), + }, + }, + { /* Handle problems with rebooting on Dell 300's */ + .callback = set_bios_reboot, + .ident = "Dell PowerEdge 300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"), + }, + }, + { /* Handle problems with rebooting on Dell 2400's */ + .callback = set_bios_reboot, + .ident = "Dell PowerEdge 2400", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), + }, + }, + { /* Handle problems with rebooting on HP laptops */ + .callback = set_bios_reboot, + .ident = "HP Compaq Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), + }, + }, + { } +}; +#endif + +static int __init reboot_init(void) +{ + const char *str; + + for ( str = reboot_str; *str != '\0'; str++ ) + { + switch ( *str ) + { + case 'n': /* no reboot */ + opt_noreboot = 1; + break; + case 'w': /* "warm" reboot (no memory testing etc) */ + reboot_mode = 0x1234; + break; + case 'c': /* "cold" reboot (with memory testing etc) */ + reboot_mode = 0x0; + break; +#ifndef reboot_thru_bios + case 'b': /* "bios" reboot by jumping through the BIOS */ + reboot_thru_bios = 1; + break; + case 'h': /* "hard" reboot by toggling RESET and/or crashing the CPU */ + reboot_thru_bios = -1; + break; +#endif + } + if ( (str = strchr(str, ',')) == NULL ) + break; + } + +#ifndef reboot_thru_bios + dmi_check_system(reboot_dmi_table); +#endif + return 0; +} +__initcall(reboot_init); From 1b7e15f112382a3c5028bda9d73627e30bfa6ad1 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 10:37:37 +0100 Subject: [PATCH 072/151] Fix checksum-offload problems introduced in c/s 9514, due to data_validated flag not being properly specified on the device channel. Signed-off-by: Keir Fraser --- .../drivers/xen/netback/netback.c | 12 ++++++++---- .../drivers/xen/netfront/netfront.c | 19 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index d9f259ce26..8e3a1c72b7 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -329,9 +329,9 @@ static void net_rx_action(unsigned long unused) irq = netif->irq; id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id; flags = 0; - if (skb->ip_summed == CHECKSUM_HW) - flags |= NETRXF_csum_blank; - if (skb->proto_data_valid) + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ + flags |= NETRXF_csum_blank | NETRXF_data_validated; + else if (skb->proto_data_valid) /* remote but checksummed? */ flags |= NETRXF_data_validated; if (make_rx_response(netif, id, status, (unsigned long)skb->data & ~PAGE_MASK, @@ -658,7 +658,11 @@ static void net_tx_action(unsigned long unused) skb->dev = netif->dev; skb->protocol = eth_type_trans(skb, skb->dev); - if (txreq.flags & NETTXF_data_validated) { + /* + * Old frontends do not assert data_validated but we + * can infer it from csum_blank so test both flags. + */ + if (txreq.flags & (NETTXF_data_validated|NETTXF_csum_blank)) { skb->ip_summed = CHECKSUM_UNNECESSARY; skb->proto_data_valid = 1; } else { diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 1f2ee99e58..b85ff4b1d3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -698,9 +698,9 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) tx->size = skb->len; tx->flags = 0; - if (skb->ip_summed == CHECKSUM_HW) - tx->flags |= NETTXF_csum_blank; - if (skb->proto_data_valid) + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ + tx->flags |= NETTXF_csum_blank | NETTXF_data_validated; + if (skb->proto_data_valid) /* remote but checksummed? */ tx->flags |= NETTXF_data_validated; np->tx.req_prod_pvt = i + 1; @@ -816,7 +816,11 @@ static int netif_poll(struct net_device *dev, int *pbudget) skb->len = rx->status; skb->tail = skb->data + skb->len; - if (rx->flags & NETRXF_data_validated) { + /* + * Old backends do not assert data_validated but we + * can infer it from csum_blank so test both flags. + */ + if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank)) { skb->ip_summed = CHECKSUM_UNNECESSARY; skb->proto_data_valid = 1; } else { @@ -1017,8 +1021,11 @@ static void network_connect(struct net_device *dev) tx->gref = np->grant_tx_ref[i]; tx->offset = (unsigned long)skb->data & ~PAGE_MASK; tx->size = skb->len; - tx->flags = (skb->ip_summed == CHECKSUM_HW) ? - NETTXF_csum_blank : 0; + tx->flags = 0; + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ + tx->flags |= NETTXF_csum_blank | NETTXF_data_validated; + if (skb->proto_data_valid) /* remote but checksummed? */ + tx->flags |= NETTXF_data_validated; np->stats.tx_bytes += skb->len; np->stats.tx_packets++; From e95a4836bc382183c4e4f966650d621394e693b8 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 10:41:11 +0100 Subject: [PATCH 073/151] Define Xen interface version for tools build. Signed-off-by: Keir Fraser --- tools/Rules.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/Rules.mk b/tools/Rules.mk index a2eeced638..f2fcd2a811 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -12,6 +12,8 @@ XEN_LIBXENSTAT = $(XEN_ROOT)/tools/xenstat/libxenstat/src X11_LDPATH = -L/usr/X11R6/$(LIBDIR) +CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030101 + %.opic: %.c $(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $< From ad9f21014fec142b972793c0c118946071744e2f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 10:52:10 +0100 Subject: [PATCH 074/151] There are a couple of bugs with the current handling of reads and writes in the configuration space overlay functions. The wrong offset is passed to the virtual field handlers. This patch uses the variable which contains the correct offset. This patch also fixes the logic which generates the actual value to write to a given virtual configuration space field. Signed-off-by: Ryan Wilson --- .../drivers/xen/pciback/conf_space.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c index 9d1fe1ecaa..cb64458ef8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c @@ -106,7 +106,7 @@ static inline int valid_request(int offset, int size) } static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask, - u32 offset) + int offset) { if (offset >= 0) { new_val_mask <<= (offset * 8); @@ -180,7 +180,8 @@ int pciback_config_read(struct pci_dev *dev, int offset, int size, if ((req_start >= field_start && req_start < field_end) || (req_end > field_start && req_end <= field_end)) { - err = conf_space_read(dev, cfg_entry, offset, &tmp_val); + err = conf_space_read(dev, cfg_entry, field_start, + &tmp_val); if (err) goto out; @@ -228,14 +229,16 @@ int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value) || (req_end > field_start && req_end <= field_end)) { tmp_val = 0; - err = pciback_config_read(dev, offset, size, &tmp_val); + err = pciback_config_read(dev, field_start, + field->size, &tmp_val); if (err) break; tmp_val = merge_value(tmp_val, value, get_mask(size), - field_start - req_start); + req_start - field_start); - err = conf_space_write(dev, cfg_entry, offset, tmp_val); + err = conf_space_write(dev, cfg_entry, field_start, + tmp_val); handled = 1; } } From beac48024f45e37fa1398414b313a893475f7eb7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 10:54:29 +0100 Subject: [PATCH 075/151] gdbserver readme update. Signed-Off-By: Nitin A Kamble --- tools/debugger/gdb/README | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/debugger/gdb/README b/tools/debugger/gdb/README index 9af7336486..8221798914 100644 --- a/tools/debugger/gdb/README +++ b/tools/debugger/gdb/README @@ -1,16 +1,17 @@ -DomU GDB server for 32-bit (PAE and non-PAE) systems +DomU & HVM GDB server for 32-bit (PAE and non-PAE) and x86_64 systems ---------------------------------------------------- Lines marked below with [*] are optional, if you want full source-level debugging of your kernel image. To build the GDB server: + 0. Build rest of the Xen first from the base directory 1. Run ./gdbbuild from within this directory. 2. Copy ./gdb-6.2.1-linux-i386-xen/gdb/gdbserver/gdbserver-xen to your test machine. -To build a debuggable guest kernel image: +To build a debuggable guest domU kernel image: 1. cd linux-2.6.xx-xenU 2. make menuconfig 3. From within the configurator, enable the following options: @@ -28,7 +29,7 @@ To debug a running guest: # bt # disass -To debug a crashed guest: +To debug a crashed domU guest: 1. Add '(enable-dump yes)' to /etc/xen/xend-config.sxp before starting xend. 2. When the domain crashes, a core file is written to From ec74700a6b17a0e78cd6816ca913001536fe91e5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 12:23:49 +0100 Subject: [PATCH 076/151] Fix a regression in hvm_pio_assist() when booting Windows on VT-x. Clean up the function also. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/io.c | 77 +++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 44 deletions(-) diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index fd9ff611df..a6cde8ee26 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -365,57 +365,46 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p, unsigned long old_eax; int sign = p->df ? -1 : 1; - if (p->pdata_valid || (mmio_opp->flags & OVERLAP)) { - if (mmio_opp->flags & REPZ) + if ( p->pdata_valid || (mmio_opp->flags & OVERLAP) ) + { + if ( mmio_opp->flags & REPZ ) regs->ecx -= p->count; - if (p->dir == IOREQ_READ) { + if ( p->dir == IOREQ_READ ) + { regs->edi += sign * p->count * p->size; - - if (mmio_opp->flags & OVERLAP) { - /* - * If we are doing in IN and it's overlapping a page boundary, - * we need to copy the data back to user's page with hvm_copy. - * Note that overlap * can only be set with paging enabled, so - * we don't need to worry about * real-mode stuff. - */ - unsigned long addr; - { - /* - * We completely ignore segment registers here - - * it's not a good idea. We also may use upper bits - * in edi when in 16-bit real/protected mode. - * We really need to get the actual address back from - * the arch-dependant HVM portion. - */ - struct vcpu *v = current; - if (hvm_realmode(v)) - __hvm_bug(regs); - } - addr = regs->edi; + if ( mmio_opp->flags & OVERLAP ) + { + unsigned long addr = regs->edi; + if (hvm_realmode(current)) + addr += regs->es << 4; if (sign > 0) addr -= p->size; hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); } - } else + } + else /* p->dir == IOREQ_WRITE */ + { + ASSERT(p->dir == IOREQ_WRITE); regs->esi += sign * p->count * p->size; - - } else { - if (p->dir == IOREQ_READ) { - old_eax = regs->eax; - switch (p->size) { - case 1: - regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff); - break; - case 2: - regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff); - break; - case 4: - regs->eax = (p->u.data & 0xffffffff); - break; - default: - printk("Error: %s unknown port size\n", __FUNCTION__); - domain_crash_synchronous(); - } + } + } + else if ( p->dir == IOREQ_READ ) + { + old_eax = regs->eax; + switch ( p->size ) + { + case 1: + regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff); + break; + case 2: + regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff); + break; + case 4: + regs->eax = (p->u.data & 0xffffffff); + break; + default: + printk("Error: %s unknown port size\n", __FUNCTION__); + domain_crash_synchronous(); } } } From d808cafa396490aafd6338bb153fdd2f2975df61 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 13:38:54 +0100 Subject: [PATCH 077/151] Extend the 'badpage' boot option to parse inclusive ranges of bad panges '-'. Signed-off-by: Erik Bosman --- xen/common/page_alloc.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 763dafd75c..ab5cd1298a 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -170,7 +170,7 @@ paddr_t init_boot_allocator(paddr_t bitmap_start) void init_boot_pages(paddr_t ps, paddr_t pe) { - unsigned long bad_pfn; + unsigned long bad_spfn, bad_epfn, i; char *p; ps = round_pgup(ps); @@ -184,18 +184,31 @@ void init_boot_pages(paddr_t ps, paddr_t pe) p = opt_badpage; while ( *p != '\0' ) { - bad_pfn = simple_strtoul(p, &p, 0); + bad_spfn = simple_strtoul(p, &p, 0); + bad_epfn = bad_spfn; + + if ( *p == '-' ) + { + p++; + bad_epfn = simple_strtoul(p, &p, 0); + if ( bad_epfn < bad_spfn ) + bad_epfn = bad_spfn; + } if ( *p == ',' ) p++; else if ( *p != '\0' ) break; - if ( (bad_pfn < max_page) && !allocated_in_map(bad_pfn) ) - { - printk("Marking page %lx as bad\n", bad_pfn); - map_alloc(bad_pfn, 1); - } + if ( bad_epfn == bad_spfn ) + printk("Marking page %lx as bad\n", bad_spfn); + else + printk("Marking pages %lx through %lx as bad\n", + bad_spfn, bad_epfn); + + for ( i = bad_spfn; i <= bad_epfn; i++ ) + if ( (i < max_page) && !allocated_in_map(i) ) + map_alloc(i, 1); } } From af73380a31d7597a8c348a815f651c02868bc3cb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 15:00:42 +0100 Subject: [PATCH 078/151] Rename update_dom_time() to update_vcpu_system_time(). Introduce new generic function update_domain_wallclock_time(). Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/xentime.c | 8 +++++++- xen/arch/x86/domain.c | 2 +- xen/arch/x86/domain_build.c | 2 +- xen/arch/x86/time.c | 41 +++++++++++++++---------------------- xen/common/schedule.c | 6 +++--- xen/include/asm-x86/time.h | 3 --- xen/include/xen/time.h | 4 +++- 7 files changed, 31 insertions(+), 35 deletions(-) diff --git a/xen/arch/ia64/xen/xentime.c b/xen/arch/ia64/xen/xentime.c index af784f7f06..97a615440d 100644 --- a/xen/arch/ia64/xen/xentime.c +++ b/xen/arch/ia64/xen/xentime.c @@ -84,7 +84,13 @@ s_time_t get_s_time(void) return now; } -void update_dom_time(struct vcpu *v) +void update_vcpu_system_time(struct vcpu *v) +{ + /* N-op here, and let dom0 to manage system time directly */ + return; +} + +void update_domain_wallclock_time(struct domain *d) { /* N-op here, and let dom0 to manage system time directly */ return; diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index a4e52139bd..b52770ef80 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -363,7 +363,7 @@ int arch_set_info_guest( update_pagetables(v); if ( v->vcpu_id == 0 ) - init_domain_time(d); + update_domain_wallclock_time(d); /* Don't redo final setup */ set_bit(_VCPUF_initialised, &v->vcpu_flags); diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 1a80aeb36f..599753a613 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -773,7 +773,7 @@ int construct_dom0(struct domain *d, zap_low_mappings(idle_pg_table_l2); #endif - init_domain_time(d); + update_domain_wallclock_time(d); set_bit(_VCPUF_initialised, &v->vcpu_flags); diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 286df06a6f..ef4c7901bd 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -670,7 +670,7 @@ static inline void version_update_end(u32 *version) (*version)++; } -static inline void __update_dom_time(struct vcpu *v) +static inline void __update_vcpu_system_time(struct vcpu *v) { struct cpu_time *t; struct vcpu_time_info *u; @@ -688,11 +688,21 @@ static inline void __update_dom_time(struct vcpu *v) version_update_end(&u->version); } -void update_dom_time(struct vcpu *v) +void update_vcpu_system_time(struct vcpu *v) { if ( v->domain->shared_info->vcpu_info[v->vcpu_id].time.tsc_timestamp != cpu_time[smp_processor_id()].local_tsc_stamp ) - __update_dom_time(v); + __update_vcpu_system_time(v); +} + +void update_domain_wallclock_time(struct domain *d) +{ + spin_lock(&wc_lock); + version_update_begin(&d->shared_info->wc_version); + d->shared_info->wc_sec = wc_sec; + d->shared_info->wc_nsec = wc_nsec; + version_update_end(&d->shared_info->wc_version); + spin_unlock(&wc_lock); } /* Set clock to after 00:00:00 UTC, 1 January, 1970. */ @@ -701,40 +711,21 @@ void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base) u64 x; u32 y, _wc_sec, _wc_nsec; struct domain *d; - shared_info_t *s; x = (secs * 1000000000ULL) + (u64)nsecs - system_time_base; y = do_div(x, 1000000000); + spin_lock(&wc_lock); wc_sec = _wc_sec = (u32)x; wc_nsec = _wc_nsec = (u32)y; + spin_unlock(&wc_lock); read_lock(&domlist_lock); - spin_lock(&wc_lock); - for_each_domain ( d ) - { - s = d->shared_info; - version_update_begin(&s->wc_version); - s->wc_sec = _wc_sec; - s->wc_nsec = _wc_nsec; - version_update_end(&s->wc_version); - } - - spin_unlock(&wc_lock); + update_domain_wallclock_time(d); read_unlock(&domlist_lock); } -void init_domain_time(struct domain *d) -{ - spin_lock(&wc_lock); - version_update_begin(&d->shared_info->wc_version); - d->shared_info->wc_sec = wc_sec; - d->shared_info->wc_nsec = wc_nsec; - version_update_end(&d->shared_info->wc_version); - spin_unlock(&wc_lock); -} - static void local_time_calibration(void *unused) { unsigned int cpu = smp_processor_id(); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 4ab5d7d879..0b1644ea5a 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -572,7 +572,7 @@ static void __enter_scheduler(void) /* Ensure that the domain has an up-to-date time base. */ if ( !is_idle_vcpu(next) ) { - update_dom_time(next); + update_vcpu_system_time(next); if ( next->sleep_tick != schedule_data[cpu].tick ) send_timer_event(next); } @@ -609,7 +609,7 @@ static void t_timer_fn(void *unused) if ( !is_idle_vcpu(v) ) { - update_dom_time(v); + update_vcpu_system_time(v); send_timer_event(v); } @@ -623,7 +623,7 @@ static void dom_timer_fn(void *data) { struct vcpu *v = data; - update_dom_time(v); + update_vcpu_system_time(v); send_timer_event(v); } diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h index 38e4dffcf2..731ce9500e 100644 --- a/xen/include/asm-x86/time.h +++ b/xen/include/asm-x86/time.h @@ -7,9 +7,6 @@ extern void calibrate_tsc_bp(void); extern void calibrate_tsc_ap(void); -struct domain; -extern void init_domain_time(struct domain *d); - typedef u64 cycles_t; static inline cycles_t get_cycles(void) diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h index 3a31af0112..931401388e 100644 --- a/xen/include/xen/time.h +++ b/xen/include/xen/time.h @@ -55,7 +55,9 @@ s_time_t get_s_time(void); #define MILLISECS(_ms) ((s_time_t)((_ms) * 1000000ULL)) #define MICROSECS(_us) ((s_time_t)((_us) * 1000ULL)) -extern void update_dom_time(struct vcpu *v); +extern void update_vcpu_system_time(struct vcpu *v); +extern void update_domain_wallclock_time(struct domain *d); + extern void do_settime( unsigned long secs, unsigned long nsecs, u64 system_time_base); From c5093e07194ce191f7bd204e6fa6315a97268682 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 15:42:01 +0100 Subject: [PATCH 079/151] Add support for XCHG instruction accessing LAPIC device model. Signed-off-by: Boris Ostrovsky --- xen/Rules.mk | 3 +++ xen/arch/x86/hvm/intercept.c | 12 +++++++++++- xen/arch/x86/hvm/platform.c | 19 +++++++++++++++++++ xen/include/asm-x86/hvm/io.h | 1 + xen/include/public/hvm/ioreq.h | 1 + 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index ade8b87a1e..faa2dd13fe 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -31,6 +31,9 @@ HDRS := $(wildcard $(BASEDIR)/include/xen/*.h) HDRS += $(wildcard $(BASEDIR)/include/public/*.h) HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h) HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/$(TARGET_SUBARCH)/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/svm/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/vmx/*.h) # Do not depend on auto-generated header files. HDRS := $(subst $(BASEDIR)/include/asm-$(TARGET_ARCH)/asm-offsets.h,,$(HDRS)) HDRS := $(subst $(BASEDIR)/include/xen/banner.h,,$(HDRS)) diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index 462627dd6e..77d5527b2c 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -123,6 +123,16 @@ static inline void hvm_mmio_access(struct vcpu *v, req->u.data = tmp1; break; + case IOREQ_TYPE_XCHG: + /* + * Note that we don't need to be atomic here since VCPU is accessing + * its own local APIC. + */ + tmp1 = read_handler(v, req->addr, req->size); + write_handler(v, req->addr, req->size, (unsigned long) req->u.data); + req->u.data = tmp1; + break; + default: printk("error ioreq type for local APIC %x\n", req->type); domain_crash_synchronous(); @@ -143,7 +153,7 @@ int hvm_mmio_intercept(ioreq_t *p) if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) ) { hvm_mmio_access(v, p, hvm_mmio_handlers[i]->read_handler, - hvm_mmio_handlers[i]->write_handler); + hvm_mmio_handlers[i]->write_handler); return 1; } } diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 94eb1fb13f..c36360bcb3 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -439,6 +439,14 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i GET_OP_SIZE_FOR_BYTE(size_reg); return mem_reg(size_reg, opcode, instr, rex); + case 0x87: /* xchg {r/m16|r/m32}, {m/r16|m/r32} */ + instr->instr = INSTR_XCHG; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + if (((*(opcode+1)) & 0xc7) == 5) + return reg_mem(instr->op_size, opcode, instr, rex); + else + return mem_reg(instr->op_size, opcode, instr, rex); + case 0x88: /* mov r8, m8 */ instr->instr = INSTR_MOV; instr->op_size = BYTE; @@ -936,6 +944,17 @@ void handle_mmio(unsigned long va, unsigned long gpa) break; } + case INSTR_XCHG: + mmio_opp->flags = mmio_inst.flags; + mmio_opp->instr = mmio_inst.instr; + mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */ + mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */ + + /* send the request and wait for the value */ + send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1, + mmio_inst.op_size, 0, IOREQ_WRITE, 0); + break; + default: printf("Unhandled MMIO instruction\n"); domain_crash_synchronous(); diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index 6992a4ffeb..b315997102 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -66,6 +66,7 @@ #define INSTR_STOS 10 #define INSTR_TEST 11 #define INSTR_BT 12 +#define INSTR_XCHG 13 struct instruction { __s8 instr; /* instruction type */ diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h index 4897ba3b14..38edfbc3e5 100644 --- a/xen/include/public/hvm/ioreq.h +++ b/xen/include/public/hvm/ioreq.h @@ -34,6 +34,7 @@ #define IOREQ_TYPE_AND 2 #define IOREQ_TYPE_OR 3 #define IOREQ_TYPE_XOR 4 +#define IOREQ_TYPE_XCHG 5 /* * VMExit dispatcher should cooperate with instruction decoder to From 2e70fcfed5ff48f9d0e33cd86702fccaedda5941 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 15:46:01 +0100 Subject: [PATCH 080/151] Clean up HDRS Makefile variable. Signed-off-by: Keir Fraser --- xen/Rules.mk | 23 +++++++++++------------ xen/arch/x86/Rules.mk | 4 ++++ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index faa2dd13fe..2639f6a1d1 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -26,21 +26,20 @@ override TARGET_SUBARCH := $(XEN_TARGET_ARCH) override COMPILE_ARCH := $(patsubst x86%,x86,$(XEN_COMPILE_ARCH)) override TARGET_ARCH := $(patsubst x86%,x86,$(XEN_TARGET_ARCH)) -TARGET := $(BASEDIR)/xen -HDRS := $(wildcard $(BASEDIR)/include/xen/*.h) -HDRS += $(wildcard $(BASEDIR)/include/public/*.h) -HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h) -HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/$(TARGET_SUBARCH)/*.h) -HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/*.h) -HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/svm/*.h) -HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/hvm/vmx/*.h) -# Do not depend on auto-generated header files. -HDRS := $(subst $(BASEDIR)/include/asm-$(TARGET_ARCH)/asm-offsets.h,,$(HDRS)) -HDRS := $(subst $(BASEDIR)/include/xen/banner.h,,$(HDRS)) -HDRS := $(subst $(BASEDIR)/include/xen/compile.h,,$(HDRS)) +TARGET := $(BASEDIR)/xen + +HDRS := $(wildcard $(BASEDIR)/include/xen/*.h) +HDRS += $(wildcard $(BASEDIR)/include/public/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/$(TARGET_SUBARCH)/*.h) include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk +# Do not depend on auto-generated header files. +HDRS := $(subst $(BASEDIR)/include/asm-$(TARGET_ARCH)/asm-offsets.h,,$(HDRS)) +HDRS := $(subst $(BASEDIR)/include/xen/banner.h,,$(HDRS)) +HDRS := $(subst $(BASEDIR)/include/xen/compile.h,,$(HDRS)) + # Note that link order matters! ALL_OBJS-y += $(BASEDIR)/common/built_in.o ALL_OBJS-y += $(BASEDIR)/drivers/built_in.o diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 9bd3c94443..399a1cce4b 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -46,6 +46,10 @@ x86_32 := n x86_64 := y endif +HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/svm/*.h) +HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/vmx/*.h) + # Test for at least GCC v3.2.x. gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/') ifeq ($(call gcc-ver,1),1) From a853f9f18f2d2c822ae098c5583cd70f1df29354 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 17:15:34 +0100 Subject: [PATCH 081/151] Clean up build system some more. No need to explicitly include Rules.mk/Post.mk all over the place. Signed-off-by: Keir Fraser --- xen/Makefile | 60 +++++++++++++++------------- xen/Post.mk | 27 ------------- xen/Rules.mk | 34 ++++++++++++++++ xen/acm/Makefile | 4 -- xen/arch/ia64/Makefile | 8 +--- xen/arch/ia64/linux-xen/Makefile | 4 -- xen/arch/ia64/linux/Makefile | 5 --- xen/arch/ia64/vmx/Makefile | 4 -- xen/arch/ia64/xen/Makefile | 4 -- xen/arch/x86/Makefile | 8 +--- xen/arch/x86/acpi/Makefile | 4 -- xen/arch/x86/cpu/Makefile | 4 -- xen/arch/x86/cpu/mcheck/Makefile | 4 -- xen/arch/x86/cpu/mtrr/Makefile | 4 -- xen/arch/x86/genapic/Makefile | 4 -- xen/arch/x86/hvm/Makefile | 4 -- xen/arch/x86/hvm/svm/Makefile | 4 -- xen/arch/x86/hvm/svm/x86_32/Makefile | 4 -- xen/arch/x86/hvm/svm/x86_64/Makefile | 4 -- xen/arch/x86/hvm/vmx/Makefile | 4 -- xen/arch/x86/hvm/vmx/x86_32/Makefile | 4 -- xen/arch/x86/hvm/vmx/x86_64/Makefile | 4 -- xen/arch/x86/x86_32/Makefile | 4 -- xen/arch/x86/x86_64/Makefile | 4 -- xen/common/Makefile | 4 -- xen/drivers/Makefile | 4 -- xen/drivers/acpi/Makefile | 4 -- xen/drivers/char/Makefile | 4 -- 28 files changed, 70 insertions(+), 160 deletions(-) delete mode 100644 xen/Post.mk diff --git a/xen/Makefile b/xen/Makefile index d7b458116c..c34445ac37 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -1,27 +1,20 @@ -INSTALL = install -INSTALL_DATA = $(INSTALL) -m0644 -INSTALL_DIR = $(INSTALL) -d -m0755 - # This is the correct place to edit the build version. # All other places this is stored (eg. compile.h) should be autogenerated. -export XEN_VERSION = 3 -export XEN_SUBVERSION = 0 -export XEN_EXTRAVERSION = -unstable -export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) +export XEN_VERSION := 3 +export XEN_SUBVERSION := 0 +export XEN_EXTRAVERSION := -unstable +export XEN_FULLVERSION := $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) -export BASEDIR := $(CURDIR) - -include Rules.mk +export BASEDIR := $(CURDIR) default: build -$(TARGET).gz: $(TARGET) - gzip -f -9 < $< > $@.new - mv $@.new $@ -debug: - objdump -D -S $(TARGET)-syms > $(TARGET).s +ifeq ($(XEN_ROOT),) -dist: install +build install clean: + make -f Rules.mk $@ + +else build: $(TARGET).gz @@ -38,24 +31,35 @@ install: $(TARGET).gz $(INSTALL_DATA) include/public/io/*.h $(DESTDIR)/usr/include/xen/io $(INSTALL_DATA) include/public/COPYING $(DESTDIR)/usr/include/xen -clean: delete-unfresh-files +clean:: delete-unfresh-files $(MAKE) -C tools clean - $(MAKE) -C common clean - $(MAKE) -C drivers clean - $(MAKE) -C acm clean - $(MAKE) -C arch/$(TARGET_ARCH) clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C common clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C drivers clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C acm clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean rm -f include/asm *.o $(TARGET)* *~ core rm -f include/asm-*/asm-offsets.h rm -f include/xen/acm_policy.h +endif + +dist: install + +debug: FORCE + objdump -D -S $(TARGET)-syms > $(TARGET).s + +$(TARGET).gz: $(TARGET) + gzip -f -9 < $< > $@.new + mv $@.new $@ + $(TARGET): delete-unfresh-files $(MAKE) -C tools - $(MAKE) include/xen/compile.h - $(MAKE) include/xen/acm_policy.h + $(MAKE) -f $(BASEDIR)/Rules.mk include/xen/compile.h + $(MAKE) -f $(BASEDIR)/Rules.mk include/xen/acm_policy.h [ -e include/asm ] || ln -sf asm-$(TARGET_ARCH) include/asm - $(MAKE) -C arch/$(TARGET_ARCH) asm-offsets.s - $(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h - $(MAKE) -C arch/$(TARGET_ARCH) $(TARGET) + $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) asm-offsets.s + $(MAKE) -f $(BASEDIR)/Rules.mk include/asm-$(TARGET_ARCH)/asm-offsets.h + $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) $(TARGET) # drivers/char/console.o contains static banner/compile info. Blow it away. # Don't refresh these files during e.g., 'sudo make install' @@ -115,7 +119,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s echo ""; \ echo "#endif") <$< >$@ -.PHONY: default debug install dist clean delete-unfresh-files TAGS tags +.PHONY: default debug build install dist clean delete-unfresh-files TAGS tags SUBDIRS = acm arch/$(TARGET_ARCH) common drivers define all_sources diff --git a/xen/Post.mk b/xen/Post.mk deleted file mode 100644 index 02008ac7b0..0000000000 --- a/xen/Post.mk +++ /dev/null @@ -1,27 +0,0 @@ -# Ensure each subdirectory has exactly one trailing slash. -subdir-n := $(patsubst %,%/,$(patsubst %/,%,$(subdir-n))) -subdir-y := $(patsubst %,%/,$(patsubst %/,%,$(subdir-y))) - -# Add explicitly declared subdirectories to the object list. -obj-y += $(patsubst %,%/built_in.o,$(subdir-y)) - -# Add implicitly declared subdirectories (in the object list) to the -# subdirectory list, and rewrite the object-list entry. -subdir-y += $(filter %/,$(obj-y)) -obj-y := $(patsubst %/,%/built-in.o,$(obj-y)) - -subdir-all := $(subdir-y) $(subdir-n) - -built_in.o: $(obj-y) - $(LD) $(LDFLAGS) -r -o $@ $^ - -.PHONY: FORCE -FORCE: - -%/built_in.o: FORCE - $(MAKE) -C $* - -clean:: $(addprefix _clean_, $(subdir-all)) FORCE - rm -f *.o *~ core -_clean_%/: FORCE - $(MAKE) -C $* clean diff --git a/xen/Rules.mk b/xen/Rules.mk index 2639f6a1d1..66749058d3 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -33,6 +33,10 @@ HDRS += $(wildcard $(BASEDIR)/include/public/*.h) HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h) HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/$(TARGET_SUBARCH)/*.h) +INSTALL := install +INSTALL_DATA := $(INSTALL) -m0644 +INSTALL_DIR := $(INSTALL) -d -m0755 + include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk # Do not depend on auto-generated header files. @@ -63,6 +67,36 @@ ALL_OBJS := $(ALL_OBJS-y) CFLAGS := $(strip $(CFLAGS) $(CFLAGS-y)) AFLAGS := $(strip $(AFLAGS) $(AFLAGS-y)) +include Makefile + +# Ensure each subdirectory has exactly one trailing slash. +subdir-n := $(patsubst %,%/,$(patsubst %/,%,$(subdir-n))) +subdir-y := $(patsubst %,%/,$(patsubst %/,%,$(subdir-y))) + +# Add explicitly declared subdirectories to the object list. +obj-y += $(patsubst %,%/built_in.o,$(subdir-y)) + +# Add implicitly declared subdirectories (in the object list) to the +# subdirectory list, and rewrite the object-list entry. +subdir-y += $(filter %/,$(obj-y)) +obj-y := $(patsubst %/,%/built-in.o,$(obj-y)) + +subdir-all := $(subdir-y) $(subdir-n) + +built_in.o: $(obj-y) + $(LD) $(LDFLAGS) -r -o $@ $^ + +.PHONY: FORCE +FORCE: + +%/built_in.o: FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $* built_in.o + +clean:: $(addprefix _clean_, $(subdir-all)) FORCE + rm -f *.o *~ core +_clean_%/: FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $* clean + %.o: %.c $(HDRS) Makefile $(CC) $(CFLAGS) -c $< -o $@ diff --git a/xen/acm/Makefile b/xen/acm/Makefile index a3656e905a..c16be20c3a 100644 --- a/xen/acm/Makefile +++ b/xen/acm/Makefile @@ -1,9 +1,5 @@ -include $(BASEDIR)/Rules.mk - obj-y += acm_core.o obj-y += acm_policy.o obj-y += acm_simple_type_enforcement_hooks.o obj-y += acm_chinesewall_hooks.o obj-y += acm_null_hooks.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile index 381c6d739b..14db4f2fa9 100644 --- a/xen/arch/ia64/Makefile +++ b/xen/arch/ia64/Makefile @@ -1,21 +1,17 @@ -include $(BASEDIR)/Rules.mk - subdir-y += xen subdir-y += vmx subdir-y += linux subdir-y += linux-xen -include $(BASEDIR)/Post.mk - $(TARGET)-syms: linux-xen/head.o $(ALL_OBJS) xen.lds.s $(LD) $(LDFLAGS) -T xen.lds.s -N \ -Map map.out linux-xen/head.o $(ALL_OBJS) -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols > $(BASEDIR)/xen-syms.S - $(MAKE) $(BASEDIR)/xen-syms.o + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds.s -N \ -Map map.out linux-xen/head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S - $(MAKE) $(BASEDIR)/xen-syms.o + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds.s -N \ -Map map.out linux-xen/head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o diff --git a/xen/arch/ia64/linux-xen/Makefile b/xen/arch/ia64/linux-xen/Makefile index f602f52c04..ca5354b343 100644 --- a/xen/arch/ia64/linux-xen/Makefile +++ b/xen/arch/ia64/linux-xen/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += efi.o obj-y += entry.o obj-y += irq_ia64.o @@ -15,5 +13,3 @@ obj-y += time.o obj-y += tlb.o obj-y += unaligned.o obj-y += unwind.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/ia64/linux/Makefile b/xen/arch/ia64/linux/Makefile index b5f2c1dd47..926fc501df 100644 --- a/xen/arch/ia64/linux/Makefile +++ b/xen/arch/ia64/linux/Makefile @@ -1,6 +1,3 @@ -include $(BASEDIR)/Rules.mk - - obj-y += bitop.o obj-y += clear_page.o obj-y += cmdline.o @@ -26,8 +23,6 @@ obj-y += __udivdi3.o obj-y += __moddi3.o obj-y += __umoddi3.o -include $(BASEDIR)/Post.mk - ## variants of divide/modulo ## see files in xen/arch/ia64/linux/lib (linux/arch/ia64/lib) __divdi3.o: idiv64.S diff --git a/xen/arch/ia64/vmx/Makefile b/xen/arch/ia64/vmx/Makefile index 55322531b1..df0a72f0fe 100644 --- a/xen/arch/ia64/vmx/Makefile +++ b/xen/arch/ia64/vmx/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += hvm_vioapic.o obj-y += mm.o obj-y += mmio.o @@ -20,5 +18,3 @@ obj-y += vmx_vcpu.o obj-y += vmx_virt.o obj-y += vmx_vsa.o obj-y += vtlb.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/ia64/xen/Makefile b/xen/arch/ia64/xen/Makefile index 1d3d80b347..600b010d11 100644 --- a/xen/arch/ia64/xen/Makefile +++ b/xen/arch/ia64/xen/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += acpi.o obj-y += dom0_ops.o obj-y += domain.o @@ -26,5 +24,3 @@ obj-y += xensetup.o obj-y += xentime.o obj-$(crash_debug) += gdbstub.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index dee62f224a..fbb1a83c1f 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - subdir-y += acpi subdir-y += cpu subdir-y += genapic @@ -50,8 +48,6 @@ obj-$(x86_64) += shadow.o shadow_public.o shadow_guest32.o shadow_guest32pae.o obj-$(crash_debug) += gdbstub.o -include $(BASEDIR)/Post.mk - $(TARGET): $(TARGET)-syms boot/mkelf32 ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \ `$(NM) $(TARGET)-syms | sort | tail -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'` @@ -60,11 +56,11 @@ $(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) xen.lds $(LD) $(LDFLAGS) -T xen.lds -N \ boot/$(TARGET_SUBARCH).o $(ALL_OBJS) -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S - $(MAKE) $(BASEDIR)/xen-syms.o + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds -N \ boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S - $(MAKE) $(BASEDIR)/xen-syms.o + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds -N \ boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o diff --git a/xen/arch/x86/acpi/Makefile b/xen/arch/x86/acpi/Makefile index 6c0e68a8ac..123f174f0e 100644 --- a/xen/arch/x86/acpi/Makefile +++ b/xen/arch/x86/acpi/Makefile @@ -1,5 +1 @@ -include $(BASEDIR)/Rules.mk - obj-y += boot.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/cpu/Makefile b/xen/arch/x86/cpu/Makefile index bbb02cb719..1fa37dbe75 100644 --- a/xen/arch/x86/cpu/Makefile +++ b/xen/arch/x86/cpu/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - subdir-y += mcheck subdir-y += mtrr @@ -12,5 +10,3 @@ obj-$(x86_32) += centaur.o obj-$(x86_32) += cyrix.o obj-$(x86_32) += rise.o obj-$(x86_32) += transmeta.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/cpu/mcheck/Makefile b/xen/arch/x86/cpu/mcheck/Makefile index 7588c577b8..fbf8f0a177 100644 --- a/xen/arch/x86/cpu/mcheck/Makefile +++ b/xen/arch/x86/cpu/mcheck/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += k7.o obj-y += mce.o obj-y += non-fatal.o @@ -7,5 +5,3 @@ obj-y += p4.o obj-y += p5.o obj-y += p6.o obj-y += winchip.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/cpu/mtrr/Makefile b/xen/arch/x86/cpu/mtrr/Makefile index 972ddb7f4b..445138aa3c 100644 --- a/xen/arch/x86/cpu/mtrr/Makefile +++ b/xen/arch/x86/cpu/mtrr/Makefile @@ -1,10 +1,6 @@ -include $(BASEDIR)/Rules.mk - obj-y += amd.o obj-y += centaur.o obj-y += cyrix.o obj-y += generic.o obj-y += main.o obj-y += state.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/genapic/Makefile b/xen/arch/x86/genapic/Makefile index ea51ead30a..1fcc2b9edb 100644 --- a/xen/arch/x86/genapic/Makefile +++ b/xen/arch/x86/genapic/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += bigsmp.o obj-y += default.o obj-y += delivery.o @@ -7,5 +5,3 @@ obj-y += es7000.o obj-y += es7000plat.o obj-y += probe.o obj-y += summit.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index 84759742b6..7cde715116 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - subdir-y += svm subdir-y += vmx @@ -10,5 +8,3 @@ obj-y += io.o obj-y += platform.o obj-y += vioapic.o obj-y += vlapic.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/svm/Makefile b/xen/arch/x86/hvm/svm/Makefile index 3e26b45e18..e3baf066a0 100644 --- a/xen/arch/x86/hvm/svm/Makefile +++ b/xen/arch/x86/hvm/svm/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - subdir-$(x86_32) += x86_32 subdir-$(x86_64) += x86_64 @@ -8,5 +6,3 @@ obj-y += instrlen.o obj-y += intr.o obj-y += svm.o obj-y += vmcb.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/svm/x86_32/Makefile b/xen/arch/x86/hvm/svm/x86_32/Makefile index 4191f3c4eb..a9efb8f9e1 100644 --- a/xen/arch/x86/hvm/svm/x86_32/Makefile +++ b/xen/arch/x86/hvm/svm/x86_32/Makefile @@ -1,5 +1 @@ -include $(BASEDIR)/Rules.mk - obj-y += exits.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/svm/x86_64/Makefile b/xen/arch/x86/hvm/svm/x86_64/Makefile index 4191f3c4eb..a9efb8f9e1 100644 --- a/xen/arch/x86/hvm/svm/x86_64/Makefile +++ b/xen/arch/x86/hvm/svm/x86_64/Makefile @@ -1,5 +1 @@ -include $(BASEDIR)/Rules.mk - obj-y += exits.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/vmx/Makefile b/xen/arch/x86/hvm/vmx/Makefile index 221e8aa694..3eede43031 100644 --- a/xen/arch/x86/hvm/vmx/Makefile +++ b/xen/arch/x86/hvm/vmx/Makefile @@ -1,10 +1,6 @@ -include $(BASEDIR)/Rules.mk - subdir-$(x86_32) += x86_32 subdir-$(x86_64) += x86_64 obj-y += io.o obj-y += vmcs.o obj-y += vmx.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/vmx/x86_32/Makefile b/xen/arch/x86/hvm/vmx/x86_32/Makefile index 4191f3c4eb..a9efb8f9e1 100644 --- a/xen/arch/x86/hvm/vmx/x86_32/Makefile +++ b/xen/arch/x86/hvm/vmx/x86_32/Makefile @@ -1,5 +1 @@ -include $(BASEDIR)/Rules.mk - obj-y += exits.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/hvm/vmx/x86_64/Makefile b/xen/arch/x86/hvm/vmx/x86_64/Makefile index 4191f3c4eb..a9efb8f9e1 100644 --- a/xen/arch/x86/hvm/vmx/x86_64/Makefile +++ b/xen/arch/x86/hvm/vmx/x86_64/Makefile @@ -1,5 +1 @@ -include $(BASEDIR)/Rules.mk - obj-y += exits.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/x86_32/Makefile b/xen/arch/x86/x86_32/Makefile index 6d834de89b..7b4ab46be6 100644 --- a/xen/arch/x86/x86_32/Makefile +++ b/xen/arch/x86/x86_32/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += domain_page.o obj-y += entry.o obj-y += mm.o @@ -7,5 +5,3 @@ obj-y += seg_fixup.o obj-y += traps.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o - -include $(BASEDIR)/Post.mk diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile index 82816f4ce5..3ce6d01156 100644 --- a/xen/arch/x86/x86_64/Makefile +++ b/xen/arch/x86/x86_64/Makefile @@ -1,7 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += entry.o obj-y += mm.o obj-y += traps.o - -include $(BASEDIR)/Post.mk diff --git a/xen/common/Makefile b/xen/common/Makefile index 6ea5889540..d7bf1c50ec 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -1,5 +1,3 @@ -include $(BASEDIR)/Rules.mk - obj-y += acm_ops.o obj-y += bitmap.o obj-y += dom0_ops.o @@ -28,7 +26,5 @@ obj-y += xmalloc.o obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o -include $(BASEDIR)/Post.mk - # Object file contains changeset and compiler information. kernel.o: $(BASEDIR)/include/xen/compile.h diff --git a/xen/drivers/Makefile b/xen/drivers/Makefile index b24da03f5e..ba39b440a9 100644 --- a/xen/drivers/Makefile +++ b/xen/drivers/Makefile @@ -1,6 +1,2 @@ -include $(BASEDIR)/Rules.mk - subdir-y += char subdir-$(HAS_ACPI) += acpi - -include $(BASEDIR)/Post.mk diff --git a/xen/drivers/acpi/Makefile b/xen/drivers/acpi/Makefile index 88b7ad93a6..68dafe3a52 100644 --- a/xen/drivers/acpi/Makefile +++ b/xen/drivers/acpi/Makefile @@ -1,5 +1 @@ -include $(BASEDIR)/Rules.mk - obj-y += tables.o - -include $(BASEDIR)/Post.mk diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile index 40fc709764..e63753d429 100644 --- a/xen/drivers/char/Makefile +++ b/xen/drivers/char/Makefile @@ -1,10 +1,6 @@ -include $(BASEDIR)/Rules.mk - obj-y += console.o obj-y += ns16550.o obj-y += serial.o -include $(BASEDIR)/Post.mk - # Object file contains changeset and compiler information. console.o: $(BASEDIR)/include/xen/compile.h From b0a4d66a6cf065ab0a4341ba88cc75dccfbe1141 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 17:41:51 +0100 Subject: [PATCH 082/151] Add new interface for allocating reserved event-channel ports to arbitrary Xen subsystems. Signed-off-by: Keir Fraser --- xen/common/event_channel.c | 52 +++++++++++++++++++++++++++++++++++++- xen/include/xen/event.h | 5 ++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index b37a6f183a..2f766f7d31 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -46,6 +46,7 @@ goto out; \ } while ( 0 ) + static int get_free_port(struct domain *d) { struct evtchn *chn; @@ -360,7 +361,7 @@ static long __evtchn_close(struct domain *d1, int port1) rc = -EINVAL; goto out; } - + port2 = chn1->u.interdomain.remote_port; BUG_ON(!port_is_valid(d2, port2)); @@ -438,6 +439,7 @@ long evtchn_send(unsigned int lport) return ret; } + void evtchn_set_pending(struct vcpu *v, int port) { struct domain *d = v->domain; @@ -471,6 +473,7 @@ void evtchn_set_pending(struct vcpu *v, int port) } } + void send_guest_virq(struct vcpu *v, int virq) { int port = v->virq_to_evtchn[virq]; @@ -479,6 +482,7 @@ void send_guest_virq(struct vcpu *v, int virq) evtchn_set_pending(v, port); } + void send_guest_pirq(struct domain *d, int pirq) { int port = d->pirq_to_evtchn[pirq]; @@ -486,6 +490,7 @@ void send_guest_pirq(struct domain *d, int pirq) evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); } + static long evtchn_status(evtchn_status_t *status) { struct domain *d; @@ -550,6 +555,7 @@ static long evtchn_status(evtchn_status_t *status) return rc; } + long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id) { struct domain *d = current->domain; @@ -585,6 +591,7 @@ long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id) return rc; } + static long evtchn_unmask(evtchn_unmask_t *unmask) { struct domain *d = current->domain; @@ -620,6 +627,7 @@ static long evtchn_unmask(evtchn_unmask_t *unmask) return 0; } + long do_event_channel_op(GUEST_HANDLE(evtchn_op_t) uop) { long rc; @@ -694,6 +702,48 @@ long do_event_channel_op(GUEST_HANDLE(evtchn_op_t) uop) } +int evtchn_open_reserved_port(struct domain *d) +{ + struct evtchn *chn; + int port; + + spin_lock(&d->evtchn_lock); + + if ( (port = get_free_port(d)) >= 0 ) + { + chn = evtchn_from_port(d, port); + chn->state = ECS_RESERVED; + } + + spin_unlock(&d->evtchn_lock); + + return port; +} + + +void evtchn_close_reserved_port(struct domain *d, int port) +{ + struct evtchn *chn; + + spin_lock(&d->evtchn_lock); + + BUG_ON(!port_is_valid(d, port)); + + chn = evtchn_from_port(d, port); + chn->state = ECS_FREE; + chn->notify_vcpu_id = 0; + + spin_unlock(&d->evtchn_lock); +} + + +void evtchn_notify_reserved_port(struct domain *d, int port) +{ + struct evtchn *chn = evtchn_from_port(d, port); + evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); +} + + int evtchn_init(struct domain *d) { spin_lock_init(&d->evtchn_lock); diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 8487a25c7b..e56b991406 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -45,4 +45,9 @@ extern long evtchn_send(unsigned int lport); /* Bind a local event-channel port to the specified VCPU. */ extern long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id); +/* Reserved event-channel ports for other Xen subsystems. */ +int evtchn_open_reserved_port(struct domain *d); +void evtchn_close_reserved_port(struct domain *d, int port); +void evtchn_notify_reserved_port(struct domain *d, int port); + #endif /* __XEN_EVENT_H__ */ From 6f1d9ff91969db563dad7f8e703b88eda7ee2c8e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 5 Apr 2006 19:30:02 +0100 Subject: [PATCH 083/151] Backtrack on the new interface for reserved event-channel ports, as binding them in user space via the evtchn driver would be a pain. Instead extend VIRQs so they can be classified as 'global' or 'per vcpu'. The former can only be allocated once per guest, but can be re-bound to an arbitrary VCPU. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/xentime.c | 2 +- xen/arch/x86/time.c | 2 +- xen/common/domain.c | 8 +-- xen/common/event_channel.c | 101 +++++++++++++++++------------ xen/common/keyhandler.c | 2 +- xen/drivers/char/console.c | 2 +- xen/include/public/event_channel.h | 18 +++-- xen/include/public/xen.h | 15 +++-- xen/include/xen/event.h | 18 ++--- 9 files changed, 100 insertions(+), 68 deletions(-) diff --git a/xen/arch/ia64/xen/xentime.c b/xen/arch/ia64/xen/xentime.c index 97a615440d..50d8dbf466 100644 --- a/xen/arch/ia64/xen/xentime.c +++ b/xen/arch/ia64/xen/xentime.c @@ -274,6 +274,6 @@ int reprogram_timer(s_time_t timeout) void send_timer_event(struct vcpu *v) { - send_guest_virq(v, VIRQ_TIMER); + send_guest_vcpu_virq(v, VIRQ_TIMER); } diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index ef4c7901bd..85f52f4d75 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -916,7 +916,7 @@ void __init early_time_init(void) void send_timer_event(struct vcpu *v) { - send_guest_virq(v, VIRQ_TIMER); + send_guest_vcpu_virq(v, VIRQ_TIMER); } /* diff --git a/xen/common/domain.c b/xen/common/domain.c index b582719545..3637d4c45c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -137,7 +137,7 @@ void domain_kill(struct domain *d) domain_relinquish_resources(d); put_domain(d); - send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC); + send_guest_global_virq(dom0, VIRQ_DOM_EXC); } } @@ -192,7 +192,7 @@ static void domain_shutdown_finalise(void) /* Don't set DOMF_shutdown until execution contexts are sync'ed. */ if ( !test_and_set_bit(_DOMF_shutdown, &d->domain_flags) ) - send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC); + send_guest_global_virq(dom0, VIRQ_DOM_EXC); UNLOCK_BIGLOCK(d); @@ -267,7 +267,7 @@ void domain_pause_for_debugger(void) for_each_vcpu ( d, v ) vcpu_sleep_nosync(v); - send_guest_virq(dom0->vcpu[0], VIRQ_DEBUGGER); + send_guest_global_virq(dom0, VIRQ_DEBUGGER); } @@ -307,7 +307,7 @@ void domain_destroy(struct domain *d) free_domain(d); - send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC); + send_guest_global_virq(dom0, VIRQ_DOM_EXC); } void vcpu_pause(struct vcpu *v) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 2f766f7d31..ccb96b0f65 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -3,7 +3,7 @@ * * Event notifications from VIRQs, PIRQs, and other domains. * - * Copyright (c) 2003-2005, K A Fraser. + * Copyright (c) 2003-2006, K A Fraser. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -47,6 +47,27 @@ } while ( 0 ) +static int virq_is_global(int virq) +{ + int rc; + + ASSERT((virq >= 0) && (virq < NR_VIRQS)); + + switch ( virq ) + { + case VIRQ_TIMER: + case VIRQ_DEBUG: + rc = 0; + break; + default: + rc = 1; + break; + } + + return rc; +} + + static int get_free_port(struct domain *d) { struct evtchn *chn; @@ -182,6 +203,9 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind) if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) ) return -EINVAL; + if ( virq_is_global(virq) && (vcpu != 0) ) + return -EINVAL; + if ( (vcpu >= ARRAY_SIZE(d->vcpu)) || ((v = d->vcpu[vcpu]) == NULL) ) return -ENOENT; @@ -474,19 +498,43 @@ void evtchn_set_pending(struct vcpu *v, int port) } -void send_guest_virq(struct vcpu *v, int virq) +void send_guest_vcpu_virq(struct vcpu *v, int virq) { - int port = v->virq_to_evtchn[virq]; + int port; - if ( likely(port != 0) ) - evtchn_set_pending(v, port); + ASSERT(!virq_is_global(virq)); + + port = v->virq_to_evtchn[virq]; + if ( unlikely(port == 0) ) + return; + + evtchn_set_pending(v, port); +} + +void send_guest_global_virq(struct domain *d, int virq) +{ + int port; + struct evtchn *chn; + + ASSERT(virq_is_global(virq)); + + port = d->vcpu[0]->virq_to_evtchn[virq]; + if ( unlikely(port == 0) ) + return; + + chn = evtchn_from_port(d, port); + evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); } void send_guest_pirq(struct domain *d, int pirq) { int port = d->pirq_to_evtchn[pirq]; - struct evtchn *chn = evtchn_from_port(d, port); + struct evtchn *chn; + + ASSERT(port != 0); + + chn = evtchn_from_port(d, port); evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); } @@ -576,6 +624,12 @@ long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id) chn = evtchn_from_port(d, port); switch ( chn->state ) { + case ECS_VIRQ: + if ( virq_is_global(chn->u.virq) ) + chn->notify_vcpu_id = vcpu_id; + else + rc = -EINVAL; + break; case ECS_UNBOUND: case ECS_INTERDOMAIN: case ECS_PIRQ: @@ -702,41 +756,6 @@ long do_event_channel_op(GUEST_HANDLE(evtchn_op_t) uop) } -int evtchn_open_reserved_port(struct domain *d) -{ - struct evtchn *chn; - int port; - - spin_lock(&d->evtchn_lock); - - if ( (port = get_free_port(d)) >= 0 ) - { - chn = evtchn_from_port(d, port); - chn->state = ECS_RESERVED; - } - - spin_unlock(&d->evtchn_lock); - - return port; -} - - -void evtchn_close_reserved_port(struct domain *d, int port) -{ - struct evtchn *chn; - - spin_lock(&d->evtchn_lock); - - BUG_ON(!port_is_valid(d, port)); - - chn = evtchn_from_port(d, port); - chn->state = ECS_FREE; - chn->notify_vcpu_id = 0; - - spin_unlock(&d->evtchn_lock); -} - - void evtchn_notify_reserved_port(struct domain *d, int port) { struct evtchn *chn = evtchn_from_port(d, port); diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index d1a87ac2c3..f881412ec7 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -162,7 +162,7 @@ static void dump_domains(unsigned char key) &d->shared_info->evtchn_mask[0]), test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel)); - send_guest_virq(v, VIRQ_DEBUG); + send_guest_vcpu_virq(v, VIRQ_DEBUG); } } diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 2755f5e46b..df4706bcb2 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -294,7 +294,7 @@ static void __serial_rx(char c, struct cpu_user_regs *regs) if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE ) serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c; /* Always notify the guest: prevents receive path from getting stuck. */ - send_guest_virq(dom0->vcpu[0], VIRQ_CONSOLE); + send_guest_global_virq(dom0, VIRQ_CONSOLE); } static void serial_rx(char c, struct cpu_user_regs *regs) diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h index c556163034..f1e067b4a3 100644 --- a/xen/include/public/event_channel.h +++ b/xen/include/public/event_channel.h @@ -50,9 +50,13 @@ typedef struct evtchn_bind_interdomain { * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ on specified * vcpu. * NOTES: - * 1. A virtual IRQ may be bound to at most one event channel per vcpu. - * 2. The allocated event channel is bound to the specified vcpu. The binding - * may not be changed. + * 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list + * in xen.h for the classification of each VIRQ. + * 2. Global VIRQs must be allocated on VCPU0 but can subsequently be + * re-bound via EVTCHNOP_bind_vcpu. + * 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu. + * The allocated event channel is bound to the specified vcpu and the + * binding cannot be changed. */ #define EVTCHNOP_bind_virq 1 typedef struct evtchn_bind_virq { @@ -152,9 +156,11 @@ typedef struct evtchn_status { * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an * event is pending. * NOTES: - * 1. IPI- and VIRQ-bound channels always notify the vcpu that initialised - * the binding. This binding cannot be changed. - * 2. All other channels notify vcpu0 by default. This default is set when + * 1. IPI-bound channels always notify the vcpu specified at bind time. + * This binding cannot be changed. + * 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time. + * This binding cannot be changed. + * 3. All other channels notify vcpu0 by default. This default is set when * the channel is allocated (a port that is freed and subsequently reused * has its binding reset to vcpu0). */ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 2921a140cd..1da6ede005 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -65,12 +65,17 @@ * VIRTUAL INTERRUPTS * * Virtual interrupts that a guest OS may receive from Xen. + * + * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a + * global VIRQ. The former can be bound once per VCPU and cannot be re-bound. + * The latter can be allocated only once per guest: they must initially be + * allocated to VCPU0 but can subsequently be re-bound. */ -#define VIRQ_TIMER 0 /* Timebase update, and/or requested timeout. */ -#define VIRQ_DEBUG 1 /* Request guest to dump debug info. */ -#define VIRQ_CONSOLE 2 /* (DOM0) Bytes received on emergency console. */ -#define VIRQ_DOM_EXC 3 /* (DOM0) Exceptional event for some domain. */ -#define VIRQ_DEBUGGER 6 /* (DOM0) A domain has paused for debugging. */ +#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */ +#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */ +#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */ +#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */ +#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */ #define NR_VIRQS 8 /* diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index e56b991406..13b2b5f9be 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -3,7 +3,7 @@ * * A nice interface for passing asynchronous events to guest OSes. * - * Copyright (c) 2002-2005, K A Fraser + * Copyright (c) 2002-2006, K A Fraser */ #ifndef __XEN_EVENT_H__ @@ -18,11 +18,18 @@ extern void evtchn_set_pending(struct vcpu *v, int port); /* - * send_guest_virq: + * send_guest_vcpu_virq: Notify guest via a per-VCPU VIRQ. * @v: VCPU to which virtual IRQ should be sent * @virq: Virtual IRQ number (VIRQ_*) */ -extern void send_guest_virq(struct vcpu *v, int virq); +extern void send_guest_vcpu_virq(struct vcpu *v, int virq); + +/* + * send_guest_global_virq: Notify guest via a global VIRQ. + * @d: Domain to which virtual IRQ should be sent + * @virq: Virtual IRQ number (VIRQ_*) + */ +extern void send_guest_global_virq(struct domain *d, int virq); /* * send_guest_pirq: @@ -45,9 +52,4 @@ extern long evtchn_send(unsigned int lport); /* Bind a local event-channel port to the specified VCPU. */ extern long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id); -/* Reserved event-channel ports for other Xen subsystems. */ -int evtchn_open_reserved_port(struct domain *d); -void evtchn_close_reserved_port(struct domain *d, int port); -void evtchn_notify_reserved_port(struct domain *d, int port); - #endif /* __XEN_EVENT_H__ */ From d220279c332247edc78db398b22fdc4a25f556d4 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 6 Apr 2006 00:59:06 +0100 Subject: [PATCH 084/151] Further workarounds for the broken string marshalling in xmlrpclib. Regardless of the encoding used, one still may not include non-printable characters in an XML document. When a dmesg contains a ^D character, something seen on one of our test machines, an invalid XML document is generated. Use a trick by David Mertz to work around this -- escape the string using Python's repr function. Signed-off-by: Ewan Mellor --- tools/python/xen/util/xmlrpclib2.py | 42 +++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index 65aa49ced5..0abc5d9149 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -20,6 +20,7 @@ An enhanced XML-RPC client/server interface for Python. """ +import string import types from httplib import HTTPConnection, HTTP @@ -54,6 +55,18 @@ class UnixTransport(Transport): def make_connection(self, host): return HTTPUnix(self.__handler) + +# See _marshalled_dispatch below. +def conv_string(x): + if (isinstance(x, types.StringType) or + isinstance(x, unicode)): + s = string.replace(x, "'", r"\047") + exec "s = '" + s + "'" + return s + else: + return x + + class ServerProxy(xmlrpclib.ServerProxy): def __init__(self, uri, transport=None, encoding=None, verbose=0, allow_none=1): @@ -65,6 +78,16 @@ class ServerProxy(xmlrpclib.ServerProxy): xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding, verbose, allow_none) + + def __request(self, methodname, params): + response = xmlrpclib.ServerProxy.__request(self, methodname, params) + + if isinstance(response, tuple): + return tuple([conv_string(x) for x in response]) + else: + return conv_string(response) + + # This is a base XML-RPC server for TCP. It sets allow_reuse_address to # true, and has an improved marshaller that logs and serializes exceptions. @@ -79,14 +102,17 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): else: response = self._dispatch(method, params) - # Convert strings to unicode strings so that they are escaped - # properly by xmlrpclib. We use latin-1 here, but any - # ASCII-compatible scheme would do -- we just care about getting - # the bytes across the wire. - # Any message handler that actually cares about the charset in - # use should be returning Unicode strings. - if isinstance(response, types.StringType): - response = unicode(response, 'iso-8859-1') + # With either Unicode or normal strings, we can only transmit + # \t, \n, \r, \u0020-\ud7ff, \ue000-\ufffd, and \u10000-\u10ffff + # in an XML document. xmlrpclib does not escape these values + # properly, and then breaks when it comes to parse the document. + # To hack around this problem, we use repr here and exec above + # to transmit the string using Python encoding. + # Thanks to David Mertz for the trick (buried + # in xml_pickle.py). + if (isinstance(response, types.StringType) or + isinstance(response, unicode)): + response = repr(response)[1:-1] response = (response,) response = xmlrpclib.dumps(response, From 21f9f9f9165788b91dbbad8568ae86e22dd475ae Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:22:00 +0100 Subject: [PATCH 085/151] Remove unused teardown_irq() definition. Removes two files from sparse tree. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/include/linux/irq.h | 244 ------------- linux-2.6-xen-sparse/kernel/irq/manage.c | 425 ----------------------- 2 files changed, 669 deletions(-) delete mode 100644 linux-2.6-xen-sparse/include/linux/irq.h delete mode 100644 linux-2.6-xen-sparse/kernel/irq/manage.c diff --git a/linux-2.6-xen-sparse/include/linux/irq.h b/linux-2.6-xen-sparse/include/linux/irq.h deleted file mode 100644 index 4ffabba098..0000000000 --- a/linux-2.6-xen-sparse/include/linux/irq.h +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef __irq_h -#define __irq_h - -/* - * Please do not include this file in generic code. There is currently - * no requirement for any architecture to implement anything held - * within this file. - * - * Thanks. --rmk - */ - -#include -#include - -#if !defined(CONFIG_S390) - -#include -#include -#include -#include - -#include -#include - -/* - * IRQ line status. - */ -#define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */ -#define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */ -#define IRQ_PENDING 4 /* IRQ pending - replay on enable */ -#define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */ -#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */ -#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */ -#define IRQ_LEVEL 64 /* IRQ level triggered */ -#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */ -#if defined(ARCH_HAS_IRQ_PER_CPU) -# define IRQ_PER_CPU 256 /* IRQ is per CPU */ -# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) -#else -# define CHECK_IRQ_PER_CPU(var) 0 -#endif - -/* - * Interrupt controller descriptor. This is all we need - * to describe about the low-level hardware. - */ -struct hw_interrupt_type { - const char * typename; - unsigned int (*startup)(unsigned int irq); - void (*shutdown)(unsigned int irq); - void (*enable)(unsigned int irq); - void (*disable)(unsigned int irq); - void (*ack)(unsigned int irq); - void (*end)(unsigned int irq); - void (*set_affinity)(unsigned int irq, cpumask_t dest); - /* Currently used only by UML, might disappear one day.*/ -#ifdef CONFIG_IRQ_RELEASE_METHOD - void (*release)(unsigned int irq, void *dev_id); -#endif -}; - -typedef struct hw_interrupt_type hw_irq_controller; - -/* - * This is the "IRQ descriptor", which contains various information - * about the irq, including what kind of hardware handling it has, - * whether it is disabled etc etc. - * - * Pad this out to 32 bytes for cache and indexing reasons. - */ -typedef struct irq_desc { - hw_irq_controller *handler; - void *handler_data; - struct irqaction *action; /* IRQ action list */ - unsigned int status; /* IRQ status */ - unsigned int depth; /* nested irq disables */ - unsigned int irq_count; /* For detecting broken interrupts */ - unsigned int irqs_unhandled; - spinlock_t lock; -#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) - unsigned int move_irq; /* Flag need to re-target intr dest*/ -#endif -} ____cacheline_aligned irq_desc_t; - -extern irq_desc_t irq_desc [NR_IRQS]; - -/* Return a pointer to the irq descriptor for IRQ. */ -static inline irq_desc_t * -irq_descp (int irq) -{ - return irq_desc + irq; -} - -#include /* the arch dependent stuff */ - -extern int setup_irq(unsigned int irq, struct irqaction * new); -#ifdef CONFIG_XEN -extern int teardown_irq(unsigned int irq, struct irqaction * old); -#endif - -#ifdef CONFIG_GENERIC_HARDIRQS -extern cpumask_t irq_affinity[NR_IRQS]; - -#ifdef CONFIG_SMP -static inline void set_native_irq_info(int irq, cpumask_t mask) -{ - irq_affinity[irq] = mask; -} -#else -static inline void set_native_irq_info(int irq, cpumask_t mask) -{ -} -#endif - -#ifdef CONFIG_SMP - -#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) -extern cpumask_t pending_irq_cpumask[NR_IRQS]; - -static inline void set_pending_irq(unsigned int irq, cpumask_t mask) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&desc->lock, flags); - desc->move_irq = 1; - pending_irq_cpumask[irq] = mask; - spin_unlock_irqrestore(&desc->lock, flags); -} - -static inline void -move_native_irq(int irq) -{ - cpumask_t tmp; - irq_desc_t *desc = irq_descp(irq); - - if (likely (!desc->move_irq)) - return; - - desc->move_irq = 0; - - if (likely(cpus_empty(pending_irq_cpumask[irq]))) - return; - - if (!desc->handler->set_affinity) - return; - - /* note - we hold the desc->lock */ - cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); - - /* - * If there was a valid mask to work with, please - * do the disable, re-program, enable sequence. - * This is *not* particularly important for level triggered - * but in a edge trigger case, we might be setting rte - * when an active trigger is comming in. This could - * cause some ioapics to mal-function. - * Being paranoid i guess! - */ - if (unlikely(!cpus_empty(tmp))) { - desc->handler->disable(irq); - desc->handler->set_affinity(irq,tmp); - desc->handler->enable(irq); - } - cpus_clear(pending_irq_cpumask[irq]); -} - -#ifdef CONFIG_PCI_MSI -/* - * Wonder why these are dummies? - * For e.g the set_ioapic_affinity_vector() calls the set_ioapic_affinity_irq() - * counter part after translating the vector to irq info. We need to perform - * this operation on the real irq, when we dont use vector, i.e when - * pci_use_vector() is false. - */ -static inline void move_irq(int irq) -{ -} - -static inline void set_irq_info(int irq, cpumask_t mask) -{ -} - -#else // CONFIG_PCI_MSI - -static inline void move_irq(int irq) -{ - move_native_irq(irq); -} - -static inline void set_irq_info(int irq, cpumask_t mask) -{ - set_native_irq_info(irq, mask); -} -#endif // CONFIG_PCI_MSI - -#else // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE - -#define move_irq(x) -#define move_native_irq(x) -#define set_pending_irq(x,y) -static inline void set_irq_info(int irq, cpumask_t mask) -{ - set_native_irq_info(irq, mask); -} - -#endif // CONFIG_GENERIC_PENDING_IRQ - -#else // CONFIG_SMP - -#define move_irq(x) -#define move_native_irq(x) - -#endif // CONFIG_SMP - -extern int no_irq_affinity; -extern int noirqdebug_setup(char *str); - -extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, - struct irqaction *action); -extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); -extern void note_interrupt(unsigned int irq, irq_desc_t *desc, - int action_ret, struct pt_regs *regs); -extern int can_request_irq(unsigned int irq, unsigned long irqflags); - -extern void init_irq_proc(void); - -#ifdef CONFIG_AUTO_IRQ_AFFINITY -extern int select_smp_affinity(unsigned int irq); -#else -static inline int -select_smp_affinity(unsigned int irq) -{ - return 1; -} -#endif - -#endif - -extern hw_irq_controller no_irq_type; /* needed in every arch ? */ - -#endif - -#endif /* __irq_h */ diff --git a/linux-2.6-xen-sparse/kernel/irq/manage.c b/linux-2.6-xen-sparse/kernel/irq/manage.c deleted file mode 100644 index 0139444c45..0000000000 --- a/linux-2.6-xen-sparse/kernel/irq/manage.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * linux/kernel/irq/manage.c - * - * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar - * - * This file contains driver APIs to the irq subsystem. - */ - -#include -#include -#include -#include -#include - -#include "internals.h" - -#ifdef CONFIG_SMP - -cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; - -#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) -cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; -#endif - -/** - * synchronize_irq - wait for pending IRQ handlers (on other CPUs) - * @irq: interrupt number to wait for - * - * This function waits for any pending IRQ handlers for this interrupt - * to complete before returning. If you use this function while - * holding a resource the IRQ handler may need you will deadlock. - * - * This function may be called - with care - from IRQ context. - */ -void synchronize_irq(unsigned int irq) -{ - struct irq_desc *desc = irq_desc + irq; - - if (irq >= NR_IRQS) - return; - - while (desc->status & IRQ_INPROGRESS) - cpu_relax(); -} - -EXPORT_SYMBOL(synchronize_irq); - -#endif - -/** - * disable_irq_nosync - disable an irq without waiting - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables and Enables are - * nested. - * Unlike disable_irq(), this function does not ensure existing - * instances of the IRQ handler have completed before returning. - * - * This function may be called from IRQ context. - */ -void disable_irq_nosync(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - spin_lock_irqsave(&desc->lock, flags); - if (!desc->depth++) { - desc->status |= IRQ_DISABLED; - desc->handler->disable(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(disable_irq_nosync); - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and Disables are - * nested. - * This function waits for any pending IRQ handlers for this interrupt - * to complete before returning. If you use this function while - * holding a resource the IRQ handler may need you will deadlock. - * - * This function may be called - with care - from IRQ context. - */ -void disable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - - if (irq >= NR_IRQS) - return; - - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} - -EXPORT_SYMBOL(disable_irq); - -/** - * enable_irq - enable handling of an irq - * @irq: Interrupt to enable - * - * Undoes the effect of one call to disable_irq(). If this - * matches the last disable, processing of interrupts on this - * IRQ line is re-enabled. - * - * This function may be called from IRQ context. - */ -void enable_irq(unsigned int irq) -{ - irq_desc_t *desc = irq_desc + irq; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - spin_lock_irqsave(&desc->lock, flags); - switch (desc->depth) { - case 0: - WARN_ON(1); - break; - case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; - - desc->status = status; - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = status | IRQ_REPLAY; - hw_resend_irq(desc->handler,irq); - } - desc->handler->enable(irq); - /* fall-through */ - } - default: - desc->depth--; - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -EXPORT_SYMBOL(enable_irq); - -/* - * Internal function that tells the architecture code whether a - * particular irq has been exclusively allocated or is available - * for driver use. - */ -int can_request_irq(unsigned int irq, unsigned long irqflags) -{ - struct irqaction *action; - - if (irq >= NR_IRQS) - return 0; - - action = irq_desc[irq].action; - if (action) - if (irqflags & action->flags & SA_SHIRQ) - action = NULL; - - return !action; -} - -/** - * setup_irq - register an irqaction structure - * @irq: Interrupt to register - * @irqaction: The irqaction structure to be registered - * - * Normally called by request_irq, this function can be used - * directly to allocate special interrupts that are part of the - * architecture. - */ -int setup_irq(unsigned int irq, struct irqaction * new) -{ - struct irq_desc *desc = irq_desc + irq; - struct irqaction *old, **p; - unsigned long flags; - int shared = 0; - - if (irq >= NR_IRQS) - return -EINVAL; - - if (desc->handler == &no_irq_type) - return -ENOSYS; - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - /* - * The following block of code has to be executed atomically - */ - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | - IRQ_WAITING | IRQ_INPROGRESS); - if (desc->handler->startup) - desc->handler->startup(irq); - else - desc->handler->enable(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - - new->irq = irq; - register_irq_proc(irq); - new->dir = NULL; - register_handler_proc(irq, new); - - return 0; -} - -/* - * teardown_irq - unregister an irqaction - * @irq: Interrupt line being freed - * @old: Pointer to the irqaction that is to be unregistered - * - * This function is called by free_irq and does the actual - * business of unregistering the handler. It exists as a - * seperate function to enable handlers to be unregistered - * for irqactions that have been allocated statically at - * boot time. - * - * This function must not be called from interrupt context. - */ -#ifndef CONFIG_XEN -static -#endif -int teardown_irq(unsigned int irq, struct irqaction * old) -{ - struct irq_desc *desc; - struct irqaction **p; - unsigned long flags; - - if (irq >= NR_IRQS) - return -ENOENT; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - p = &desc->action; - for (;;) { - struct irqaction * action = *p; - - if (action) { - struct irqaction **pp = p; - - p = &action->next; - if (action != old) - continue; - - /* Found it - now remove it from the list of entries */ - *pp = action->next; - - /* Currently used only by UML, might disappear one day.*/ -#ifdef CONFIG_IRQ_RELEASE_METHOD - if (desc->handler->release) - desc->handler->release(irq, dev_id); -#endif - - if (!desc->action) { - desc->status |= IRQ_DISABLED; - if (desc->handler->shutdown) - desc->handler->shutdown(irq); - else - desc->handler->disable(irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - unregister_handler_proc(irq, action); - - /* Make sure it's not being used on another CPU */ - synchronize_irq(irq); - return 0; - } - printk(KERN_ERR "Trying to teardown free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return -ENOENT; - } -} - -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. The function - * does not return until any executing interrupts for this IRQ - * have completed. - * - * This function must not be called from interrupt context. - */ -void free_irq(unsigned int irq, void *dev_id) -{ - struct irq_desc *desc; - struct irqaction *action; - unsigned long flags; - - if (irq >= NR_IRQS) - return; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock,flags); - for (action = desc->action; action != NULL; action = action->next) { - if (action->dev_id != dev_id) - continue; - - spin_unlock_irqrestore(&desc->lock,flags); - - if (teardown_irq(irq, action) == 0) - kfree(action); - return; - } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); - spin_unlock_irqrestore(&desc->lock,flags); - return; -} - -EXPORT_SYMBOL(free_irq); - -/** - * request_irq - allocate an interrupt line - * @irq: Interrupt line to allocate - * @handler: Function to be called when the IRQ occurs - * @irqflags: Interrupt type flags - * @devname: An ascii name for the claiming device - * @dev_id: A cookie passed back to the handler function - * - * This call allocates interrupt resources and enables the - * interrupt line and IRQ handling. From the point this - * call is made your handler function may be invoked. Since - * your handler function must clear any interrupt the board - * raises, you must take care both to initialise your hardware - * and to set up the interrupt handler in the right order. - * - * Dev_id must be globally unique. Normally the address of the - * device data structure is used as the cookie. Since the handler - * receives this value it makes sense to use it. - * - * If your interrupt is shared you must pass a non NULL dev_id - * as this is required when freeing the interrupt. - * - * Flags: - * - * SA_SHIRQ Interrupt is shared - * SA_INTERRUPT Disable local interrupts while processing - * SA_SAMPLE_RANDOM The interrupt can be used for entropy - * - */ -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - struct irqaction * action; - int retval; - - /* - * Sanity-check: shared interrupts must pass in a real dev-ID, - * otherwise we'll have trouble later trying to figure out - * which interrupt is which (messes up the interrupt freeing - * logic etc). - */ - if ((irqflags & SA_SHIRQ) && !dev_id) - return -EINVAL; - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - select_smp_affinity(irq); - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - - return retval; -} - -EXPORT_SYMBOL(request_irq); - From fd7dd2c0ce5c09afbfd65da79e80981f516d9981 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:32:55 +0100 Subject: [PATCH 086/151] Use PAGE_OFFSET instead of __PAGE_OFFSET in netfront.c. __PAGE_OFFSET is not defined on all platforms. Linux/ia64 and Linux/ppc don't have __PAGE_OFFSET definition. Signed-off-by: Isaku Yamahata --- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index b85ff4b1d3..1336be5432 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -993,8 +993,8 @@ static void network_connect(struct net_device *dev) * the RX ring because some of our pages are currently flipped out * so we can't just free the RX skbs. * NB2. Freelist index entries are always going to be less than - * __PAGE_OFFSET, whereas pointers to skbs will always be equal or - * greater than __PAGE_OFFSET: we use this property to distinguish + * PAGE_OFFSET, whereas pointers to skbs will always be equal or + * greater than PAGE_OFFSET: we use this property to distinguish * them. */ @@ -1005,7 +1005,7 @@ static void network_connect(struct net_device *dev) * interface has been down. */ for (requeue_idx = 0, i = 1; i <= NET_TX_RING_SIZE; i++) { - if ((unsigned long)np->tx_skbs[i] < __PAGE_OFFSET) + if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET) continue; skb = np->tx_skbs[i]; @@ -1036,7 +1036,7 @@ static void network_connect(struct net_device *dev) /* Rebuild the RX buffer freelist and the RX ring itself. */ for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) { - if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET) + if ((unsigned long)np->rx_skbs[i] < PAGE_OFFSET) continue; gnttab_grant_foreign_transfer_ref( np->grant_rx_ref[i], np->xbdev->otherend_id, From 96e1e633225fc83dc648cb2afdaa27cf0f0d36d3 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:34:30 +0100 Subject: [PATCH 087/151] Remove unused code in netback's net_rx_action(): new_mfn and old_mfn are set in the end half of the function but they are not used. Signed-off-by: Isaku Yamahata --- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index 8e3a1c72b7..8b2b66b139 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -301,9 +301,6 @@ static void net_rx_action(unsigned long unused) netif = netdev_priv(skb->dev); size = skb->tail - skb->data; - /* Rederive the machine addresses. */ - new_mfn = mcl->args[1] >> PAGE_SHIFT; - old_mfn = gop->mfn; atomic_set(&(skb_shinfo(skb)->dataref), 1); skb_shinfo(skb)->nr_frags = 0; skb_shinfo(skb)->frag_list = NULL; From be7f264bdce1fbfea9df1a4bb89281556d2295f3 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:36:54 +0100 Subject: [PATCH 088/151] Update the user manual appendix to describe bow to get a mouse working properly in a VNC window. Also add 'pae' configuration introduction for HVM guests. Signed-off-by: You, Yongkang Signed-off-by: Dugger, Donald D --- docs/src/user.tex | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/src/user.tex b/docs/src/user.tex index 412410ac4a..e268f2a732 100644 --- a/docs/src/user.tex +++ b/docs/src/user.tex @@ -2052,7 +2052,7 @@ dev86 & The dev86 package provides an assembler and linker for real mode 80x86 i If the dev86 package is not available on the x86\_64 distribution, you can install the i386 version of it. The dev86 rpm package for various distributions can be found at {\scriptsize {\tt http://www.rpmfind.net/linux/rpm2html/search.php?query=dev86\&submit=Search}} \\ -LibVNCServer & The unmodified guest's VGA display, keyboard, and mouse are virtualized using the vncserver library provided by this package. You can get the sources of libvncserver from {\small {\tt http://sourceforge.net/projects/libvncserver}}. Build and install the sources on the build system to get the libvncserver library. The 0.8pre version of libvncserver is currently working well with Xen.\\ +LibVNCServer & The unmodified guest's VGA display, keyboard, and mouse can be virtualized by the vncserver library. You can get the sources of libvncserver from {\small {\tt http://sourceforge.net/projects/libvncserver}}. Build and install the sources on the build system to get the libvncserver library. There is a significant performance degradation in 0.8 version. The current sources in the CVS tree have fixed this degradation. So it is highly recommended to download the latest CVS sources and install them.\\ SDL-devel, SDL & Simple DirectMedia Layer (SDL) is another way of virtualizing the unmodified guest console. It provides an X window for the guest console. @@ -2077,6 +2077,8 @@ acpi & Enable VMX guest ACPI, default=0 (disabled)\\ apic & Enable VMX guest APIC, default=0 (disabled)\\ +pae & Enable VMX guest PAE, default=0 (disabled)\\ + vif & Optionally defines MAC address and/or bridge for the network interfaces. Random MACs are assigned if not given. {\small {\tt type=ioemu}} means ioemu is used to virtualize the VMX NIC. If no type is specified, vbd is used, as with paravirtualized guests.\\ disk & Defines the disk devices you want the domain to have access to, and what you want them accessible as. If using a physical device as the VMX guest's disk, each disk entry is of the form @@ -2229,6 +2231,30 @@ Simply follow the usual method of creating the guest, using the -f parameter and In the default configuration, VNC is on and SDL is off. Therefore VNC windows will open when VMX guests are created. If you want to use SDL to create VMX guests, set {\small {\tt sdl=1}} in your VMX configuration file. You can also turn off VNC by setting {\small {\tt vnc=0}}. +\subsection{Use mouse in VNC window} +The default PS/2 mouse will not work properly in VMX by a VNC window. Summagraphics mouse emulation does work in this environment. A Summagraphics mouse can be enabled by reconfiguring 2 services: + +{\small {\tt 1. General Purpose Mouse (GPM). The GPM daemon is configured in different ways in different Linux distributions. On a Redhat distribution, this is accomplished by changing the file `/etc/sysconfig/mouse' to have the following:\\ +MOUSETYPE="summa"\\ +XMOUSETYPE="SUMMA"\\ +DEVICE=/dev/ttyS0\\ +\\ +2. X11. For all Linux distributions, change the Mouse0 stanza in `/etc/X11/xorg.conf' to:\\ +Section "InputDevice"\\ +Identifier "Mouse0"\\ +Driver "summa"\\ +Option "Device" "/dev/ttyS0"\\ +Option "InputFashion" "Tablet"\\ +Option "Mode" "Absolute"\\ +Option "Name" "EasyPen"\\ +Option "Compatible" "True"\\ +Option "Protocol" "Auto"\\ +Option "SendCoreEvents" "on"\\ +Option "Vendor" "GENIUS"\\ +EndSection}} + +If the Summagraphics mouse isn't the default mouse, you can manually kill 'gpm' and restart it with the command "gpm -m /dev/ttyS0 -t summa". Note that Summagraphics mouse makes no sense in an SDL window and is therefore not available in this environment. + \subsection{Destroy VMX guests} VMX guests can be destroyed in the same way as can paravirtualized guests. We recommend that you type the command From 0773e2a340786190f61b1a9f3f9bb651ba7a377e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:39:30 +0100 Subject: [PATCH 089/151] Fix a problem that was caused by recent changes to the xenbus's behavior that cause the .remove function not to be called anymore during suspend. Due to that the driver allocated one more interrupt on every suspend/resume cycle. Otherwise some code reformatting, cleanups and improvements on allocation and freeing of data structure. Signed-off-by: Stefan Berger --- .../drivers/xen/tpmfront/tpmfront.c | 121 ++++++++++++------ 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index 03a2ab9ea0..53ccf66b82 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -65,14 +65,18 @@ static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs); static void tpmif_rx_action(unsigned long unused); -static void tpmif_connect(struct tpm_private *tp, domid_t domid); +static int tpmif_connect(struct xenbus_device *dev, + struct tpm_private *tp, + domid_t domid); static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0); -static int tpm_allocate_buffers(struct tpm_private *tp); +static int tpmif_allocate_tx_buffers(struct tpm_private *tp); +static void tpmif_free_tx_buffers(struct tpm_private *tp); static void tpmif_set_connected_state(struct tpm_private *tp, u8 newstate); static int tpm_xmit(struct tpm_private *tp, const u8 * buf, size_t count, int userbuffer, void *remember); +static void destroy_tpmring(struct tpm_private *tp); #define DPRINTK(fmt, args...) \ pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) @@ -81,6 +85,8 @@ static int tpm_xmit(struct tpm_private *tp, #define WPRINTK(fmt, args...) \ printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args) +#define GRANT_INVALID_REF 0 + static inline int tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len, @@ -119,6 +125,14 @@ static inline struct tx_buffer *tx_buffer_alloc(void) } +static inline void tx_buffer_free(struct tx_buffer *txb) +{ + if (txb) { + free_page((long)txb->data); + kfree(txb); + } +} + /************************************************************** Utility function for the tpm_private structure **************************************************************/ @@ -128,23 +142,29 @@ static inline void tpm_private_init(struct tpm_private *tp) init_waitqueue_head(&tp->wait_q); } +static inline void tpm_private_free(void) +{ + tpmif_free_tx_buffers(my_priv); + kfree(my_priv); + my_priv = NULL; +} + static struct tpm_private *tpm_private_get(void) { + int err; if (!my_priv) { my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL); if (my_priv) { tpm_private_init(my_priv); + err = tpmif_allocate_tx_buffers(my_priv); + if (err < 0) { + tpm_private_free(); + } } } return my_priv; } -static inline void tpm_private_free(void) -{ - kfree(my_priv); - my_priv = NULL; -} - /************************************************************** The interface to let the tpm plugin register its callback @@ -233,6 +253,8 @@ static int setup_tpmring(struct xenbus_device *dev, tpmif_tx_interface_t *sring; int err; + tp->ring_ref = GRANT_INVALID_REF; + sring = (void *)__get_free_page(GFP_KERNEL); if (!sring) { xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); @@ -240,8 +262,6 @@ static int setup_tpmring(struct xenbus_device *dev, } tp->tx = sring; - tpm_allocate_buffers(tp); - err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx)); if (err < 0) { free_page((unsigned long)sring); @@ -251,14 +271,13 @@ static int setup_tpmring(struct xenbus_device *dev, } tp->ring_ref = err; - err = xenbus_alloc_evtchn(dev, &tp->evtchn); + err = tpmif_connect(dev, tp, dev->otherend_id); if (err) goto fail; - tpmif_connect(tp, dev->otherend_id); - return 0; fail: + destroy_tpmring(tp); return err; } @@ -266,14 +285,17 @@ fail: static void destroy_tpmring(struct tpm_private *tp) { tpmif_set_connected_state(tp, 0); - if (tp->tx != NULL) { + + if (tp->ring_ref != GRANT_INVALID_REF) { gnttab_end_foreign_access(tp->ring_ref, 0, (unsigned long)tp->tx); + tp->ring_ref = GRANT_INVALID_REF; tp->tx = NULL; } if (tp->irq) - unbind_from_irqhandler(tp->irq, NULL); + unbind_from_irqhandler(tp->irq, tp); + tp->evtchn = tp->irq = 0; } @@ -377,6 +399,9 @@ static int tpmfront_probe(struct xenbus_device *dev, int handle; struct tpm_private *tp = tpm_private_get(); + if (!tp) + return -ENOMEM; + err = xenbus_scanf(XBT_NULL, dev->nodename, "handle", "%i", &handle); if (XENBUS_EXIST_ERR(err)) @@ -402,15 +427,14 @@ static int tpmfront_probe(struct xenbus_device *dev, static int tpmfront_remove(struct xenbus_device *dev) { - struct tpm_private *tp = dev->data; + struct tpm_private *tp = (struct tpm_private *)dev->data; destroy_tpmring(tp); return 0; } -static int -tpmfront_suspend(struct xenbus_device *dev) +static int tpmfront_suspend(struct xenbus_device *dev) { - struct tpm_private *tp = dev->data; + struct tpm_private *tp = (struct tpm_private *)dev->data; u32 ctr; /* lock, so no app can send */ @@ -437,29 +461,35 @@ tpmfront_suspend(struct xenbus_device *dev) return 0; } -static int -tpmfront_resume(struct xenbus_device *dev) +static int tpmfront_resume(struct xenbus_device *dev) { - struct tpm_private *tp = dev->data; + struct tpm_private *tp = (struct tpm_private *)dev->data; + destroy_tpmring(tp); return talk_to_backend(dev, tp); } -static void -tpmif_connect(struct tpm_private *tp, domid_t domid) +static int tpmif_connect(struct xenbus_device *dev, + struct tpm_private *tp, + domid_t domid) { int err; tp->backend_id = domid; + err = xenbus_alloc_evtchn(dev, &tp->evtchn); + if (err) + return err; + err = bind_evtchn_to_irqhandler(tp->evtchn, tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp); if (err <= 0) { WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); - return; + return err; } tp->irq = err; + return 0; } static struct xenbus_device_id tpmfront_ids[] = { @@ -488,19 +518,30 @@ static void __exit exit_tpm_xenbus(void) xenbus_unregister_driver(&tpmfront); } - -static int -tpm_allocate_buffers(struct tpm_private *tp) +static int tpmif_allocate_tx_buffers(struct tpm_private *tp) { unsigned int i; - for (i = 0; i < TPMIF_TX_RING_SIZE; i++) + for (i = 0; i < TPMIF_TX_RING_SIZE; i++) { tp->tx_buffers[i] = tx_buffer_alloc(); - return 1; + if (!tp->tx_buffers[i]) { + tpmif_free_tx_buffers(tp); + return -ENOMEM; + } + } + return 0; } -static void -tpmif_rx_action(unsigned long priv) +static void tpmif_free_tx_buffers(struct tpm_private *tp) +{ + unsigned int i; + + for (i = 0; i < TPMIF_TX_RING_SIZE; i++) { + tx_buffer_free(tp->tx_buffers[i]); + } +} + +static void tpmif_rx_action(unsigned long priv) { struct tpm_private *tp = (struct tpm_private *)priv; @@ -545,8 +586,7 @@ exit: } -static irqreturn_t -tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs) +static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs) { struct tpm_private *tp = tpm_priv; unsigned long flags; @@ -560,10 +600,9 @@ tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs) } -static int -tpm_xmit(struct tpm_private *tp, - const u8 * buf, size_t count, int isuserbuffer, - void *remember) +static int tpm_xmit(struct tpm_private *tp, + const u8 * buf, size_t count, int isuserbuffer, + void *remember) { tpmif_tx_request_t *tx; TPMIF_RING_IDX i; @@ -693,8 +732,7 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) * ================================================================= */ -static int __init -tpmif_init(void) +static int __init tpmif_init(void) { IPRINTK("Initialising the vTPM driver.\n"); if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE, @@ -709,8 +747,7 @@ tpmif_init(void) module_init(tpmif_init); -static void __exit -tpmif_exit(void) +static void __exit tpmif_exit(void) { exit_tpm_xenbus(); gnttab_free_grant_references(gref_head); From a6ac8cd28117fe589dd3065c210261c191381786 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:40:15 +0100 Subject: [PATCH 090/151] Remove some unnecessary code from the vTPM hotplug scripts. Signed-off-by: Stefan Berger --- tools/examples/vtpm-common.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/examples/vtpm-common.sh b/tools/examples/vtpm-common.sh index 190f74193a..7d032a6c1d 100644 --- a/tools/examples/vtpm-common.sh +++ b/tools/examples/vtpm-common.sh @@ -261,12 +261,6 @@ function vtpm_create_instance () { if [ "$REASON" == "create" ]; then vtpm_reset $instance - elif [ "$REASON" == "resume" ]; then - vtpm_setup $instance - else - #default case for 'now' - #vtpm_reset $instance - true fi xenstore_write $XENBUS_PATH/instance $instance } From 14713b052ff7805f7ddfef70aa24b34a3ef3081f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 09:47:58 +0100 Subject: [PATCH 091/151] Allow CONFIG_DEBUG_INFO to be specified when building x86/64 XenLinux. Builds and boots fine. Leave the option disabled by default, as with all other defconfigs. Signed-off-by: Keir Fraser --- buildconfigs/linux-defconfig_xen0_x86_64 | 1 + buildconfigs/linux-defconfig_xenU_x86_64 | 1 + buildconfigs/linux-defconfig_xen_x86_64 | 1 + linux-2.6-xen-sparse/lib/Kconfig.debug | 224 ----------------------- 4 files changed, 3 insertions(+), 224 deletions(-) delete mode 100644 linux-2.6-xen-sparse/lib/Kconfig.debug diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index 8f6506a090..04e992076d 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -1183,6 +1183,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set CONFIG_FRAME_POINTER=y diff --git a/buildconfigs/linux-defconfig_xenU_x86_64 b/buildconfigs/linux-defconfig_xenU_x86_64 index d41b30d3a1..68893b915e 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_64 +++ b/buildconfigs/linux-defconfig_xenU_x86_64 @@ -1080,6 +1080,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set CONFIG_FRAME_POINTER=y diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index 58a24a5954..8e97389570 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -2587,6 +2587,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set # CONFIG_FRAME_POINTER is not set diff --git a/linux-2.6-xen-sparse/lib/Kconfig.debug b/linux-2.6-xen-sparse/lib/Kconfig.debug deleted file mode 100644 index f50aa3aa87..0000000000 --- a/linux-2.6-xen-sparse/lib/Kconfig.debug +++ /dev/null @@ -1,224 +0,0 @@ - -config PRINTK_TIME - bool "Show timing information on printks" - help - Selecting this option causes timing information to be - included in printk output. This allows you to measure - the interval between kernel operations, including bootup - operations. This is useful for identifying long delays - in kernel startup. - - -config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on !UML - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config DEBUG_KERNEL - bool "Kernel debugging" - help - Say Y here if you are developing drivers or trying to debug and - identify kernel problems. - -config LOG_BUF_SHIFT - int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL - range 12 21 - default 17 if S390 - default 16 if X86_NUMAQ || IA64 - default 15 if SMP - default 14 - help - Select kernel log buffer size as a power of 2. - Defaults and Examples: - 17 => 128 KB for S/390 - 16 => 64 KB for x86 NUMAQ or IA-64 - 15 => 32 KB for SMP - 14 => 16 KB for uniprocessor - 13 => 8 KB - 12 => 4 KB - -config DETECT_SOFTLOCKUP - bool "Detect Soft Lockups" - depends on DEBUG_KERNEL - default y - help - Say Y here to enable the kernel to detect "soft lockups", - which are bugs that cause the kernel to loop in kernel - mode for more than 10 seconds, without giving other tasks a - chance to run. - - When a soft-lockup is detected, the kernel will print the - current stack trace (which you should report), but the - system will stay locked up. This feature has negligible - overhead. - - (Note that "hard lockups" are separate type of bugs that - can be detected via the NMI-watchdog, on platforms that - support it.) - -config SCHEDSTATS - bool "Collect scheduler statistics" - depends on DEBUG_KERNEL && PROC_FS - help - If you say Y here, additional code will be inserted into the - scheduler and related routines to collect statistics about - scheduler behavior and provide them in /proc/schedstat. These - stats may be useful for both tuning and debugging the scheduler - If you aren't debugging the scheduler or trying to tune a specific - application, you can say N to avoid the very slight overhead - this adds. - -config DEBUG_SLAB - bool "Debug memory allocations" - depends on DEBUG_KERNEL && SLAB - help - Say Y here to have the kernel do limited verification on memory - allocation as well as poisoning memory on free to catch use of freed - memory. This can make kmalloc/kfree-intensive workloads much slower. - -config DEBUG_PREEMPT - bool "Debug preemptible kernel" - depends on DEBUG_KERNEL && PREEMPT - default y - help - If you say Y here then the kernel will use a debug variant of the - commonly used smp_processor_id() function and will print warnings - if kernel code uses it in a preemption-unsafe way. Also, the kernel - will detect preemption count underflows. - -config DEBUG_MUTEXES - bool "Mutex debugging, deadlock detection" - default y - depends on DEBUG_KERNEL - help - This allows mutex semantics violations and mutex related deadlocks - (lockups) to be detected and reported automatically. - -config DEBUG_SPINLOCK - bool "Spinlock debugging" - depends on DEBUG_KERNEL - help - Say Y here and build SMP to catch missing spinlock initialization - and certain other kinds of spinlock errors commonly made. This is - best used in conjunction with the NMI watchdog so that spinlock - deadlocks are also debuggable. - -config DEBUG_SPINLOCK_SLEEP - bool "Sleep-inside-spinlock checking" - depends on DEBUG_KERNEL - help - If you say Y here, various routines which may sleep will become very - noisy if they are called with a spinlock held. - -config DEBUG_KOBJECT - bool "kobject debugging" - depends on DEBUG_KERNEL - help - If you say Y here, some extra kobject debugging messages will be sent - to the syslog. - -config DEBUG_HIGHMEM - bool "Highmem debugging" - depends on DEBUG_KERNEL && HIGHMEM - help - This options enables addition error checking for high memory systems. - Disable for production systems. - -config DEBUG_BUGVERBOSE - bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED - depends on BUG - depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV - default !EMBEDDED - help - Say Y here to make BUG() panics output the file name and line number - of the BUG call as well as the EIP and oops trace. This aids - debugging but costs about 70-100K of memory. - -config DEBUG_INFO - bool "Compile the kernel with debug info" - depends on DEBUG_KERNEL && !X86_64_XEN - help - If you say Y here the resulting kernel image will include - debugging info resulting in a larger kernel image. - Say Y here only if you plan to debug the kernel. - - If unsure, say N. - -config DEBUG_IOREMAP - bool "Enable ioremap() debugging" - depends on DEBUG_KERNEL && PARISC - help - Enabling this option will cause the kernel to distinguish between - ioremapped and physical addresses. It will print a backtrace (at - most one every 10 seconds), hopefully allowing you to see which - drivers need work. Fixing all these problems is a prerequisite - for turning on USE_HPPA_IOREMAP. The warnings are harmless; - the kernel has enough information to fix the broken drivers - automatically, but we'd like to make it more efficient by not - having to do that. - -config DEBUG_FS - bool "Debug Filesystem" - depends on DEBUG_KERNEL && SYSFS - help - debugfs is a virtual file system that kernel developers use to put - debugging files into. Enable this option to be able to read and - write to these files. - - If unsure, say N. - -config DEBUG_VM - bool "Debug VM" - depends on DEBUG_KERNEL - help - Enable this to turn on extended checks in the virtual-memory system - that may impact performance. - - If unsure, say N. - -config FRAME_POINTER - bool "Compile the kernel with frame pointers" - depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML) - default y if DEBUG_INFO && UML - help - If you say Y here the resulting kernel image will be slightly larger - and slower, but it might give very useful debugging information on - some architectures or if you use external debuggers. - If you don't debug the kernel, you can say N. - -config FORCED_INLINING - bool "Force gcc to inline functions marked 'inline'" - depends on DEBUG_KERNEL - default y - help - This option determines if the kernel forces gcc to inline the functions - developers have marked 'inline'. Doing so takes away freedom from gcc to - do what it thinks is best, which is desirable for the gcc 3.x series of - compilers. The gcc 4.x series have a rewritten inlining algorithm and - disabling this option will generate a smaller kernel there. Hopefully - this algorithm is so good that allowing gcc4 to make the decision can - become the default in the future, until then this option is there to - test gcc for this. - -config RCU_TORTURE_TEST - tristate "torture tests for RCU" - depends on DEBUG_KERNEL - default n - help - This option provides a kernel module that runs torture tests - on the RCU infrastructure. The kernel module may be built - after the fact on the running kernel to be tested, if desired. - - Say Y here if you want RCU torture tests to start automatically - at boot time (you probably don't). - Say M if you want the RCU torture tests to build as a module. - Say N if you are unsure. From 4e52e7ef09540355b5c55a2057c9b84abeeac84b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 10:20:32 +0100 Subject: [PATCH 092/151] Fix the blkif_schedule() kthread loop. Much simpler; much more correct. Signed-off-by: Keir Fraser --- .../drivers/xen/blkback/blkback.c | 47 ++++--------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 2de5f1c60c..587f49f0f2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -215,49 +215,20 @@ static void print_stats(blkif_t *blkif) int blkif_schedule(void *arg) { - blkif_t *blkif = arg; + blkif_t *blkif = arg; blkif_get(blkif); + if (debug_lvl) printk(KERN_DEBUG "%s: started\n", current->comm); - for (;;) { - if (kthread_should_stop()) { - /* asked to quit? */ - if (!atomic_read(&blkif->io_pending)) - break; - if (debug_lvl) - printk(KERN_DEBUG "%s: I/O pending, " - "delaying exit\n", current->comm); - } - if (!atomic_read(&blkif->io_pending)) { - /* Wait for work to do. */ - wait_event_interruptible( - blkif->wq, - (atomic_read(&blkif->io_pending) || - kthread_should_stop())); - } else if (list_empty(&pending_free)) { - /* Wait for pending_req becoming available. */ - wait_event_interruptible( - pending_free_wq, - !list_empty(&pending_free)); - } + while (!kthread_should_stop()) { + wait_event_interruptible( + blkif->wq, + (atomic_read(&blkif->io_pending) && + !list_empty(&pending_free)) || + kthread_should_stop()); - if (blkif->status != CONNECTED) { - /* make sure we are connected */ - if (debug_lvl) - printk(KERN_DEBUG "%s: not connected " - "(%d pending)\n", - current->comm, - atomic_read(&blkif->io_pending)); - wait_event_interruptible( - blkif->wq, - (blkif->status == CONNECTED || - kthread_should_stop())); - continue; - } - - /* Schedule I/O */ atomic_set(&blkif->io_pending, 0); if (do_block_io_op(blkif)) atomic_inc(&blkif->io_pending); @@ -271,8 +242,10 @@ int blkif_schedule(void *arg) print_stats(blkif); if (debug_lvl) printk(KERN_DEBUG "%s: exiting\n", current->comm); + blkif->xenblkd = NULL; blkif_put(blkif); + return 0; } From 3f7c9e7d7eedf2e102531dbdc06331f5d4738e86 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 11:13:33 +0100 Subject: [PATCH 093/151] Stupidly forgot there is a separate waitqueue for free pending request structures in blkback. Fix my changes to blkif_schedule(). Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 587f49f0f2..477cab4bc6 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -225,8 +225,11 @@ int blkif_schedule(void *arg) while (!kthread_should_stop()) { wait_event_interruptible( blkif->wq, - (atomic_read(&blkif->io_pending) && - !list_empty(&pending_free)) || + atomic_read(&blkif->io_pending) || + kthread_should_stop()); + wait_event_interruptible( + pending_free_wq, + !list_empty(&pending_free) || kthread_should_stop()); atomic_set(&blkif->io_pending, 0); From 564a3bf276a54124229617f57d1940c2e8d17cf0 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 11:34:14 +0100 Subject: [PATCH 094/151] More simplifications to blkback: 1. Remove blkif->status field as it's really not needed. 2. Simplify connection logic. 3. Get rid of atomic_t io_pending. There's no need for atomic r-m-w updates to the work-to-do flag, so replace with an integer and add barriers where serialisation is required. Signed-off-by: Keir Fraser --- .../drivers/xen/blkback/blkback.c | 29 ++++++++-------- .../drivers/xen/blkback/common.h | 6 ++-- .../drivers/xen/blkback/interface.c | 4 --- .../drivers/xen/blkback/xenbus.c | 33 ++++++------------- 4 files changed, 27 insertions(+), 45 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 477cab4bc6..4faf117069 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -225,16 +225,16 @@ int blkif_schedule(void *arg) while (!kthread_should_stop()) { wait_event_interruptible( blkif->wq, - atomic_read(&blkif->io_pending) || - kthread_should_stop()); + blkif->waiting_reqs || kthread_should_stop()); wait_event_interruptible( pending_free_wq, - !list_empty(&pending_free) || - kthread_should_stop()); + !list_empty(&pending_free) || kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ - atomic_set(&blkif->io_pending, 0); if (do_block_io_op(blkif)) - atomic_inc(&blkif->io_pending); + blkif->waiting_reqs = 1; unplug_queue(blkif); if (log_stats && time_after(jiffies, blkif->st_print)) @@ -287,12 +287,15 @@ static int end_block_io_op(struct bio *bio, unsigned int done, int error) * NOTIFICATION FROM GUEST OS. */ +void blkif_notify_work(blkif_t *blkif) +{ + blkif->waiting_reqs = 1; + wake_up(&blkif->wq); +} + irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) { - blkif_t *blkif = dev_id; - - atomic_inc(&blkif->io_pending); - wake_up(&blkif->wq); + blkif_notify_work(dev_id); return IRQ_HANDLED; } @@ -512,10 +515,8 @@ static void make_response(blkif_t *blkif, unsigned long id, } spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); - if (more_to_do) { - atomic_inc(&blkif->io_pending); - wake_up(&blkif->wq); - } + if (more_to_do) + blkif_notify_work(blkif); if (notify) notify_remote_via_irq(blkif->irq); } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index 502a02c6b8..58939d6ab2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -72,7 +72,6 @@ typedef struct blkif_st { /* Back pointer to the backend_info. */ struct backend_info *be; /* Private fields. */ - enum { DISCONNECTED, CONNECTED } status; #ifdef CONFIG_XEN_BLKDEV_TAP_BE /* Is this a blktap frontend */ unsigned int is_blktap; @@ -82,7 +81,7 @@ typedef struct blkif_st { wait_queue_head_t wq; struct task_struct *xenblkd; - atomic_t io_pending; + unsigned int waiting_reqs; request_queue_t *plug; /* statistics */ @@ -130,11 +129,10 @@ void blkif_interface_init(void); void blkif_xenbus_init(void); +void blkif_notify_work(blkif_t *blkif); irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); int blkif_schedule(void *arg); -void update_blkif_status(blkif_t *blkif); - #endif /* __BLKIF__BACKEND__COMMON_H__ */ /* diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index 75b9f74b0b..c220efcf4b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -45,7 +45,6 @@ blkif_t *alloc_blkif(domid_t domid) memset(blkif, 0, sizeof(*blkif)); blkif->domid = domid; - blkif->status = DISCONNECTED; spin_lock_init(&blkif->blk_ring_lock); atomic_set(&blkif->refcnt, 1); init_waitqueue_head(&blkif->wq); @@ -138,9 +137,6 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) blkif->irq = bind_evtchn_to_irqhandler( blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); - /* We're potentially connected now */ - update_blkif_status(blkif); - return 0; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 636caefdd8..d0ec094d66 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -17,7 +17,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include #include @@ -25,36 +24,33 @@ #include "common.h" #undef DPRINTK -#define DPRINTK(fmt, args...) \ - pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) - +#define DPRINTK(fmt, args...) \ + pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \ + __FUNCTION__, __LINE__, ##args) struct backend_info { struct xenbus_device *dev; blkif_t *blkif; struct xenbus_watch backend_watch; - unsigned major; unsigned minor; char *mode; }; - -static void maybe_connect(struct backend_info *); static void connect(struct backend_info *); static int connect_ring(struct backend_info *); static void backend_changed(struct xenbus_watch *, const char **, unsigned int); -void update_blkif_status(blkif_t *blkif) +static void update_blkif_status(blkif_t *blkif) { - if(blkif->irq && blkif->vbd.bdev) { - blkif->status = CONNECTED; - (void)blkif_be_int(0, blkif, NULL); + if (blkif->irq && blkif->vbd.bdev && + (blkif->be->dev->state != XenbusStateConnected)) { + connect(blkif->be); + blkif_notify_work(blkif); } - maybe_connect(blkif->be); } @@ -91,7 +87,6 @@ static int blkback_remove(struct xenbus_device *dev) be->backend_watch.node = NULL; } if (be->blkif) { - be->blkif->status = DISCONNECTED; if (be->blkif->xenblkd) kthread_stop(be->blkif->xenblkd); blkif_put(be->blkif); @@ -185,8 +180,8 @@ static void backend_changed(struct xenbus_watch *watch, return; } - if (be->major && be->minor && - (be->major != major || be->minor != minor)) { + if ((be->major || be->minor) && + ((be->major != major) || (be->minor != minor))) { printk(KERN_WARNING "blkback: changing physical device (from %x:%x to " "%x:%x) not supported.\n", be->major, be->minor, @@ -290,14 +285,6 @@ static void frontend_changed(struct xenbus_device *dev, /* ** Connection ** */ -static void maybe_connect(struct backend_info *be) -{ - if ((be->major != 0 || be->minor != 0) && - be->blkif->status == CONNECTED) - connect(be); -} - - /** * Write the physical details regarding the block device to the store, and * switch to Connected state. From d366b69d6ad3d584408c253d3d52398c3d5c48b3 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Thu, 6 Apr 2006 12:03:53 +0100 Subject: [PATCH 095/151] Add new hypercall "set_callback" taking a callback identifier and the callback address. This new hypercall incorporates the functionality of the existing set_callbacks hypercall in a more flexible manner. set_callbacks is retained for compatibility. Signed-off-by: Ian Campbell --- .../include/asm-i386/mach-xen/asm/hypercall.h | 8 ++ .../asm-i386/mach-xen/setup_arch_post.h | 15 ++- .../asm-x86_64/mach-xen/asm/hypercall.h | 7 ++ .../asm-x86_64/mach-xen/setup_arch_post.h | 21 +++- xen/arch/x86/x86_32/entry.S | 2 + xen/arch/x86/x86_32/traps.c | 100 ++++++++++++++++-- xen/arch/x86/x86_64/entry.S | 2 + xen/arch/x86/x86_64/traps.c | 100 +++++++++++++++++- xen/include/public/arch-x86_32.h | 5 + xen/include/public/arch-x86_64.h | 2 + xen/include/public/callback.h | 57 ++++++++++ xen/include/public/xen.h | 1 + 12 files changed, 301 insertions(+), 19 deletions(-) create mode 100644 xen/include/public/callback.h diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h index 20977d0b80..d789fa3ae0 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h @@ -329,6 +329,14 @@ HYPERVISOR_nmi_op( return _hypercall2(int, nmi_op, op, arg); } +static inline int +HYPERVISOR_callback_op( + int cmd, + void *arg) +{ + return _hypercall2(int, callback_op, cmd, arg); +} + #endif /* __HYPERCALL_H__ */ /* diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h index 646cf78578..ef697fde73 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h @@ -6,6 +6,8 @@ * use of all of the static functions. **/ +#include + static char * __init machine_specific_memory_setup(void) { unsigned long max_pfn = xen_start_info->nr_pages; @@ -23,6 +25,14 @@ extern void nmi(void); static void __init machine_specific_arch_setup(void) { struct xen_platform_parameters pp; + callback_register_t event = { + .type = CALLBACKTYPE_event, + .address = { __KERNEL_CS, (unsigned long)hypervisor_callback }, + }; + callback_register_t failsafe = { + .type = CALLBACKTYPE_failsafe, + .address = { __KERNEL_CS, (unsigned long)failsafe_callback }, + }; struct xennmi_callback cb; if (xen_feature(XENFEAT_auto_translated_physmap) && @@ -32,9 +42,8 @@ static void __init machine_specific_arch_setup(void) memset(empty_zero_page, 0, sizeof(empty_zero_page)); } - HYPERVISOR_set_callbacks( - __KERNEL_CS, (unsigned long)hypervisor_callback, - __KERNEL_CS, (unsigned long)failsafe_callback); + HYPERVISOR_callback_op(CALLBACKOP_register, &event); + HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); cb.handler_address = (unsigned long)&nmi; HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h index 6b7411f4c5..24f0762374 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h @@ -330,6 +330,13 @@ HYPERVISOR_nmi_op( return _hypercall2(int, nmi_op, op, arg); } +static inline int +HYPERVISOR_callback_op( + int cmd, void *arg) +{ + return _hypercall2(int, callback_op, cmd, arg); +} + #endif /* __HYPERCALL_H__ */ /* diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h index 701190a49b..c48ef6cbb3 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h @@ -6,20 +6,33 @@ * use of all of the static functions. **/ +#include + extern void hypervisor_callback(void); extern void failsafe_callback(void); extern void nmi(void); static void __init machine_specific_arch_setup(void) { + callback_register_t event = { + .type = CALLBACKTYPE_event, + .address = (unsigned long) hypervisor_callback, + }; + callback_register_t failsafe = { + .type = CALLBACKTYPE_failsafe, + .address = (unsigned long)failsafe_callback, + }; + callback_register_t syscall = { + .type = CALLBACKTYPE_syscall, + .address = (unsigned long)system_call, + }; #ifdef CONFIG_X86_LOCAL_APIC struct xennmi_callback cb; #endif - HYPERVISOR_set_callbacks( - (unsigned long) hypervisor_callback, - (unsigned long) failsafe_callback, - (unsigned long) system_call); + HYPERVISOR_callback_op(CALLBACKOP_register, &event); + HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe); + HYPERVISOR_callback_op(CALLBACKOP_register, &syscall); #ifdef CONFIG_X86_LOCAL_APIC cb.handler_address = (unsigned long)&nmi; diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index b19796bbac..049dc5ced5 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -648,6 +648,7 @@ ENTRY(hypercall_table) .long do_acm_op .long do_nmi_op .long do_arch_sched_op + .long do_callback_op /* 30 */ .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -683,6 +684,7 @@ ENTRY(hypercall_args_table) .byte 1 /* do_acm_op */ .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ + .byte 2 /* do_callback_op */ /* 30 */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 59d1a845a8..f0dc661821 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -14,6 +14,8 @@ #include #include +#include + /* All CPUs have their own IDT to allow int80 direct trap. */ idt_entry_t *idt_tables[NR_CPUS] = { 0 }; @@ -315,20 +317,102 @@ void init_int80_direct_trap(struct vcpu *v) set_int80_direct_trap(v); } +static long register_guest_callback(struct callback_register *reg) +{ + long ret = 0; + struct vcpu *v = current; + + if ( reg->address.cs ) + fixup_guest_code_selector(reg->address.cs); + + switch ( reg->type ) + { + case CALLBACKTYPE_event: + v->arch.guest_context.event_callback_cs = reg->address.cs; + v->arch.guest_context.event_callback_eip = reg->address.eip; + break; + + case CALLBACKTYPE_failsafe: + v->arch.guest_context.failsafe_callback_cs = reg->address.cs; + v->arch.guest_context.failsafe_callback_eip = reg->address.eip; + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static long unregister_guest_callback(struct callback_unregister *unreg) +{ + long ret; + + switch ( unreg->type ) + { + default: + ret = -EINVAL; + break; + } + return ret; +} + + +long do_callback_op(int cmd, GUEST_HANDLE(void) arg) +{ + long ret; + + switch ( cmd ) + { + case CALLBACKOP_register: + { + struct callback_register reg; + + ret = -EFAULT; + if ( copy_from_guest( ®, arg, 1 ) ) + break; + + ret = register_guest_callback(®); + } + break; + + case CALLBACKOP_unregister: + { + struct callback_unregister unreg; + + ret = -EFAULT; + if ( copy_from_guest( &unreg, arg, 1 ) ) + break; + + ret = unregister_guest_callback(&unreg); + } + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + long do_set_callbacks(unsigned long event_selector, unsigned long event_address, unsigned long failsafe_selector, unsigned long failsafe_address) { - struct vcpu *d = current; + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = { event_selector, event_address }, + }; + struct callback_register failsafe = { + .type = CALLBACKTYPE_failsafe, + .address = { failsafe_selector, failsafe_address }, + }; - fixup_guest_code_selector(event_selector); - fixup_guest_code_selector(failsafe_selector); - - d->arch.guest_context.event_callback_cs = event_selector; - d->arch.guest_context.event_callback_eip = event_address; - d->arch.guest_context.failsafe_callback_cs = failsafe_selector; - d->arch.guest_context.failsafe_callback_eip = failsafe_address; + register_guest_callback(&event); + register_guest_callback(&failsafe); return 0; } diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 6176188a85..622ca4d7cc 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -557,6 +557,7 @@ ENTRY(hypercall_table) .quad do_acm_op .quad do_nmi_op .quad do_arch_sched_op + .quad do_callback_op /* 30 */ .rept NR_hypercalls-((.-hypercall_table)/8) .quad do_ni_hypercall .endr @@ -592,6 +593,7 @@ ENTRY(hypercall_args_table) .byte 1 /* do_acm_op */ .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ + .byte 2 /* do_callback_op */ /* 30 */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 6794cefecf..ddf7b0aa30 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -17,6 +17,8 @@ #include #include +#include + void show_registers(struct cpu_user_regs *regs) { struct cpu_user_regs fault_regs = *regs; @@ -312,15 +314,105 @@ void __init percpu_traps_init(void) wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); } +static long register_guest_callback(struct callback_register *reg) +{ + long ret = 0; + struct vcpu *v = current; + + switch ( reg->type ) + { + case CALLBACKTYPE_event: + v->arch.guest_context.event_callback_eip = reg->address; + break; + + case CALLBACKTYPE_failsafe: + v->arch.guest_context.failsafe_callback_eip = reg->address; + break; + + case CALLBACKTYPE_syscall: + v->arch.guest_context.syscall_callback_eip = reg->address; + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static long unregister_guest_callback(struct callback_unregister *unreg) +{ + long ret; + + switch ( unreg->type ) + { + default: + ret = -EINVAL; + break; + } + return ret; +} + + +long do_callback_op(int cmd, GUEST_HANDLE(void) arg) +{ + long ret; + + switch ( cmd ) + { + case CALLBACKOP_register: + { + struct callback_register reg; + + ret = -EFAULT; + if ( copy_from_guest( ®, arg, 1 ) ) + break; + + ret = register_guest_callback(®); + } + break; + + case CALLBACKOP_unregister: + { + struct callback_unregister unreg; + + ret = -EFAULT; + if ( copy_from_guest( &unreg, arg, 1 ) ) + break; + + ret = unregister_guest_callback(&unreg); + } + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + long do_set_callbacks(unsigned long event_address, unsigned long failsafe_address, unsigned long syscall_address) { - struct vcpu *d = current; + callback_register_t event = { + .type = CALLBACKTYPE_event, + .address = event_address, + }; + callback_register_t failsafe = { + .type = CALLBACKTYPE_failsafe, + .address = failsafe_address, + }; + callback_register_t syscall = { + .type = CALLBACKTYPE_syscall, + .address = syscall_address, + }; - d->arch.guest_context.event_callback_eip = event_address; - d->arch.guest_context.failsafe_callback_eip = failsafe_address; - d->arch.guest_context.syscall_callback_eip = syscall_address; + register_guest_callback(&event); + register_guest_callback(&failsafe); + register_guest_callback(&syscall); return 0; } diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 1ae2df6f14..a723837f48 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -168,6 +168,11 @@ typedef struct { unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */ } arch_vcpu_info_t; +typedef struct { + unsigned long cs; + unsigned long eip; +} xen_callback_t; + #endif /* !__ASSEMBLY__ */ /* diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 98948c4ff5..d8b978436a 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -244,6 +244,8 @@ typedef struct { unsigned long pad; /* sizeof(vcpu_info_t) == 64 */ } arch_vcpu_info_t; +typedef unsigned long xen_callback_t; + #endif /* !__ASSEMBLY__ */ /* diff --git a/xen/include/public/callback.h b/xen/include/public/callback.h new file mode 100644 index 0000000000..479333ddb8 --- /dev/null +++ b/xen/include/public/callback.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * callback.h + * + * Register guest OS callbacks with Xen. + * + * Copyright (c) 2006, Ian Campbell + */ + +#ifndef __XEN_PUBLIC_CALLBACK_H__ +#define __XEN_PUBLIC_CALLBACK_H__ + +#include "xen.h" + +/* + * Prototype for this hypercall is: + * long callback_op(int cmd, void *extra_args) + * @cmd == CALLBACKOP_??? (callback operation). + * @extra_args == Operation-specific extra arguments (NULL if none). + */ + +#define CALLBACKTYPE_event 0 +#define CALLBACKTYPE_failsafe 1 +#define CALLBACKTYPE_syscall 2 /* x86_64 only */ + +/* + * Register a callback. + */ +#define CALLBACKOP_register 0 +typedef struct callback_register { + int type; + xen_callback_t address; +} callback_register_t; +DEFINE_GUEST_HANDLE(callback_register_t); + +/* + * Unregister a callback. + * + * Not all callbacks can be unregistered. -EINVAL will be returned if + * you attempt to unregister such a callback. + */ +#define CALLBACKOP_unregister 1 +typedef struct callback_unregister { + int type; +} callback_unregister_t; +DEFINE_GUEST_HANDLE(callback_unregister_t); + +#endif /* __XEN_PUBLIC_CALLBACK_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 1da6ede005..8dba3ad541 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -60,6 +60,7 @@ #define __HYPERVISOR_acm_op 27 #define __HYPERVISOR_nmi_op 28 #define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_callback_op 30 /* * VIRTUAL INTERRUPTS From d5ed151f128f5bcd7efd7ffecfd637041892aae5 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 6 Apr 2006 14:21:45 +0100 Subject: [PATCH 096/151] Fix test to match change to DCE formatting of UUIDs. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/tests/test_uuid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/tests/test_uuid.py b/tools/python/xen/xend/tests/test_uuid.py index d79ab53e4a..d96c9043e1 100644 --- a/tools/python/xen/xend/tests/test_uuid.py +++ b/tools/python/xen/xend/tests/test_uuid.py @@ -21,9 +21,9 @@ class test_uuid(unittest.TestCase): self.assertEqual(uuid.toString(inp), expected) self.assertEqual(uuid.fromString(expected), inp) - t([0 for _ in range(0, 16)], "00000000-00000000-00000000-00000000") + t([0 for _ in range(0, 16)], "00000000-0000-0000-0000-000000000000") t([185, 158, 125, 206, 250, 178, 125, 57, 2, 6, 162, 74, 178, 236, - 196, 5], "b99e7dce-fab27d39-0206a24a-b2ecc405") + 196, 5], "b99e7dce-fab2-7d39-0206-a24ab2ecc405") def test_suite(): From 45bd0044c4481f4d0469cdaea78b22ae08a33412 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 6 Apr 2006 14:22:52 +0100 Subject: [PATCH 097/151] Factor out the parsing of XAUTHORITY, so that it can be used by the unit test, and fix that test to use it. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/create.py | 21 +++++++++++++-------- tools/python/xen/xm/tests/test_create.py | 7 +++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 6da9ed3711..8c3be846bd 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -850,6 +850,18 @@ def make_domain(opts, config): opts.info("Started domain %s" % (dom)) return int(sxp.child_value(dominfo, 'domid')) + +def get_xauthority(): + xauth = os.getenv("XAUTHORITY") + if not xauth: + home = os.getenv("HOME") + if not home: + import posix, pwd + home = pwd.getpwuid(posix.getuid())[5] + xauth = home + "/.Xauthority" + return xauth + + def parseCommandLine(argv): gopts.reset() args = gopts.parse(argv) @@ -864,14 +876,7 @@ def parseCommandLine(argv): gopts.vals.display = os.getenv("DISPLAY") if not gopts.vals.xauthority: - xauth = os.getenv("XAUTHORITY") - if not xauth: - home = os.getenv("HOME") - if not home: - import posix, pwd - home = pwd.getpwuid(posix.getuid())[5] - xauth = home + "/.Xauthority" - gopts.vals.xauthority = xauth + gopts.vals.xauthority = get_xauthority() # Process remaining args as config variables. for arg in args: diff --git a/tools/python/xen/xm/tests/test_create.py b/tools/python/xen/xm/tests/test_create.py index 4cce721ea0..7bbe709834 100644 --- a/tools/python/xen/xm/tests/test_create.py +++ b/tools/python/xen/xm/tests/test_create.py @@ -51,6 +51,7 @@ class test_create(unittest.TestCase): 'path' : '.:/etc/xen', 'builder' : 'linux', 'nics' : -1, + 'xauthority': xen.xm.create.get_xauthority(), }) @@ -99,6 +100,8 @@ on_crash = 'destroy' 'interface' : 'eth0', 'path' : '.:/etc/xen', 'builder' : 'linux', + + 'xauthority' : xen.xm.create.get_xauthority(), }) @@ -138,6 +141,8 @@ cpu_weight = 0.75 'path' : '.:/etc/xen', 'builder' : 'linux', 'nics' : -1, + + 'xauthority' : xen.xm.create.get_xauthority(), }) @@ -188,6 +193,8 @@ ne2000=0 'dhcp' : 'off', 'interface' : 'eth0', 'path' : '.:/etc/xen', + + 'xauthority' : xen.xm.create.get_xauthority(), }) From 4d9b8db9fc68d7b4ed8839eb2c6576d895f0a183 Mon Sep 17 00:00:00 2001 From: "apeace@paploo.uk.xensource.com" Date: Thu, 6 Apr 2006 14:58:55 +0100 Subject: [PATCH 098/151] Fix the example xend init.d script so it correctly detects when it is running in a guest. Signed-off by: Andrew Peace --- tools/examples/init.d/xend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/examples/init.d/xend b/tools/examples/init.d/xend index c789d5d28d..8ad407637c 100755 --- a/tools/examples/init.d/xend +++ b/tools/examples/init.d/xend @@ -7,7 +7,7 @@ # chkconfig: 2345 98 01 # description: Starts and stops the Xen control daemon. -if ! [ -e /proc/xen/privcmd ]; then +if ! grep -q "control_d" /proc/xen/capabilities ; then exit 0 fi From f0a187ecb73186b1fbb7eae3fd0ba6ff8d602e1a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 15:22:46 +0100 Subject: [PATCH 099/151] Move misplaced CONFIG_KEXEC code chunk in setup-xen.c to its proper location. From: Jan Beulich Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c index 11d17a7a12..b738343e89 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c @@ -1317,6 +1317,11 @@ void __init setup_bootmem_allocator(void) } } #endif +#ifdef CONFIG_KEXEC + if (crashk_res.start != crashk_res.end) + reserve_bootmem(crashk_res.start, + crashk_res.end - crashk_res.start + 1); +#endif if (!xen_feature(XENFEAT_auto_translated_physmap)) phys_to_machine_mapping = @@ -1436,11 +1441,6 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat } } #endif -#ifdef CONFIG_KEXEC - if (crashk_res.start != crashk_res.end) - reserve_bootmem(crashk_res.start, - crashk_res.end - crashk_res.start + 1); -#endif } /* From 66edd49a38a5f5eb57e12b1302adae2e7bc05594 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 15:24:00 +0100 Subject: [PATCH 100/151] Add code to make handling domain poweroff/reboot symmetrical between paravirtualized and fully virtualized. This approach uses the new sched_op to handle other domains than the current domain. The new code, SCHEDOP_remote_shutdown, is very much like SCHEDOP_shutdown, but is called with the id of the domain which is to be shut down. This allows fully virtualized shutdown and para-virtualized shutdown to be identical from that point forward. A paravirtualized domain uses sched_op to shut down and set the reason code. This will send a VIRQ_DOM_EXC, which can be handled in dom0 by control software. In some ways, this resembles SIGCHILD/waitpid, and is a reasonable model. The fully virtualized case has qemu invoke xm directly. This is a different path than paravirtualized. It also removes decision and policy making choices from the rest of the control software and places it within qemu. When any dom0 logic eventually gets a VIRQ_DOM_EXC, the information about the domain is gone having been destroyed by xm. A libxenctrl wrapper, xc_shutdown_domain has been added and qemu now calls it. As a freebie, #if 0 some very verbose logging code in qemu. Totally unrelated, but as long as I was there... Signed-off-by: Ben Thomas --- .../drivers/xen/privcmd/privcmd.c | 1 + tools/ioemu/target-i386-dm/helper2.c | 41 ++++++++++++++----- tools/ioemu/vl.c | 2 + tools/libxc/xc_domain.c | 29 +++++++++++++ tools/libxc/xenctrl.h | 15 +++++++ xen/common/schedule.c | 24 +++++++++++ xen/include/public/sched.h | 13 ++++++ 7 files changed, 114 insertions(+), 11 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index 52364f9aeb..e572fa7c79 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -277,6 +277,7 @@ static int __init privcmd_init(void) set_bit(__HYPERVISOR_mmu_update, hypercall_permission_map); set_bit(__HYPERVISOR_mmuext_op, hypercall_permission_map); set_bit(__HYPERVISOR_xen_version, hypercall_permission_map); + set_bit(__HYPERVISOR_sched_op, hypercall_permission_map); privcmd_intf = create_xen_proc_entry("privcmd", 0400); if (privcmd_intf != NULL) diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index af4a8e8d8b..a596c6edab 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -409,12 +409,20 @@ int xc_handle; void destroy_hvm_domain(void) { - extern FILE* logfile; - char destroy_cmd[32]; - - sprintf(destroy_cmd, "xm destroy %d", domid); - if (system(destroy_cmd) == -1) - fprintf(logfile, "%s failed.!\n", destroy_cmd); + int xcHandle; + int sts; + + xcHandle = xc_interface_open(); + if (xcHandle < 0) + fprintf(logfile, "Cannot acquire xenctrl handle\n"); + else { + sts = xc_domain_shutdown(xcHandle, domid, SHUTDOWN_poweroff); + if (sts != 0) + fprintf(logfile, "? xc_domain_shutdown failed to issue poweroff, sts %d, errno %d\n", sts, errno); + else + fprintf(logfile, "Issued domain %d poweroff\n", domid); + xc_interface_close(xcHandle); + } } fd_set wakeup_rfds; @@ -480,13 +488,24 @@ int main_loop(void) static void qemu_hvm_reset(void *unused) { - char cmd[64]; + int xcHandle; + int sts; - /* pause domain first, to avoid repeated reboot request*/ - xc_domain_pause(xc_handle, domid); + /* pause domain first, to avoid repeated reboot request*/ + xc_domain_pause(xc_handle, domid); - sprintf(cmd, "xm shutdown -R %d", domid); - system(cmd); + xcHandle = xc_interface_open(); + if (xcHandle < 0) + fprintf(logfile, "Cannot acquire xenctrl handle\n"); + else { + sts = xc_domain_shutdown(xcHandle, domid, SHUTDOWN_reboot); + if (sts != 0) + fprintf(logfile, "? xc_domain_shutdown failed to issue reboot, sts %d\n", sts); + else + fprintf(logfile, "Issued domain %d reboot\n", domid); + xc_interface_close(xcHandle); + } + } CPUState * cpu_init() diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 6586f77deb..da009dd11b 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2556,8 +2556,10 @@ static int set_mm_mapping(int xc_handle, return -1; } +#if 0 /* Generates lots of log file output - turn on for debugging */ for (i = 0; i < nr_pages; i++) fprintf(stderr, "set_map result i %x result %lx\n", i, extent_start[i]); +#endif return 0; } diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index ea2ca76d1b..3b9abd11f8 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -58,6 +58,35 @@ int xc_domain_destroy(int xc_handle, return do_dom0_op(xc_handle, &op); } +int xc_domain_shutdown(int xc_handle, + uint32_t domid, + int reason) +{ + int ret = -1; + sched_remote_shutdown_t arg; + DECLARE_HYPERCALL; + + hypercall.op = __HYPERVISOR_sched_op; + hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown; + hypercall.arg[1] = (unsigned long)&arg; + arg.domain_id = domid; + arg.reason = reason; + + if ( mlock(&arg, sizeof(arg)) != 0 ) + { + PERROR("Could not lock memory for Xen hypercall"); + goto out1; + } + + ret = do_xen_hypercall(xc_handle, &hypercall); + + safe_munlock(&arg, sizeof(arg)); + + out1: + return ret; +} + + int xc_vcpu_setaffinity(int xc_handle, uint32_t domid, int vcpu, diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index fce21b7334..3bc124d77d 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -206,6 +206,21 @@ int xc_domain_unpause(int xc_handle, int xc_domain_destroy(int xc_handle, uint32_t domid); +/** + * This function will shutdown a domain. This is intended for use in + * fully-virtualized domains where this operation is analogous to the + * sched_op operations in a paravirtualized domain. The caller is + * expected to give the reason for the shutdown. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain id to destroy + * @parm reason is the reason (SHUTDOWN_xxx) for the shutdown + * @return 0 on success, -1 on failure + */ +int xc_domain_shutdown(int xc_handle, + uint32_t domid, + int reason); + int xc_vcpu_setaffinity(int xc_handle, uint32_t domid, int vcpu, diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 0b1644ea5a..5fe6cb4304 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -413,6 +413,30 @@ long do_sched_op(int cmd, GUEST_HANDLE(void) arg) break; } + case SCHEDOP_remote_shutdown: + { + struct domain *d; + struct sched_remote_shutdown sched_remote_shutdown; + + if ( !IS_PRIV(current->domain) ) + return -EPERM; + + ret = -EFAULT; + if ( copy_from_guest(&sched_remote_shutdown, arg, 1) ) + break; + + ret = -ESRCH; + d = find_domain_by_id(sched_remote_shutdown.domain_id); + if ( d == NULL ) + break; + + domain_shutdown(d, (u8)sched_remote_shutdown.reason); + put_domain(d); + ret = 0; + + break; + } + default: ret = -ENOSYS; } diff --git a/xen/include/public/sched.h b/xen/include/public/sched.h index 28e86c0d76..27f321e080 100644 --- a/xen/include/public/sched.h +++ b/xen/include/public/sched.h @@ -64,6 +64,19 @@ typedef struct sched_poll { } sched_poll_t; DEFINE_GUEST_HANDLE(sched_poll_t); +/* + * Declare a shutdown for another domain. The main use of this function is + * in interpreting shutdown requests and reasons for fully-virtualized + * domains. A para-virtualized domain may use SCHEDOP_shutdown directly. + * @arg == pointer to sched_remote_shutdown structure. + */ +#define SCHEDOP_remote_shutdown 4 +typedef struct sched_remote_shutdown { + domid_t domain_id; /* Remote domain ID */ + unsigned int reason; /* SHUTDOWN_xxx reason */ +} sched_remote_shutdown_t; +DEFINE_GUEST_HANDLE(sched_remote_shutdown_t); + /* * Reason codes for SCHEDOP_shutdown. These may be interpreted by control * software to determine the appropriate action. For the most part, Xen does From 535f8b893f9415eb77020400ec6206b7dbe7e54a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 15:25:26 +0100 Subject: [PATCH 101/151] Clean up files created by the XenLinux boot-xen code. Signed-Off-By: Magnus Damm --- linux-2.6-xen-sparse/arch/i386/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-2.6-xen-sparse/arch/i386/Makefile b/linux-2.6-xen-sparse/arch/i386/Makefile index 54ee32ee57..99a8fa2aaa 100644 --- a/linux-2.6-xen-sparse/arch/i386/Makefile +++ b/linux-2.6-xen-sparse/arch/i386/Makefile @@ -162,3 +162,4 @@ define archhelp endef CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf +CLEAN_FILES += vmlinuz vmlinux-stripped From deecd6adc0193e8d10881e366156885f918e150b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 15:55:37 +0100 Subject: [PATCH 102/151] Saner error handling in iret hypercall (x86/64). Signed-off-by: Keir Fraser --- xen/arch/x86/x86_64/traps.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index ddf7b0aa30..fcc188364b 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -186,13 +186,19 @@ unsigned long do_iret(void) if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, sizeof(iret_saved))) ) + { + DPRINTK("Fault while reading IRET context from guest stack\n"); domain_crash_synchronous(); + } /* Returning to user mode? */ if ( (iret_saved.cs & 3) == 3 ) { if ( unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) - return -EFAULT; + { + DPRINTK("Guest switching to user mode with no user page tables\n"); + domain_crash_synchronous(); + } toggle_guest_mode(v); } From 9444c07bdb26be151c6566fd703fa3b5c403e8d4 Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 16:15:28 +0100 Subject: [PATCH 103/151] Fix long-standing save/restore bug on x86-64. Signed-off-by: Steven Hand --- .../drivers/xen/core/reboot.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index 990dc35cee..ba0b9b9112 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -85,6 +85,23 @@ void smp_resume(void); #define smp_resume() ((void)0) #endif +/* Ensure we run on the idle task page tables so that we will + switch page tables before running user space. This is needed + on architectures with separate kernel and user page tables + because the user page table pointer is not saved/restored. */ +static void switch_idle_mm(void) +{ + struct mm_struct *mm = current->active_mm; + + if (mm == &init_mm) + return; + + atomic_inc(&init_mm.mm_count); + switch_mm(mm, &init_mm, current); + current->active_mm = &init_mm; + mmdrop(mm); +} + static int __do_suspend(void *ignore) { int i, j, k, fpp, err; @@ -164,6 +181,8 @@ static int __do_suspend(void *ignore) time_resume(); + switch_idle_mm(); + __sti(); xencons_resume(); From 7f21016a22a3f28f0ef8aba35f29a81b0cc2d5c5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 16:41:53 +0100 Subject: [PATCH 104/151] Use machine_halt() where it makes sense, to halt all processors rather than just the current one. Signed-off-by: Keir Fraser --- xen/arch/x86/shutdown.c | 2 +- xen/arch/x86/traps.c | 4 ++-- xen/arch/x86/x86_32/traps.c | 4 ++-- xen/arch/x86/x86_64/traps.c | 4 ++-- xen/drivers/char/console.c | 1 + 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c index e3cd61085a..97b41a94ca 100644 --- a/xen/arch/x86/shutdown.c +++ b/xen/arch/x86/shutdown.c @@ -44,7 +44,7 @@ static inline void kb_wait(void) void __attribute__((noreturn)) __machine_halt(void *unused) { for ( ; ; ) - safe_halt(); + __asm__ __volatile__ ( "hlt" ); } void machine_halt(void) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 2856f75a0c..72272f30ca 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -318,8 +319,7 @@ asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs) console_force_lock(); /* Wait for manual reset. */ - for ( ; ; ) - __asm__ __volatile__ ( "hlt" ); + machine_halt(); } static inline int do_trap(int trapnr, char *str, diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index f0dc661821..d99fecdae9 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -180,8 +181,7 @@ asmlinkage void do_double_fault(void) console_force_lock(); /* Wait for manual reset. */ - for ( ; ; ) - __asm__ __volatile__ ( "hlt" ); + machine_halt(); } unsigned long do_iret(void) diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index fcc188364b..f7dd3e939f 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -166,8 +167,7 @@ asmlinkage void do_double_fault(struct cpu_user_regs *regs) console_force_lock(); /* Wait for manual reset. */ - for ( ; ; ) - __asm__ __volatile__ ( "hlt" ); + machine_halt(); } void toggle_guest_mode(struct vcpu *v) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index df4706bcb2..948000c743 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -520,6 +520,7 @@ void console_force_unlock(void) { console_lock = SPIN_LOCK_UNLOCKED; serial_force_unlock(sercon_handle); + console_start_sync(); } void console_force_lock(void) From 1da49c151eba67cd3ae817234397b08c807625e9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 17:25:24 +0100 Subject: [PATCH 105/151] Cleanups to do_callback_op() new hypercall changeset. Signed-off-by: Keir Fraser --- .../include/asm-i386/mach-xen/asm/hypercall.h | 3 +-- .../include/asm-i386/mach-xen/setup_arch_post.h | 4 ++-- .../include/asm-x86_64/mach-xen/setup_arch_post.h | 6 +++--- xen/arch/x86/x86_32/traps.c | 8 ++++---- xen/arch/x86/x86_64/traps.c | 11 ++++++----- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h index d789fa3ae0..088b182c1c 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h @@ -331,8 +331,7 @@ HYPERVISOR_nmi_op( static inline int HYPERVISOR_callback_op( - int cmd, - void *arg) + int cmd, void *arg) { return _hypercall2(int, callback_op, cmd, arg); } diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h index ef697fde73..71d0258b8d 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h @@ -25,11 +25,11 @@ extern void nmi(void); static void __init machine_specific_arch_setup(void) { struct xen_platform_parameters pp; - callback_register_t event = { + struct callback_register event = { .type = CALLBACKTYPE_event, .address = { __KERNEL_CS, (unsigned long)hypervisor_callback }, }; - callback_register_t failsafe = { + struct callback_register failsafe = { .type = CALLBACKTYPE_failsafe, .address = { __KERNEL_CS, (unsigned long)failsafe_callback }, }; diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h index c48ef6cbb3..f2342b0097 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h @@ -14,15 +14,15 @@ extern void nmi(void); static void __init machine_specific_arch_setup(void) { - callback_register_t event = { + struct callback_register event = { .type = CALLBACKTYPE_event, .address = (unsigned long) hypervisor_callback, }; - callback_register_t failsafe = { + struct callback_register failsafe = { .type = CALLBACKTYPE_failsafe, .address = (unsigned long)failsafe_callback, }; - callback_register_t syscall = { + struct callback_register syscall = { .type = CALLBACKTYPE_syscall, .address = (unsigned long)system_call, }; diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index d99fecdae9..085c126153 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -322,8 +322,7 @@ static long register_guest_callback(struct callback_register *reg) long ret = 0; struct vcpu *v = current; - if ( reg->address.cs ) - fixup_guest_code_selector(reg->address.cs); + fixup_guest_code_selector(reg->address.cs); switch ( reg->type ) { @@ -355,6 +354,7 @@ static long unregister_guest_callback(struct callback_unregister *unreg) ret = -EINVAL; break; } + return ret; } @@ -370,7 +370,7 @@ long do_callback_op(int cmd, GUEST_HANDLE(void) arg) struct callback_register reg; ret = -EFAULT; - if ( copy_from_guest( ®, arg, 1 ) ) + if ( copy_from_guest(®, arg, 1) ) break; ret = register_guest_callback(®); @@ -382,7 +382,7 @@ long do_callback_op(int cmd, GUEST_HANDLE(void) arg) struct callback_unregister unreg; ret = -EFAULT; - if ( copy_from_guest( &unreg, arg, 1 ) ) + if ( copy_from_guest(&unreg, arg, 1) ) break; ret = unregister_guest_callback(&unreg); diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index f7dd3e939f..4f5ff5ba11 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -357,6 +357,7 @@ static long unregister_guest_callback(struct callback_unregister *unreg) ret = -EINVAL; break; } + return ret; } @@ -372,7 +373,7 @@ long do_callback_op(int cmd, GUEST_HANDLE(void) arg) struct callback_register reg; ret = -EFAULT; - if ( copy_from_guest( ®, arg, 1 ) ) + if ( copy_from_guest(®, arg, 1) ) break; ret = register_guest_callback(®); @@ -384,7 +385,7 @@ long do_callback_op(int cmd, GUEST_HANDLE(void) arg) struct callback_unregister unreg; ret = -EFAULT; - if ( copy_from_guest( &unreg, arg, 1 ) ) + if ( copy_from_guest(&unreg, arg, 1) ) break; ret = unregister_guest_callback(&unreg); @@ -403,15 +404,15 @@ long do_set_callbacks(unsigned long event_address, unsigned long failsafe_address, unsigned long syscall_address) { - callback_register_t event = { + struct callback_register event = { .type = CALLBACKTYPE_event, .address = event_address, }; - callback_register_t failsafe = { + struct callback_register failsafe = { .type = CALLBACKTYPE_failsafe, .address = failsafe_address, }; - callback_register_t syscall = { + struct callback_register syscall = { .type = CALLBACKTYPE_syscall, .address = syscall_address, }; From 6ff686de51416a4819098761fd1930029708c23b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 17:32:47 +0100 Subject: [PATCH 106/151] Rename and clean up 'error_code' path in entry.S. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_32/entry.S | 64 +++++++++++++++++-------------------- xen/arch/x86/x86_64/entry.S | 57 +++++++++++++++------------------ 2 files changed, 56 insertions(+), 65 deletions(-) diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 049dc5ced5..8efd96fc1d 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -119,7 +119,7 @@ FIX1: SET_XEN_SEGMENTS(a) movl $DBLFLT1,%eax pushl %eax # EIP pushl %esi # error_code/entry_vector - jmp error_code + jmp handle_exception DBLFLT1:GET_CURRENT(%ebx) jmp test_all_events failsafe_callback: @@ -380,14 +380,6 @@ domain_crash_synchronous: call printf jmp __domain_crash_synchronous - ALIGN -process_guest_exception_and_events: - leal VCPU_trap_bounce(%ebx),%edx - testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%edx) - jz test_all_events - call create_bounce_frame - jmp test_all_events - ALIGN ENTRY(ret_from_intr) GET_CURRENT(%ebx) @@ -400,7 +392,7 @@ ENTRY(ret_from_intr) ENTRY(divide_error) pushl $TRAP_divide_error<<16 ALIGN -error_code: +handle_exception: FIXUP_RING0_GUEST_STACK SAVE_ALL_NOSEGREGS(a) SET_XEN_SEGMENTS(a) @@ -419,7 +411,11 @@ error_code: movb UREGS_cs(%esp),%al testl $(3|X86_EFLAGS_VM),%eax jz restore_all_xen - jmp process_guest_exception_and_events + leal VCPU_trap_bounce(%ebx),%edx + testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%edx) + jz test_all_events + call create_bounce_frame + jmp test_all_events exception_with_ints_disabled: movl UREGS_eflags(%esp),%eax @@ -452,71 +448,71 @@ FATAL_exception_with_ints_disabled: ENTRY(coprocessor_error) pushl $TRAP_copro_error<<16 - jmp error_code + jmp handle_exception ENTRY(simd_coprocessor_error) pushl $TRAP_simd_error<<16 - jmp error_code + jmp handle_exception ENTRY(device_not_available) pushl $TRAP_no_device<<16 - jmp error_code + jmp handle_exception ENTRY(debug) pushl $TRAP_debug<<16 - jmp error_code + jmp handle_exception ENTRY(int3) pushl $TRAP_int3<<16 - jmp error_code + jmp handle_exception ENTRY(overflow) pushl $TRAP_overflow<<16 - jmp error_code + jmp handle_exception ENTRY(bounds) pushl $TRAP_bounds<<16 - jmp error_code + jmp handle_exception ENTRY(invalid_op) pushl $TRAP_invalid_op<<16 - jmp error_code + jmp handle_exception ENTRY(coprocessor_segment_overrun) pushl $TRAP_copro_seg<<16 - jmp error_code + jmp handle_exception ENTRY(invalid_TSS) - movw $TRAP_invalid_tss,2(%esp) - jmp error_code + movw $TRAP_invalid_tss,2(%esp) + jmp handle_exception ENTRY(segment_not_present) - movw $TRAP_no_segment,2(%esp) - jmp error_code + movw $TRAP_no_segment,2(%esp) + jmp handle_exception ENTRY(stack_segment) - movw $TRAP_stack_error,2(%esp) - jmp error_code + movw $TRAP_stack_error,2(%esp) + jmp handle_exception ENTRY(general_protection) - movw $TRAP_gp_fault,2(%esp) - jmp error_code + movw $TRAP_gp_fault,2(%esp) + jmp handle_exception ENTRY(alignment_check) - movw $TRAP_alignment_check,2(%esp) - jmp error_code + movw $TRAP_alignment_check,2(%esp) + jmp handle_exception ENTRY(page_fault) - movw $TRAP_page_fault,2(%esp) - jmp error_code + movw $TRAP_page_fault,2(%esp) + jmp handle_exception ENTRY(machine_check) pushl $TRAP_machine_check<<16 - jmp error_code + jmp handle_exception ENTRY(spurious_interrupt_bug) pushl $TRAP_spurious_int<<16 - jmp error_code + jmp handle_exception ENTRY(nmi) #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 622ca4d7cc..6af4a0162b 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -68,7 +68,7 @@ FIX1: popq -15*8-8(%rsp) # error_code/entry_vector leaq DBLFLT1(%rip),%rax pushq %rax # RIP pushq %rsi # error_code/entry_vector - jmp error_code + jmp handle_exception DBLFLT1:GET_CURRENT(%rbx) jmp test_all_events failsafe_callback: @@ -319,15 +319,6 @@ domain_crash_synchronous: call printf jmp __domain_crash_synchronous - ALIGN -/* %rbx: struct vcpu */ -process_guest_exception_and_events: - leaq VCPU_trap_bounce(%rbx),%rdx - testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) - jz test_all_events - call create_bounce_frame - jmp test_all_events - ALIGN /* No special register assumptions. */ ENTRY(ret_from_intr) @@ -338,7 +329,7 @@ ENTRY(ret_from_intr) ALIGN /* No special register assumptions. */ -error_code: +handle_exception: SAVE_ALL testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp) jz exception_with_ints_disabled @@ -351,7 +342,11 @@ error_code: callq *(%rdx,%rax,8) testb $3,UREGS_cs(%rsp) jz restore_all_xen - jmp process_guest_exception_and_events + leaq VCPU_trap_bounce(%rbx),%rdx + testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) + jz test_all_events + call create_bounce_frame + jmp test_all_events /* No special register assumptions. */ exception_with_ints_disabled: @@ -384,90 +379,90 @@ FATAL_exception_with_ints_disabled: ENTRY(divide_error) pushq $0 movl $TRAP_divide_error,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(coprocessor_error) pushq $0 movl $TRAP_copro_error,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(simd_coprocessor_error) pushq $0 movl $TRAP_simd_error,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(device_not_available) pushq $0 movl $TRAP_no_device,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(debug) pushq $0 movl $TRAP_debug,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(int3) pushq $0 movl $TRAP_int3,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(overflow) pushq $0 movl $TRAP_overflow,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(bounds) pushq $0 movl $TRAP_bounds,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(invalid_op) pushq $0 movl $TRAP_invalid_op,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(coprocessor_segment_overrun) pushq $0 movl $TRAP_copro_seg,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(invalid_TSS) movl $TRAP_invalid_tss,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(segment_not_present) movl $TRAP_no_segment,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(stack_segment) movl $TRAP_stack_error,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(general_protection) movl $TRAP_gp_fault,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(alignment_check) movl $TRAP_alignment_check,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(page_fault) movl $TRAP_page_fault,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(machine_check) pushq $0 movl $TRAP_machine_check,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(spurious_interrupt_bug) pushq $0 movl $TRAP_spurious_int,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(double_fault) movl $TRAP_double_fault,4(%rsp) - jmp error_code + jmp handle_exception ENTRY(nmi) pushq $0 From 5e1e26bd96648683705e28b545345ed86380159e Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 17:34:54 +0100 Subject: [PATCH 107/151] Make root page table sanity check on restore more generic. Signed-off-by: Steven Hand --- tools/libxc/xc_linux_restore.c | 12 ++++-------- xen/include/public/dom0_ops.h | 13 +++++++------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 7d8ebda0c7..0a52758327 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -646,18 +646,14 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } - if ((pt_levels == 2) && ((pfn_type[pfn]<ABTYPE_MASK) != L2TAB)) { + if ( (pfn_type[pfn] & LTABTYPE_MASK) != + ((unsigned long)pt_levels< Date: Thu, 6 Apr 2006 17:41:07 +0100 Subject: [PATCH 108/151] This adds proper cleanup in case of a failure. Signed-off-by: Stefan Berger --- tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py | 1 + tools/xm-test/tests/vtpm/03_vtpm-susp_res.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py b/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py index ab948b827d..feeb6cb42a 100644 --- a/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py +++ b/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py @@ -46,6 +46,7 @@ except ConsoleError, e: FAIL(str(e)) if re.search("No such file",run["output"]): + vtpm_cleanup(domName) FAIL("TPM frontend support not compiled into (domU?) kernel") console.closeConsole() diff --git a/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py b/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py index 793e4b2afc..7e291763af 100644 --- a/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py +++ b/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py @@ -47,6 +47,7 @@ except ConsoleError, e: FAIL(str(e)) if re.search("No such file",run["output"]): + vtpm_cleanup(domName) FAIL("TPM frontend support not compiled into (domU?) kernel") console.closeConsole() From 6e5243b3287362b32d491ad75e674e38a3825c19 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 6 Apr 2006 18:39:00 +0100 Subject: [PATCH 109/151] Do not create blkback vbd kernel thread until fully connected to frontend driver. Otherwise the kernel thread may crash trying to access the non-existent shared ring. Signed-off-by: Keir Fraser --- .../drivers/xen/blkback/blkback.c | 2 +- .../drivers/xen/blkback/common.h | 1 - .../drivers/xen/blkback/xenbus.c | 38 +++++++++++-------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 4faf117069..fe2367a8fc 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -287,7 +287,7 @@ static int end_block_io_op(struct bio *bio, unsigned int done, int error) * NOTIFICATION FROM GUEST OS. */ -void blkif_notify_work(blkif_t *blkif) +static void blkif_notify_work(blkif_t *blkif) { blkif->waiting_reqs = 1; wake_up(&blkif->wq); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index 58939d6ab2..a32466e3a7 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -129,7 +129,6 @@ void blkif_interface_init(void); void blkif_xenbus_init(void); -void blkif_notify_work(blkif_t *blkif); irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs); int blkif_schedule(void *arg); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index d0ec094d66..011bec8d19 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -46,10 +46,29 @@ static void backend_changed(struct xenbus_watch *, const char **, static void update_blkif_status(blkif_t *blkif) { - if (blkif->irq && blkif->vbd.bdev && - (blkif->be->dev->state != XenbusStateConnected)) { - connect(blkif->be); - blkif_notify_work(blkif); + int err; + + /* Not ready to connect? */ + if (!blkif->irq || !blkif->vbd.bdev) + return; + + /* Already connected? */ + if (blkif->be->dev->state == XenbusStateConnected) + return; + + /* Attempt to connect: exit if we fail to. */ + connect(blkif->be); + if (blkif->be->dev->state != XenbusStateConnected) + return; + + blkif->xenblkd = kthread_run(blkif_schedule, blkif, + "xvd %d %02x:%02x", + blkif->domid, + blkif->be->major, blkif->be->minor); + if (IS_ERR(blkif->xenblkd)) { + err = PTR_ERR(blkif->xenblkd); + blkif->xenblkd = NULL; + xenbus_dev_error(blkif->be->dev, err, "start xenblkd"); } } @@ -215,17 +234,6 @@ static void backend_changed(struct xenbus_watch *watch, return; } - be->blkif->xenblkd = kthread_run(blkif_schedule, be->blkif, - "xvd %d %02x:%02x", - be->blkif->domid, - be->major, be->minor); - if (IS_ERR(be->blkif->xenblkd)) { - err = PTR_ERR(be->blkif->xenblkd); - be->blkif->xenblkd = NULL; - xenbus_dev_error(dev, err, "start xenblkd"); - return; - } - device_create_file(&dev->dev, &dev_attr_physical_device); device_create_file(&dev->dev, &dev_attr_mode); From c5b774278a01097410ce6ec3b181526e466f9c2a Mon Sep 17 00:00:00 2001 From: "ack@kneesa.uk.xensource.com" Date: Thu, 6 Apr 2006 18:58:01 +0100 Subject: [PATCH 110/151] Add xenoprof support Signed-off-by: Jose Renato Santos --- buildconfigs/linux-defconfig_xen0_x86_32 | 1 + buildconfigs/linux-defconfig_xenU_x86_32 | 1 + buildconfigs/linux-defconfig_xen_x86_32 | 1 + linux-2.6-xen-sparse/arch/i386/Kconfig | 2 - .../arch/i386/mm/ioremap-xen.c | 26 + .../arch/i386/oprofile/Makefile | 16 + .../arch/i386/oprofile/xenoprof.c | 395 ++++++++++ .../arch/x86_64/oprofile/Makefile | 22 + .../include/asm-i386/mach-xen/asm/hypercall.h | 8 + .../asm-x86_64/mach-xen/asm/hypercall.h | 7 + patches/linux-2.6.16/xenoprof-generic.patch | 384 +++++++++ xen/arch/x86/Makefile | 1 + xen/arch/x86/domain.c | 6 + xen/arch/x86/oprofile/Makefile | 5 + xen/arch/x86/oprofile/nmi_int.c | 399 ++++++++++ xen/arch/x86/oprofile/op_counter.h | 29 + xen/arch/x86/oprofile/op_model_athlon.c | 168 ++++ xen/arch/x86/oprofile/op_model_p4.c | 739 ++++++++++++++++++ xen/arch/x86/oprofile/op_model_ppro.c | 153 ++++ xen/arch/x86/oprofile/op_x86_model.h | 51 ++ xen/arch/x86/oprofile/xenoprof.c | 553 +++++++++++++ xen/arch/x86/x86_32/entry.S | 2 + xen/arch/x86/x86_64/entry.S | 2 + xen/include/public/xen.h | 4 +- xen/include/public/xenoprof.h | 72 ++ xen/include/xen/sched.h | 4 + xen/include/xen/xenoprof.h | 40 + 27 files changed, 3088 insertions(+), 3 deletions(-) create mode 100644 linux-2.6-xen-sparse/arch/i386/oprofile/Makefile create mode 100644 linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c create mode 100644 linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile create mode 100644 patches/linux-2.6.16/xenoprof-generic.patch create mode 100644 xen/arch/x86/oprofile/Makefile create mode 100644 xen/arch/x86/oprofile/nmi_int.c create mode 100644 xen/arch/x86/oprofile/op_counter.h create mode 100644 xen/arch/x86/oprofile/op_model_athlon.c create mode 100644 xen/arch/x86/oprofile/op_model_p4.c create mode 100644 xen/arch/x86/oprofile/op_model_ppro.c create mode 100644 xen/arch/x86/oprofile/op_x86_model.h create mode 100644 xen/arch/x86/oprofile/xenoprof.c create mode 100644 xen/include/public/xenoprof.h create mode 100644 xen/include/xen/xenoprof.h diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32 index 89f700682f..c520622e1e 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_32 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 @@ -1231,6 +1231,7 @@ CONFIG_NLS_ISO8859_1=y # # Instrumentation Support # +# CONFIG_PROFILING is not set # CONFIG_KPROBES is not set # diff --git a/buildconfigs/linux-defconfig_xenU_x86_32 b/buildconfigs/linux-defconfig_xenU_x86_32 index 077c626ca3..cca500a2e4 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_32 +++ b/buildconfigs/linux-defconfig_xenU_x86_32 @@ -779,6 +779,7 @@ CONFIG_NLS_ISO8859_1=y # # Instrumentation Support # +# CONFIG_PROFILING is not set # CONFIG_KPROBES is not set # diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index bce7cf92c2..59baf22bb2 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -2892,6 +2892,7 @@ CONFIG_NLS_UTF8=m # # Instrumentation Support # +# CONFIG_PROFILING is not set # CONFIG_KPROBES is not set # diff --git a/linux-2.6-xen-sparse/arch/i386/Kconfig b/linux-2.6-xen-sparse/arch/i386/Kconfig index 6a4988c5e3..9687edf9f0 100644 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig @@ -1116,9 +1116,7 @@ source "fs/Kconfig" menu "Instrumentation Support" depends on EXPERIMENTAL -if !X86_XEN source "arch/i386/oprofile/Kconfig" -endif config KPROBES bool "Kprobes (EXPERIMENTAL)" diff --git a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c index 05f3daab98..0966875124 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c @@ -177,6 +177,32 @@ int touch_pte_range(struct mm_struct *mm, EXPORT_SYMBOL(touch_pte_range); +void *vm_map_xen_pages (unsigned long maddr, int vm_size, pgprot_t prot) +{ + int error; + + struct vm_struct *vma; + vma = get_vm_area (vm_size, VM_IOREMAP); + + if (vma == NULL) { + printk ("ioremap.c,vm_map_xen_pages(): " + "Failed to get VMA area\n"); + return NULL; + } + + error = direct_kernel_remap_pfn_range((unsigned long) vma->addr, + maddr >> PAGE_SHIFT, vm_size, + prot, DOMID_SELF ); + if (error == 0) { + return vma->addr; + } else { + printk ("ioremap.c,vm_map_xen_pages(): " + "Failed to map xen shared pages into kernel space\n"); + return NULL; + } +} +EXPORT_SYMBOL(vm_map_xen_pages); + /* * Does @address reside within a non-highmem page that is local to this virtual * machine (i.e., not an I/O page, nor a memory page belonging to another VM). diff --git a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile new file mode 100644 index 0000000000..d283cd6c4d --- /dev/null +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile @@ -0,0 +1,16 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +ifdef CONFIG_X86_XEN +oprofile-y := $(DRIVER_OBJS) xenoprof.o +else +oprofile-y := $(DRIVER_OBJS) init.o backtrace.o +oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ + op_model_ppro.o op_model_p4.o +oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o +endif diff --git a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c new file mode 100644 index 0000000000..f5184a2c0c --- /dev/null +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c @@ -0,0 +1,395 @@ +/** + * @file xenoprof.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * + * Modified by Aravind Menon and Jose Renato Santos for Xen + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "op_counter.h" + +#include +#include + +static int xenoprof_start(void); +static void xenoprof_stop(void); + +void * vm_map_xen_pages(unsigned long maddr, int vm_size, pgprot_t prot); + +static int xenoprof_enabled = 0; +static int num_events = 0; +static int is_primary = 0; + +/* sample buffers shared with Xen */ +xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; +/* Shared buffer area */ +char * shared_buffer; +/* Number of buffers in shared area (one per VCPU) */ +int nbuf; +/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */ +int ovf_irq[NR_CPUS]; +/* cpu model type string - copied from Xen memory space on XENOPROF_init command */ +char cpu_type[XENOPROF_CPU_TYPE_SIZE]; + +#ifdef CONFIG_PM + +static int xenoprof_suspend(struct sys_device * dev, pm_message_t state) +{ + if (xenoprof_enabled == 1) + xenoprof_stop(); + return 0; +} + + +static int xenoprof_resume(struct sys_device * dev) +{ + if (xenoprof_enabled == 1) + xenoprof_start(); + return 0; +} + + +static struct sysdev_class oprofile_sysclass = { + set_kset_name("oprofile"), + .resume = xenoprof_resume, + .suspend = xenoprof_suspend +}; + + +static struct sys_device device_oprofile = { + .id = 0, + .cls = &oprofile_sysclass, +}; + + +static int __init init_driverfs(void) +{ + int error; + if (!(error = sysdev_class_register(&oprofile_sysclass))) + error = sysdev_register(&device_oprofile); + return error; +} + + +static void __exit exit_driverfs(void) +{ + sysdev_unregister(&device_oprofile); + sysdev_class_unregister(&oprofile_sysclass); +} + +#else +#define init_driverfs() do { } while (0) +#define exit_driverfs() do { } while (0) +#endif /* CONFIG_PM */ + +unsigned long long oprofile_samples = 0; + +static irqreturn_t +xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + int head, tail, size; + xenoprof_buf_t * buf; + int cpu; + + cpu = smp_processor_id(); + buf = xenoprof_buf[cpu]; + + head = buf->event_head; + tail = buf->event_tail; + size = buf->event_size; + + if (tail > head) { + while (tail < size) { + oprofile_add_pc(buf->event_log[tail].eip, + buf->event_log[tail].mode, + buf->event_log[tail].event); + oprofile_samples++; + tail++; + } + tail = 0; + } + while (tail < head) { + oprofile_add_pc(buf->event_log[tail].eip, + buf->event_log[tail].mode, + buf->event_log[tail].event); + oprofile_samples++; + tail++; + } + + buf->event_tail = tail; + + return IRQ_HANDLED; +} + + +static void unbind_virq_cpu(void * info) +{ + int cpu = smp_processor_id(); + if (ovf_irq[cpu] >= 0) { + unbind_from_irqhandler(ovf_irq[cpu], NULL); + ovf_irq[cpu] = -1; + } +} + + +static void unbind_virq(void) +{ + on_each_cpu(unbind_virq_cpu, NULL, 0, 1); +} + + +int bind_virq_error; + +static void bind_virq_cpu(void * info) +{ + int result; + int cpu = smp_processor_id(); + + result = bind_virq_to_irqhandler(VIRQ_XENOPROF, + cpu, + xenoprof_ovf_interrupt, + SA_INTERRUPT, + "xenoprof", + NULL); + + if (result<0) { + bind_virq_error = result; + printk("xenoprof.c: binding VIRQ_XENOPROF to IRQ failed on CPU " + "%d\n", cpu); + } else { + ovf_irq[cpu] = result; + } +} + + +static int bind_virq(void) +{ + bind_virq_error = 0; + on_each_cpu(bind_virq_cpu, NULL, 0, 1); + if (bind_virq_error) { + unbind_virq(); + return bind_virq_error; + } else { + return 0; + } +} + + +static int xenoprof_setup(void) +{ + int ret; + + ret = bind_virq(); + if (ret) + return ret; + + if (is_primary) { + ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, + (unsigned long)NULL, + (unsigned long)NULL); + if (ret) + goto err; + + ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, + (unsigned long)&counter_config, + (unsigned long)num_events); + if (ret) + goto err; + } + + ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, + (unsigned long)NULL, + (unsigned long)NULL); + if (ret) + goto err; + + xenoprof_enabled = 1; + return 0; + err: + unbind_virq(); + return ret; +} + + +static void xenoprof_shutdown(void) +{ + xenoprof_enabled = 0; + + HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, + (unsigned long)NULL, + (unsigned long)NULL); + + if (is_primary) { + HYPERVISOR_xenoprof_op(XENOPROF_release_counters, + (unsigned long)NULL, + (unsigned long)NULL); + } + + unbind_virq(); +} + + +static int xenoprof_start(void) +{ + int ret = 0; + + if (is_primary) + ret = HYPERVISOR_xenoprof_op(XENOPROF_start, + (unsigned long)NULL, + (unsigned long)NULL); + return ret; +} + + +static void xenoprof_stop(void) +{ + if (is_primary) + HYPERVISOR_xenoprof_op(XENOPROF_stop, + (unsigned long)NULL, + (unsigned long)NULL); +} + + +static int xenoprof_set_active(int * active_domains, + unsigned int adomains) +{ + int ret = 0; + if (is_primary) + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, + (unsigned long)active_domains, + (unsigned long)adomains); + return ret; +} + + +struct op_counter_config counter_config[OP_MAX_COUNTER]; + +static int xenoprof_create_files(struct super_block * sb, struct dentry * root) +{ + unsigned int i; + + for (i = 0; i < num_events; ++i) { + struct dentry * dir; + char buf[2]; + + snprintf(buf, 2, "%d", i); + dir = oprofilefs_mkdir(sb, root, buf); + oprofilefs_create_ulong(sb, dir, "enabled", + &counter_config[i].enabled); + oprofilefs_create_ulong(sb, dir, "event", + &counter_config[i].event); + oprofilefs_create_ulong(sb, dir, "count", + &counter_config[i].count); + oprofilefs_create_ulong(sb, dir, "unit_mask", + &counter_config[i].unit_mask); + oprofilefs_create_ulong(sb, dir, "kernel", + &counter_config[i].kernel); + oprofilefs_create_ulong(sb, dir, "user", + &counter_config[i].user); + } + + return 0; +} + + +struct oprofile_operations xenoprof_ops = { + .create_files = xenoprof_create_files, + .set_active = xenoprof_set_active, + .setup = xenoprof_setup, + .shutdown = xenoprof_shutdown, + .start = xenoprof_start, + .stop = xenoprof_stop +}; + + +/* in order to get driverfs right */ +static int using_xenoprof; + +int __init oprofile_arch_init(struct oprofile_operations * ops) +{ + xenoprof_init_result_t result; + xenoprof_buf_t * buf; + int max_samples = 16; + int vm_size; + int npages; + int i; + + int ret = HYPERVISOR_xenoprof_op(XENOPROF_init, + (unsigned long)max_samples, + (unsigned long)&result); + + if (!ret) { + pgprot_t prot = __pgprot(_KERNPG_TABLE); + + num_events = result.num_events; + is_primary = result.is_primary; + nbuf = result.nbuf; + + npages = (result.bufsize * nbuf - 1) / PAGE_SIZE + 1; + vm_size = npages * PAGE_SIZE; + + shared_buffer = (char *) vm_map_xen_pages(result.buf_maddr, + vm_size, prot); + if (!shared_buffer) { + ret = -ENOMEM; + goto out; + } + + for (i=0; i< nbuf; i++) { + buf = (xenoprof_buf_t*) + &shared_buffer[i * result.bufsize]; + BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); + xenoprof_buf[buf->vcpu_id] = buf; + } + + /* cpu_type is detected by Xen */ + cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0; + strncpy(cpu_type, result.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1); + xenoprof_ops.cpu_type = cpu_type; + + init_driverfs(); + using_xenoprof = 1; + *ops = xenoprof_ops; + + for (i=0; i + * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. ++ * + * This is the core of the buffer management. Each + * CPU buffer is processed and entered into the + * global event buffer. Such processing is necessary +@@ -275,15 +279,24 @@ static void add_cpu_switch(int i) + last_cookie = INVALID_COOKIE; + } + +-static void add_kernel_ctx_switch(unsigned int in_kernel) ++static void add_cpu_mode_switch(unsigned int cpu_mode) + { + add_event_entry(ESCAPE_CODE); +- if (in_kernel) +- add_event_entry(KERNEL_ENTER_SWITCH_CODE); +- else +- add_event_entry(KERNEL_EXIT_SWITCH_CODE); ++ switch (cpu_mode) { ++ case CPU_MODE_USER: ++ add_event_entry(USER_ENTER_SWITCH_CODE); ++ break; ++ case CPU_MODE_KERNEL: ++ add_event_entry(KERNEL_ENTER_SWITCH_CODE); ++ break; ++ case CPU_MODE_XEN: ++ add_event_entry(XEN_ENTER_SWITCH_CODE); ++ break; ++ default: ++ break; ++ } + } +- ++ + static void + add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) + { +@@ -348,9 +361,9 @@ static int add_us_sample(struct mm_struc + * for later lookup from userspace. + */ + static int +-add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel) ++add_sample(struct mm_struct * mm, struct op_sample * s, int cpu_mode) + { +- if (in_kernel) { ++ if (cpu_mode >= CPU_MODE_KERNEL) { + add_sample_entry(s->eip, s->event); + return 1; + } else if (mm) { +@@ -496,7 +509,7 @@ void sync_buffer(int cpu) + struct mm_struct *mm = NULL; + struct task_struct * new; + unsigned long cookie = 0; +- int in_kernel = 1; ++ int cpu_mode = 1; + unsigned int i; + sync_buffer_state state = sb_buffer_start; + unsigned long available; +@@ -513,12 +526,12 @@ void sync_buffer(int cpu) + struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; + + if (is_code(s->eip)) { +- if (s->event <= CPU_IS_KERNEL) { ++ if (s->event <= CPU_MODE_XEN) { + /* kernel/userspace switch */ +- in_kernel = s->event; ++ cpu_mode = s->event; + if (state == sb_buffer_start) + state = sb_sample_start; +- add_kernel_ctx_switch(s->event); ++ add_cpu_mode_switch(s->event); + } else if (s->event == CPU_TRACE_BEGIN) { + state = sb_bt_start; + add_trace_begin(); +@@ -536,7 +549,7 @@ void sync_buffer(int cpu) + } + } else { + if (state >= sb_bt_start && +- !add_sample(mm, s, in_kernel)) { ++ !add_sample(mm, s, cpu_mode)) { + if (state == sb_bt_start) { + state = sb_bt_ignore; + atomic_inc(&oprofile_stats.bt_lost_no_mapping); +diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c +--- ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.c 2006-03-20 05:53:29.000000000 +0000 ++++ ./drivers/oprofile/cpu_buffer.c 2006-04-03 15:53:05.000000000 +0100 +@@ -6,6 +6,10 @@ + * + * @author John Levon + * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. ++ * + * Each CPU has a local buffer that stores PC value/event + * pairs. We also log context switches when we notice them. + * Eventually each CPU's buffer is processed into the global +@@ -58,7 +62,7 @@ int alloc_cpu_buffers(void) + goto fail; + + b->last_task = NULL; +- b->last_is_kernel = -1; ++ b->last_cpu_mode = -1; + b->tracing = 0; + b->buffer_size = buffer_size; + b->tail_pos = 0; +@@ -114,7 +118,7 @@ void cpu_buffer_reset(struct oprofile_cp + * collected will populate the buffer with proper + * values to initialize the buffer + */ +- cpu_buf->last_is_kernel = -1; ++ cpu_buf->last_cpu_mode = -1; + cpu_buf->last_task = NULL; + } + +@@ -164,13 +168,13 @@ add_code(struct oprofile_cpu_buffer * bu + * because of the head/tail separation of the writer and reader + * of the CPU buffer. + * +- * is_kernel is needed because on some architectures you cannot ++ * cpu_mode is needed because on some architectures you cannot + * tell if you are in kernel or user space simply by looking at +- * pc. We tag this in the buffer by generating kernel enter/exit +- * events whenever is_kernel changes ++ * pc. We tag this in the buffer by generating kernel/user (and xen) ++ * enter events whenever cpu_mode changes + */ + static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, +- int is_kernel, unsigned long event) ++ int cpu_mode, unsigned long event) + { + struct task_struct * task; + +@@ -181,16 +185,16 @@ static int log_sample(struct oprofile_cp + return 0; + } + +- is_kernel = !!is_kernel; ++ WARN_ON(cpu_mode > CPU_MODE_XEN); + + task = current; + + /* notice a switch from user->kernel or vice versa */ +- if (cpu_buf->last_is_kernel != is_kernel) { +- cpu_buf->last_is_kernel = is_kernel; +- add_code(cpu_buf, is_kernel); ++ if (cpu_buf->last_cpu_mode != cpu_mode) { ++ cpu_buf->last_cpu_mode = cpu_mode; ++ add_code(cpu_buf, cpu_mode); + } +- ++ + /* notice a task switch */ + if (cpu_buf->last_task != task) { + cpu_buf->last_task = task; +diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.h ./drivers/oprofile/cpu_buffer.h +--- ../pristine-linux-2.6.16/drivers/oprofile/cpu_buffer.h 2006-03-20 05:53:29.000000000 +0000 ++++ ./drivers/oprofile/cpu_buffer.h 2006-04-03 15:53:05.000000000 +0100 +@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer { + volatile unsigned long tail_pos; + unsigned long buffer_size; + struct task_struct * last_task; +- int last_is_kernel; ++ int last_cpu_mode; + int tracing; + struct op_sample * buffer; + unsigned long sample_received; +@@ -51,7 +51,9 @@ extern struct oprofile_cpu_buffer cpu_bu + void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); + + /* transient events for the CPU buffer -> event buffer */ +-#define CPU_IS_KERNEL 1 +-#define CPU_TRACE_BEGIN 2 ++#define CPU_MODE_USER 0 ++#define CPU_MODE_KERNEL 1 ++#define CPU_MODE_XEN 2 ++#define CPU_TRACE_BEGIN 3 + + #endif /* OPROFILE_CPU_BUFFER_H */ +diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/event_buffer.h ./drivers/oprofile/event_buffer.h +--- ../pristine-linux-2.6.16/drivers/oprofile/event_buffer.h 2006-03-20 05:53:29.000000000 +0000 ++++ ./drivers/oprofile/event_buffer.h 2006-04-03 15:53:05.000000000 +0100 +@@ -29,11 +29,12 @@ void wake_up_buffer_waiter(void); + #define CPU_SWITCH_CODE 2 + #define COOKIE_SWITCH_CODE 3 + #define KERNEL_ENTER_SWITCH_CODE 4 +-#define KERNEL_EXIT_SWITCH_CODE 5 ++#define USER_ENTER_SWITCH_CODE 5 + #define MODULE_LOADED_CODE 6 + #define CTX_TGID_CODE 7 + #define TRACE_BEGIN_CODE 8 + #define TRACE_END_CODE 9 ++#define XEN_ENTER_SWITCH_CODE 10 + + #define INVALID_COOKIE ~0UL + #define NO_COOKIE 0UL +diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/oprof.c ./drivers/oprofile/oprof.c +--- ../pristine-linux-2.6.16/drivers/oprofile/oprof.c 2006-03-20 05:53:29.000000000 +0000 ++++ ./drivers/oprofile/oprof.c 2006-04-03 15:53:05.000000000 +0100 +@@ -5,6 +5,10 @@ + * @remark Read the file COPYING + * + * @author John Levon ++ * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. + */ + + #include +@@ -19,7 +23,7 @@ + #include "cpu_buffer.h" + #include "buffer_sync.h" + #include "oprofile_stats.h" +- ++ + struct oprofile_operations oprofile_ops; + + unsigned long oprofile_started; +@@ -33,6 +37,17 @@ static DECLARE_MUTEX(start_sem); + */ + static int timer = 0; + ++extern unsigned int adomains; ++extern int active_domains[MAX_OPROF_DOMAINS]; ++ ++int oprofile_set_active(void) ++{ ++ if (oprofile_ops.set_active) ++ return oprofile_ops.set_active(active_domains, adomains); ++ ++ return -EINVAL; ++} ++ + int oprofile_setup(void) + { + int err; +diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/oprof.h ./drivers/oprofile/oprof.h +--- ../pristine-linux-2.6.16/drivers/oprofile/oprof.h 2006-03-20 05:53:29.000000000 +0000 ++++ ./drivers/oprofile/oprof.h 2006-04-03 15:53:05.000000000 +0100 +@@ -35,5 +35,7 @@ void oprofile_create_files(struct super_ + void oprofile_timer_init(struct oprofile_operations * ops); + + int oprofile_set_backtrace(unsigned long depth); ++ ++int oprofile_set_active(void); + + #endif /* OPROF_H */ +diff -pruN ../pristine-linux-2.6.16/drivers/oprofile/oprofile_files.c ./drivers/oprofile/oprofile_files.c +--- ../pristine-linux-2.6.16/drivers/oprofile/oprofile_files.c 2006-03-20 05:53:29.000000000 +0000 ++++ ./drivers/oprofile/oprofile_files.c 2006-04-03 15:53:05.000000000 +0100 +@@ -5,15 +5,21 @@ + * @remark Read the file COPYING + * + * @author John Levon ++ * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. + */ + + #include + #include ++#include ++#include + + #include "event_buffer.h" + #include "oprofile_stats.h" + #include "oprof.h" +- ++ + unsigned long fs_buffer_size = 131072; + unsigned long fs_cpu_buffer_size = 8192; + unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */ +@@ -117,11 +123,79 @@ static ssize_t dump_write(struct file * + static struct file_operations dump_fops = { + .write = dump_write, + }; +- ++ ++#define TMPBUFSIZE 512 ++ ++unsigned int adomains = 0; ++long active_domains[MAX_OPROF_DOMAINS]; ++ ++static ssize_t adomain_write(struct file * file, char const __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char tmpbuf[TMPBUFSIZE]; ++ char * startp = tmpbuf; ++ char * endp = tmpbuf; ++ int i; ++ unsigned long val; ++ ++ if (*offset) ++ return -EINVAL; ++ if (!count) ++ return 0; ++ if (count > TMPBUFSIZE - 1) ++ return -EINVAL; ++ ++ memset(tmpbuf, 0x0, TMPBUFSIZE); ++ ++ if (copy_from_user(tmpbuf, buf, count)) ++ return -EFAULT; ++ ++ for (i = 0; i < MAX_OPROF_DOMAINS; i++) ++ active_domains[i] = -1; ++ adomains = 0; ++ ++ while (1) { ++ val = simple_strtol(startp, &endp, 0); ++ if (endp == startp) ++ break; ++ while (ispunct(*endp)) ++ endp++; ++ active_domains[adomains++] = val; ++ if (adomains >= MAX_OPROF_DOMAINS) ++ break; ++ startp = endp; ++ } ++ if (oprofile_set_active()) ++ return -EINVAL; ++ return count; ++} ++ ++static ssize_t adomain_read(struct file * file, char __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char tmpbuf[TMPBUFSIZE]; ++ size_t len = 0; ++ int i; ++ /* This is all screwed up if we run out of space */ ++ for (i = 0; i < adomains; i++) ++ len += snprintf(tmpbuf + len, TMPBUFSIZE - len, ++ "%u ", (unsigned int)active_domains[i]); ++ len += snprintf(tmpbuf + len, TMPBUFSIZE - len, "\n"); ++ return simple_read_from_buffer((void __user *)buf, count, ++ offset, tmpbuf, len); ++} ++ ++ ++static struct file_operations active_domain_ops = { ++ .read = adomain_read, ++ .write = adomain_write, ++}; ++ + void oprofile_create_files(struct super_block * sb, struct dentry * root) + { + oprofilefs_create_file(sb, root, "enable", &enable_fops); + oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); ++ oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops); + oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); + oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); + oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); +diff -pruN ../pristine-linux-2.6.16/include/linux/oprofile.h ./include/linux/oprofile.h +--- ../pristine-linux-2.6.16/include/linux/oprofile.h 2006-03-20 05:53:29.000000000 +0000 ++++ ./include/linux/oprofile.h 2006-04-03 15:53:05.000000000 +0100 +@@ -16,6 +16,8 @@ + #include + #include + #include ++ ++#include + + struct super_block; + struct dentry; +@@ -27,6 +29,8 @@ struct oprofile_operations { + /* create any necessary configuration files in the oprofile fs. + * Optional. */ + int (*create_files)(struct super_block * sb, struct dentry * root); ++ /* setup active domains with Xen */ ++ int (*set_active)(int *active_domains, unsigned int adomains); + /* Do any necessary interrupt setup. Optional. */ + int (*setup)(void); + /* Do any necessary interrupt shutdown. Optional. */ diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index fbb1a83c1f..5e70e72533 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -2,6 +2,7 @@ subdir-y += acpi subdir-y += cpu subdir-y += genapic subdir-y += hvm +subdir-y += oprofile subdir-$(x86_32) += x86_32 subdir-$(x86_64) += x86_64 diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index b52770ef80..8c0bb136fa 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -915,6 +915,8 @@ static void relinquish_memory(struct domain *d, struct list_head *list) spin_unlock_recursive(&d->page_alloc_lock); } +extern void free_xenoprof_pages(struct domain *d); + void domain_relinquish_resources(struct domain *d) { struct vcpu *v; @@ -961,6 +963,10 @@ void domain_relinquish_resources(struct domain *d) /* Relinquish every page of memory. */ relinquish_memory(d, &d->xenpage_list); relinquish_memory(d, &d->page_list); + + /* Free page used by xen oprofile buffer */ + free_xenoprof_pages(d); + } void arch_dump_domain_info(struct domain *d) diff --git a/xen/arch/x86/oprofile/Makefile b/xen/arch/x86/oprofile/Makefile new file mode 100644 index 0000000000..1956c02df5 --- /dev/null +++ b/xen/arch/x86/oprofile/Makefile @@ -0,0 +1,5 @@ +obj-y += xenoprof.o +obj-y += nmi_int.o +obj-y += op_model_p4.o +obj-y += op_model_ppro.o +obj-y += op_model_athlon.o diff --git a/xen/arch/x86/oprofile/nmi_int.c b/xen/arch/x86/oprofile/nmi_int.c new file mode 100644 index 0000000000..d9495b0566 --- /dev/null +++ b/xen/arch/x86/oprofile/nmi_int.c @@ -0,0 +1,399 @@ +/** + * @file nmi_int.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * + * Modified for Xen: by Aravind Menon & Jose Renato Santos + * These modifications are: + * Copyright (C) 2005 Hewlett-Packard Co. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "op_counter.h" +#include "op_x86_model.h" + +static struct op_x86_model_spec const * model; +static struct op_msrs cpu_msrs[NR_CPUS]; +static unsigned long saved_lvtpc[NR_CPUS]; + +#define VIRQ_BITMASK_SIZE (MAX_OPROF_DOMAINS/32 + 1) +extern int active_domains[MAX_OPROF_DOMAINS]; +extern unsigned int adomains; +extern struct domain *primary_profiler; +extern struct domain *adomain_ptrs[MAX_OPROF_DOMAINS]; +extern unsigned long virq_ovf_pending[VIRQ_BITMASK_SIZE]; +extern int is_active(struct domain *d); +extern int active_id(struct domain *d); +extern int is_profiled(struct domain *d); + +extern size_t strlcpy(char *dest, const char *src, size_t size); + + +int nmi_callback(struct cpu_user_regs *regs, int cpu) +{ + int xen_mode = 0; + int ovf; + + ovf = model->check_ctrs(cpu, &cpu_msrs[cpu], regs); + xen_mode = ring_0(regs); + if ( ovf ) + { + if ( is_active(current->domain) ) + { + if ( !xen_mode ) + { + send_guest_vcpu_virq(current, VIRQ_XENOPROF); + } + } + } + return 1; +} + + +static void nmi_cpu_save_registers(struct op_msrs * msrs) +{ + unsigned int const nr_ctrs = model->num_counters; + unsigned int const nr_ctrls = model->num_controls; + struct op_msr * counters = msrs->counters; + struct op_msr * controls = msrs->controls; + unsigned int i; + + for (i = 0; i < nr_ctrs; ++i) { + rdmsr(counters[i].addr, + counters[i].saved.low, + counters[i].saved.high); + } + + for (i = 0; i < nr_ctrls; ++i) { + rdmsr(controls[i].addr, + controls[i].saved.low, + controls[i].saved.high); + } +} + + +static void nmi_save_registers(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs * msrs = &cpu_msrs[cpu]; + model->fill_in_addresses(msrs); + nmi_cpu_save_registers(msrs); +} + + +static void free_msrs(void) +{ + int i; + for (i = 0; i < NR_CPUS; ++i) { + xfree(cpu_msrs[i].counters); + cpu_msrs[i].counters = NULL; + xfree(cpu_msrs[i].controls); + cpu_msrs[i].controls = NULL; + } +} + + +static int allocate_msrs(void) +{ + int success = 1; + size_t controls_size = sizeof(struct op_msr) * model->num_controls; + size_t counters_size = sizeof(struct op_msr) * model->num_counters; + + int i; + for (i = 0; i < NR_CPUS; ++i) { + if (!test_bit(i, &cpu_online_map)) + continue; + + cpu_msrs[i].counters = xmalloc_bytes(counters_size); + if (!cpu_msrs[i].counters) { + success = 0; + break; + } + cpu_msrs[i].controls = xmalloc_bytes(controls_size); + if (!cpu_msrs[i].controls) { + success = 0; + break; + } + } + + if (!success) + free_msrs(); + + return success; +} + + +static void nmi_cpu_setup(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs * msrs = &cpu_msrs[cpu]; + model->setup_ctrs(msrs); +} + + +int nmi_setup_events(void) +{ + on_each_cpu(nmi_cpu_setup, NULL, 0, 1); + return 0; +} + +int nmi_reserve_counters(void) +{ + if (!allocate_msrs()) + return -ENOMEM; + + /* We walk a thin line between law and rape here. + * We need to be careful to install our NMI handler + * without actually triggering any NMIs as this will + * break the core code horrifically. + */ + if (reserve_lapic_nmi() < 0) { + free_msrs(); + return -EBUSY; + } + /* We need to serialize save and setup for HT because the subset + * of msrs are distinct for save and setup operations + */ + on_each_cpu(nmi_save_registers, NULL, 0, 1); + return 0; +} + +int nmi_enable_virq(void) +{ + set_nmi_callback(nmi_callback); + return 0; +} + + +void nmi_disable_virq(void) +{ + unset_nmi_callback(); +} + + +static void nmi_restore_registers(struct op_msrs * msrs) +{ + unsigned int const nr_ctrs = model->num_counters; + unsigned int const nr_ctrls = model->num_controls; + struct op_msr * counters = msrs->counters; + struct op_msr * controls = msrs->controls; + unsigned int i; + + for (i = 0; i < nr_ctrls; ++i) { + wrmsr(controls[i].addr, + controls[i].saved.low, + controls[i].saved.high); + } + + for (i = 0; i < nr_ctrs; ++i) { + wrmsr(counters[i].addr, + counters[i].saved.low, + counters[i].saved.high); + } +} + + +static void nmi_cpu_shutdown(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs * msrs = &cpu_msrs[cpu]; + nmi_restore_registers(msrs); +} + + +void nmi_release_counters(void) +{ + on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1); + release_lapic_nmi(); + free_msrs(); +} + + +static void nmi_cpu_start(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs const * msrs = &cpu_msrs[cpu]; + saved_lvtpc[cpu] = apic_read(APIC_LVTPC); + apic_write(APIC_LVTPC, APIC_DM_NMI); + model->start(msrs); +} + + +int nmi_start(void) +{ + on_each_cpu(nmi_cpu_start, NULL, 0, 1); + return 0; +} + + +static void nmi_cpu_stop(void * dummy) +{ + unsigned int v; + int cpu = smp_processor_id(); + struct op_msrs const * msrs = &cpu_msrs[cpu]; + model->stop(msrs); + + /* restoring APIC_LVTPC can trigger an apic error because the delivery + * mode and vector nr combination can be illegal. That's by design: on + * power on apic lvt contain a zero vector nr which are legal only for + * NMI delivery mode. So inhibit apic err before restoring lvtpc + */ + if ( !(apic_read(APIC_LVTPC) & APIC_DM_NMI) + || (apic_read(APIC_LVTPC) & APIC_LVT_MASKED) ) + { + printk("nmi_stop: APIC not good %ul\n", apic_read(APIC_LVTPC)); + mdelay(5000); + } + v = apic_read(APIC_LVTERR); + apic_write(APIC_LVTERR, v | APIC_LVT_MASKED); + apic_write(APIC_LVTPC, saved_lvtpc[cpu]); + apic_write(APIC_LVTERR, v); +} + + +void nmi_stop(void) +{ + on_each_cpu(nmi_cpu_stop, NULL, 0, 1); +} + + +struct op_counter_config counter_config[OP_MAX_COUNTER]; + +static int __init p4_init(char * cpu_type) +{ + __u8 cpu_model = current_cpu_data.x86_model; + + if (cpu_model > 4) + return 0; + +#ifndef CONFIG_SMP + strncpy (cpu_type, "i386/p4", XENOPROF_CPU_TYPE_SIZE - 1); + model = &op_p4_spec; + return 1; +#else + switch (smp_num_siblings) { + case 1: + strncpy (cpu_type, "i386/p4", + XENOPROF_CPU_TYPE_SIZE - 1); + model = &op_p4_spec; + return 1; + + case 2: + strncpy (cpu_type, "i386/p4-ht", + XENOPROF_CPU_TYPE_SIZE - 1); + model = &op_p4_ht2_spec; + return 1; + } +#endif + printk("Xenoprof ERROR: P4 HyperThreading detected with > 2 threads\n"); + + return 0; +} + + +static int __init ppro_init(char *cpu_type) +{ + __u8 cpu_model = current_cpu_data.x86_model; + + if (cpu_model > 0xd) + return 0; + + if (cpu_model == 9) { + strncpy (cpu_type, "i386/p6_mobile", XENOPROF_CPU_TYPE_SIZE - 1); + } else if (cpu_model > 5) { + strncpy (cpu_type, "i386/piii", XENOPROF_CPU_TYPE_SIZE - 1); + } else if (cpu_model > 2) { + strncpy (cpu_type, "i386/pii", XENOPROF_CPU_TYPE_SIZE - 1); + } else { + strncpy (cpu_type, "i386/ppro", XENOPROF_CPU_TYPE_SIZE - 1); + } + + model = &op_ppro_spec; + return 1; +} + +int nmi_init(int *num_events, int *is_primary, char *cpu_type) +{ + __u8 vendor = current_cpu_data.x86_vendor; + __u8 family = current_cpu_data.x86; + int prim = 0; + + if (!cpu_has_apic) + return -ENODEV; + + if (primary_profiler == NULL) { + /* For now, only dom0 can be the primary profiler */ + if (current->domain->domain_id == 0) { + primary_profiler = current->domain; + prim = 1; + } + } + + /* Make sure string is NULL terminated */ + cpu_type[XENOPROF_CPU_TYPE_SIZE - 1] = 0; + + switch (vendor) { + case X86_VENDOR_AMD: + /* Needs to be at least an Athlon (or hammer in 32bit mode) */ + + switch (family) { + default: + return -ENODEV; + case 6: + model = &op_athlon_spec; + strncpy (cpu_type, "i386/athlon", + XENOPROF_CPU_TYPE_SIZE - 1); + break; + case 0xf: + model = &op_athlon_spec; + /* Actually it could be i386/hammer too, but give + user space an consistent name. */ + strncpy (cpu_type, "x86-64/hammer", + XENOPROF_CPU_TYPE_SIZE - 1); + break; + } + break; + + case X86_VENDOR_INTEL: + switch (family) { + /* Pentium IV */ + case 0xf: + if (!p4_init(cpu_type)) + return -ENODEV; + break; + + /* A P6-class processor */ + case 6: + if (!ppro_init(cpu_type)) + return -ENODEV; + break; + + default: + return -ENODEV; + } + break; + + default: + return -ENODEV; + } + + *num_events = model->num_counters; + *is_primary = prim; + + return 0; +} + diff --git a/xen/arch/x86/oprofile/op_counter.h b/xen/arch/x86/oprofile/op_counter.h new file mode 100644 index 0000000000..2880b15c46 --- /dev/null +++ b/xen/arch/x86/oprofile/op_counter.h @@ -0,0 +1,29 @@ +/** + * @file op_counter.h + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + */ + +#ifndef OP_COUNTER_H +#define OP_COUNTER_H + +#define OP_MAX_COUNTER 8 + +/* Per-perfctr configuration as set via + * oprofilefs. + */ +struct op_counter_config { + unsigned long count; + unsigned long enabled; + unsigned long event; + unsigned long kernel; + unsigned long user; + unsigned long unit_mask; +}; + +extern struct op_counter_config counter_config[]; + +#endif /* OP_COUNTER_H */ diff --git a/xen/arch/x86/oprofile/op_model_athlon.c b/xen/arch/x86/oprofile/op_model_athlon.c new file mode 100644 index 0000000000..c946c1ea8e --- /dev/null +++ b/xen/arch/x86/oprofile/op_model_athlon.c @@ -0,0 +1,168 @@ +/** + * @file op_model_athlon.h + * athlon / K7 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * @author Philippe Elie + * @author Graydon Hoare + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "op_x86_model.h" +#include "op_counter.h" + +#define NUM_COUNTERS 4 +#define NUM_CONTROLS 4 + +#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0) +#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1);} while (0) +#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) + +#define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls[(c)].addr, (l), (h));} while (0) +#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0) +#define CTRL_SET_ACTIVE(n) (n |= (1<<22)) +#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) +#define CTRL_CLEAR(x) (x &= (1<<21)) +#define CTRL_SET_ENABLE(val) (val |= 1<<20) +#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) +#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) +#define CTRL_SET_UM(val, m) (val |= (m << 8)) +#define CTRL_SET_EVENT(val, e) (val |= e) + +static unsigned long reset_value[NUM_COUNTERS]; + +extern void xenoprof_log_event(struct vcpu *v, unsigned long eip, + int mode, int event); + +static void athlon_fill_in_addresses(struct op_msrs * const msrs) +{ + msrs->counters[0].addr = MSR_K7_PERFCTR0; + msrs->counters[1].addr = MSR_K7_PERFCTR1; + msrs->counters[2].addr = MSR_K7_PERFCTR2; + msrs->counters[3].addr = MSR_K7_PERFCTR3; + + msrs->controls[0].addr = MSR_K7_EVNTSEL0; + msrs->controls[1].addr = MSR_K7_EVNTSEL1; + msrs->controls[2].addr = MSR_K7_EVNTSEL2; + msrs->controls[3].addr = MSR_K7_EVNTSEL3; +} + + +static void athlon_setup_ctrs(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + /* clear all counters */ + for (i = 0 ; i < NUM_CONTROLS; ++i) { + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_WRITE(low, high, msrs, i); + } + + /* avoid a false detection of ctr overflows in NMI handler */ + for (i = 0; i < NUM_COUNTERS; ++i) { + CTR_WRITE(1, msrs, i); + } + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if (counter_config[i].enabled) { + reset_value[i] = counter_config[i].count; + + CTR_WRITE(counter_config[i].count, msrs, i); + + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_SET_ENABLE(low); + CTRL_SET_USR(low, counter_config[i].user); + CTRL_SET_KERN(low, counter_config[i].kernel); + CTRL_SET_UM(low, counter_config[i].unit_mask); + CTRL_SET_EVENT(low, counter_config[i].event); + CTRL_WRITE(low, high, msrs, i); + } else { + reset_value[i] = 0; + } + } +} + + +static int athlon_check_ctrs(unsigned int const cpu, + struct op_msrs const * const msrs, + struct cpu_user_regs * const regs) + +{ + unsigned int low, high; + int i; + int ovf = 0; + unsigned long eip = regs->eip; + int mode = 0; + + if (guest_kernel_mode(current, regs)) + mode = 1; + else if (ring_0(regs)) + mode = 2; + + for (i = 0 ; i < NUM_COUNTERS; ++i) { + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + xenoprof_log_event(current, eip, mode, i); + CTR_WRITE(reset_value[i], msrs, i); + ovf = 1; + } + } + + /* See op_model_ppro.c */ + return ovf; +} + + +static void athlon_start(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + if (reset_value[i]) { + CTRL_READ(low, high, msrs, i); + CTRL_SET_ACTIVE(low); + CTRL_WRITE(low, high, msrs, i); + } + } +} + + +static void athlon_stop(struct op_msrs const * const msrs) +{ + unsigned int low,high; + int i; + + /* Subtle: stop on all counters to avoid race with + * setting our pm callback */ + for (i = 0 ; i < NUM_COUNTERS ; ++i) { + CTRL_READ(low, high, msrs, i); + CTRL_SET_INACTIVE(low); + CTRL_WRITE(low, high, msrs, i); + } +} + + +struct op_x86_model_spec const op_athlon_spec = { + .num_counters = NUM_COUNTERS, + .num_controls = NUM_CONTROLS, + .fill_in_addresses = &athlon_fill_in_addresses, + .setup_ctrs = &athlon_setup_ctrs, + .check_ctrs = &athlon_check_ctrs, + .start = &athlon_start, + .stop = &athlon_stop +}; diff --git a/xen/arch/x86/oprofile/op_model_p4.c b/xen/arch/x86/oprofile/op_model_p4.c new file mode 100644 index 0000000000..453ee2ec8e --- /dev/null +++ b/xen/arch/x86/oprofile/op_model_p4.c @@ -0,0 +1,739 @@ +/** + * @file op_model_p4.c + * P4 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author Graydon Hoare + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "op_x86_model.h" +#include "op_counter.h" + +#define NUM_EVENTS 39 + +#define NUM_COUNTERS_NON_HT 8 +#define NUM_ESCRS_NON_HT 45 +#define NUM_CCCRS_NON_HT 18 +#define NUM_CONTROLS_NON_HT (NUM_ESCRS_NON_HT + NUM_CCCRS_NON_HT) + +#define NUM_COUNTERS_HT2 4 +#define NUM_ESCRS_HT2 23 +#define NUM_CCCRS_HT2 9 +#define NUM_CONTROLS_HT2 (NUM_ESCRS_HT2 + NUM_CCCRS_HT2) + +static unsigned int num_counters = NUM_COUNTERS_NON_HT; + + +/* this has to be checked dynamically since the + hyper-threadedness of a chip is discovered at + kernel boot-time. */ +static inline void setup_num_counters(void) +{ +#ifdef CONFIG_SMP + if (smp_num_siblings == 2) + num_counters = NUM_COUNTERS_HT2; +#endif +} + +static int inline addr_increment(void) +{ +#ifdef CONFIG_SMP + return smp_num_siblings == 2 ? 2 : 1; +#else + return 1; +#endif +} + + +/* tables to simulate simplified hardware view of p4 registers */ +struct p4_counter_binding { + int virt_counter; + int counter_address; + int cccr_address; +}; + +struct p4_event_binding { + int escr_select; /* value to put in CCCR */ + int event_select; /* value to put in ESCR */ + struct { + int virt_counter; /* for this counter... */ + int escr_address; /* use this ESCR */ + } bindings[2]; +}; + +/* nb: these CTR_* defines are a duplicate of defines in + event/i386.p4*events. */ + + +#define CTR_BPU_0 (1 << 0) +#define CTR_MS_0 (1 << 1) +#define CTR_FLAME_0 (1 << 2) +#define CTR_IQ_4 (1 << 3) +#define CTR_BPU_2 (1 << 4) +#define CTR_MS_2 (1 << 5) +#define CTR_FLAME_2 (1 << 6) +#define CTR_IQ_5 (1 << 7) + +static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = { + { CTR_BPU_0, MSR_P4_BPU_PERFCTR0, MSR_P4_BPU_CCCR0 }, + { CTR_MS_0, MSR_P4_MS_PERFCTR0, MSR_P4_MS_CCCR0 }, + { CTR_FLAME_0, MSR_P4_FLAME_PERFCTR0, MSR_P4_FLAME_CCCR0 }, + { CTR_IQ_4, MSR_P4_IQ_PERFCTR4, MSR_P4_IQ_CCCR4 }, + { CTR_BPU_2, MSR_P4_BPU_PERFCTR2, MSR_P4_BPU_CCCR2 }, + { CTR_MS_2, MSR_P4_MS_PERFCTR2, MSR_P4_MS_CCCR2 }, + { CTR_FLAME_2, MSR_P4_FLAME_PERFCTR2, MSR_P4_FLAME_CCCR2 }, + { CTR_IQ_5, MSR_P4_IQ_PERFCTR5, MSR_P4_IQ_CCCR5 } +}; + +#define NUM_UNUSED_CCCRS NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT + +/* All cccr we don't use. */ +static int p4_unused_cccr[NUM_UNUSED_CCCRS] = { + MSR_P4_BPU_CCCR1, MSR_P4_BPU_CCCR3, + MSR_P4_MS_CCCR1, MSR_P4_MS_CCCR3, + MSR_P4_FLAME_CCCR1, MSR_P4_FLAME_CCCR3, + MSR_P4_IQ_CCCR0, MSR_P4_IQ_CCCR1, + MSR_P4_IQ_CCCR2, MSR_P4_IQ_CCCR3 +}; + +/* p4 event codes in libop/op_event.h are indices into this table. */ + +static struct p4_event_binding p4_events[NUM_EVENTS] = { + + { /* BRANCH_RETIRED */ + 0x05, 0x06, + { {CTR_IQ_4, MSR_P4_CRU_ESCR2}, + {CTR_IQ_5, MSR_P4_CRU_ESCR3} } + }, + + { /* MISPRED_BRANCH_RETIRED */ + 0x04, 0x03, + { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, + { CTR_IQ_5, MSR_P4_CRU_ESCR1} } + }, + + { /* TC_DELIVER_MODE */ + 0x01, 0x01, + { { CTR_MS_0, MSR_P4_TC_ESCR0}, + { CTR_MS_2, MSR_P4_TC_ESCR1} } + }, + + { /* BPU_FETCH_REQUEST */ + 0x00, 0x03, + { { CTR_BPU_0, MSR_P4_BPU_ESCR0}, + { CTR_BPU_2, MSR_P4_BPU_ESCR1} } + }, + + { /* ITLB_REFERENCE */ + 0x03, 0x18, + { { CTR_BPU_0, MSR_P4_ITLB_ESCR0}, + { CTR_BPU_2, MSR_P4_ITLB_ESCR1} } + }, + + { /* MEMORY_CANCEL */ + 0x05, 0x02, + { { CTR_FLAME_0, MSR_P4_DAC_ESCR0}, + { CTR_FLAME_2, MSR_P4_DAC_ESCR1} } + }, + + { /* MEMORY_COMPLETE */ + 0x02, 0x08, + { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, + { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } + }, + + { /* LOAD_PORT_REPLAY */ + 0x02, 0x04, + { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, + { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } + }, + + { /* STORE_PORT_REPLAY */ + 0x02, 0x05, + { { CTR_FLAME_0, MSR_P4_SAAT_ESCR0}, + { CTR_FLAME_2, MSR_P4_SAAT_ESCR1} } + }, + + { /* MOB_LOAD_REPLAY */ + 0x02, 0x03, + { { CTR_BPU_0, MSR_P4_MOB_ESCR0}, + { CTR_BPU_2, MSR_P4_MOB_ESCR1} } + }, + + { /* PAGE_WALK_TYPE */ + 0x04, 0x01, + { { CTR_BPU_0, MSR_P4_PMH_ESCR0}, + { CTR_BPU_2, MSR_P4_PMH_ESCR1} } + }, + + { /* BSQ_CACHE_REFERENCE */ + 0x07, 0x0c, + { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, + { CTR_BPU_2, MSR_P4_BSU_ESCR1} } + }, + + { /* IOQ_ALLOCATION */ + 0x06, 0x03, + { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, + { 0, 0 } } + }, + + { /* IOQ_ACTIVE_ENTRIES */ + 0x06, 0x1a, + { { CTR_BPU_2, MSR_P4_FSB_ESCR1}, + { 0, 0 } } + }, + + { /* FSB_DATA_ACTIVITY */ + 0x06, 0x17, + { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, + { CTR_BPU_2, MSR_P4_FSB_ESCR1} } + }, + + { /* BSQ_ALLOCATION */ + 0x07, 0x05, + { { CTR_BPU_0, MSR_P4_BSU_ESCR0}, + { 0, 0 } } + }, + + { /* BSQ_ACTIVE_ENTRIES */ + 0x07, 0x06, + { { CTR_BPU_2, MSR_P4_BSU_ESCR1 /* guess */}, + { 0, 0 } } + }, + + { /* X87_ASSIST */ + 0x05, 0x03, + { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, + { CTR_IQ_5, MSR_P4_CRU_ESCR3} } + }, + + { /* SSE_INPUT_ASSIST */ + 0x01, 0x34, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* PACKED_SP_UOP */ + 0x01, 0x08, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* PACKED_DP_UOP */ + 0x01, 0x0c, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* SCALAR_SP_UOP */ + 0x01, 0x0a, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* SCALAR_DP_UOP */ + 0x01, 0x0e, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* 64BIT_MMX_UOP */ + 0x01, 0x02, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* 128BIT_MMX_UOP */ + 0x01, 0x1a, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* X87_FP_UOP */ + 0x01, 0x04, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* X87_SIMD_MOVES_UOP */ + 0x01, 0x2e, + { { CTR_FLAME_0, MSR_P4_FIRM_ESCR0}, + { CTR_FLAME_2, MSR_P4_FIRM_ESCR1} } + }, + + { /* MACHINE_CLEAR */ + 0x05, 0x02, + { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, + { CTR_IQ_5, MSR_P4_CRU_ESCR3} } + }, + + { /* GLOBAL_POWER_EVENTS */ + 0x06, 0x13 /* older manual says 0x05, newer 0x13 */, + { { CTR_BPU_0, MSR_P4_FSB_ESCR0}, + { CTR_BPU_2, MSR_P4_FSB_ESCR1} } + }, + + { /* TC_MS_XFER */ + 0x00, 0x05, + { { CTR_MS_0, MSR_P4_MS_ESCR0}, + { CTR_MS_2, MSR_P4_MS_ESCR1} } + }, + + { /* UOP_QUEUE_WRITES */ + 0x00, 0x09, + { { CTR_MS_0, MSR_P4_MS_ESCR0}, + { CTR_MS_2, MSR_P4_MS_ESCR1} } + }, + + { /* FRONT_END_EVENT */ + 0x05, 0x08, + { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, + { CTR_IQ_5, MSR_P4_CRU_ESCR3} } + }, + + { /* EXECUTION_EVENT */ + 0x05, 0x0c, + { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, + { CTR_IQ_5, MSR_P4_CRU_ESCR3} } + }, + + { /* REPLAY_EVENT */ + 0x05, 0x09, + { { CTR_IQ_4, MSR_P4_CRU_ESCR2}, + { CTR_IQ_5, MSR_P4_CRU_ESCR3} } + }, + + { /* INSTR_RETIRED */ + 0x04, 0x02, + { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, + { CTR_IQ_5, MSR_P4_CRU_ESCR1} } + }, + + { /* UOPS_RETIRED */ + 0x04, 0x01, + { { CTR_IQ_4, MSR_P4_CRU_ESCR0}, + { CTR_IQ_5, MSR_P4_CRU_ESCR1} } + }, + + { /* UOP_TYPE */ + 0x02, 0x02, + { { CTR_IQ_4, MSR_P4_RAT_ESCR0}, + { CTR_IQ_5, MSR_P4_RAT_ESCR1} } + }, + + { /* RETIRED_MISPRED_BRANCH_TYPE */ + 0x02, 0x05, + { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, + { CTR_MS_2, MSR_P4_TBPU_ESCR1} } + }, + + { /* RETIRED_BRANCH_TYPE */ + 0x02, 0x04, + { { CTR_MS_0, MSR_P4_TBPU_ESCR0}, + { CTR_MS_2, MSR_P4_TBPU_ESCR1} } + } +}; + + +#define MISC_PMC_ENABLED_P(x) ((x) & 1 << 7) + +#define ESCR_RESERVED_BITS 0x80000003 +#define ESCR_CLEAR(escr) ((escr) &= ESCR_RESERVED_BITS) +#define ESCR_SET_USR_0(escr, usr) ((escr) |= (((usr) & 1) << 2)) +#define ESCR_SET_OS_0(escr, os) ((escr) |= (((os) & 1) << 3)) +#define ESCR_SET_USR_1(escr, usr) ((escr) |= (((usr) & 1))) +#define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1)) +#define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x3f) << 25)) +#define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9)) +#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) +#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0) + +#define CCCR_RESERVED_BITS 0x38030FFF +#define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS) +#define CCCR_SET_REQUIRED_BITS(cccr) ((cccr) |= 0x00030000) +#define CCCR_SET_ESCR_SELECT(cccr, sel) ((cccr) |= (((sel) & 0x07) << 13)) +#define CCCR_SET_PMI_OVF_0(cccr) ((cccr) |= (1<<26)) +#define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27)) +#define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12)) +#define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12)) +#define CCCR_READ(low, high, i) do {rdmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) +#define CCCR_WRITE(low, high, i) do {wrmsr(p4_counters[(i)].cccr_address, (low), (high));} while (0) +#define CCCR_OVF_P(cccr) ((cccr) & (1U<<31)) +#define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31))) + +#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0) +#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0) +#define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000)) + + +/* this assigns a "stagger" to the current CPU, which is used throughout + the code in this module as an extra array offset, to select the "even" + or "odd" part of all the divided resources. */ +static unsigned int get_stagger(void) +{ +#ifdef CONFIG_SMP + int cpu = smp_processor_id(); + return (cpu != first_cpu(cpu_sibling_map[cpu])); +#endif + return 0; +} + + +/* finally, mediate access to a real hardware counter + by passing a "virtual" counter numer to this macro, + along with your stagger setting. */ +#define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger))) + +static unsigned long reset_value[NUM_COUNTERS_NON_HT]; + + +static void p4_fill_in_addresses(struct op_msrs * const msrs) +{ + unsigned int i; + unsigned int addr, stag; + + setup_num_counters(); + stag = get_stagger(); + + /* the counter registers we pay attention to */ + for (i = 0; i < num_counters; ++i) { + msrs->counters[i].addr = + p4_counters[VIRT_CTR(stag, i)].counter_address; + } + + /* FIXME: bad feeling, we don't save the 10 counters we don't use. */ + + /* 18 CCCR registers */ + for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag; + addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + + /* 43 ESCR registers in three or four discontiguous group */ + for (addr = MSR_P4_BSU_ESCR0 + stag; + addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + + /* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1 + * to avoid special case in nmi_{save|restore}_registers() */ + if (boot_cpu_data.x86_model >= 0x3) { + for (addr = MSR_P4_BSU_ESCR0 + stag; + addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + } else { + for (addr = MSR_P4_IQ_ESCR0 + stag; + addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + } + + for (addr = MSR_P4_RAT_ESCR0 + stag; + addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + + for (addr = MSR_P4_MS_ESCR0 + stag; + addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + + for (addr = MSR_P4_IX_ESCR0 + stag; + addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { + msrs->controls[i].addr = addr; + } + + /* there are 2 remaining non-contiguously located ESCRs */ + + if (num_counters == NUM_COUNTERS_NON_HT) { + /* standard non-HT CPUs handle both remaining ESCRs*/ + msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; + msrs->controls[i++].addr = MSR_P4_CRU_ESCR4; + + } else if (stag == 0) { + /* HT CPUs give the first remainder to the even thread, as + the 32nd control register */ + msrs->controls[i++].addr = MSR_P4_CRU_ESCR4; + + } else { + /* and two copies of the second to the odd thread, + for the 22st and 23nd control registers */ + msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; + msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; + } +} + + +static void pmc_setup_one_p4_counter(unsigned int ctr) +{ + int i; + int const maxbind = 2; + unsigned int cccr = 0; + unsigned int escr = 0; + unsigned int high = 0; + unsigned int counter_bit; + struct p4_event_binding *ev = NULL; + unsigned int stag; + + stag = get_stagger(); + + /* convert from counter *number* to counter *bit* */ + counter_bit = 1 << VIRT_CTR(stag, ctr); + + /* find our event binding structure. */ + if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) { + printk(KERN_ERR + "oprofile: P4 event code 0x%lx out of range\n", + counter_config[ctr].event); + return; + } + + ev = &(p4_events[counter_config[ctr].event - 1]); + + for (i = 0; i < maxbind; i++) { + if (ev->bindings[i].virt_counter & counter_bit) { + + /* modify ESCR */ + ESCR_READ(escr, high, ev, i); + ESCR_CLEAR(escr); + if (stag == 0) { + ESCR_SET_USR_0(escr, counter_config[ctr].user); + ESCR_SET_OS_0(escr, counter_config[ctr].kernel); + } else { + ESCR_SET_USR_1(escr, counter_config[ctr].user); + ESCR_SET_OS_1(escr, counter_config[ctr].kernel); + } + ESCR_SET_EVENT_SELECT(escr, ev->event_select); + ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); + ESCR_WRITE(escr, high, ev, i); + + /* modify CCCR */ + CCCR_READ(cccr, high, VIRT_CTR(stag, ctr)); + CCCR_CLEAR(cccr); + CCCR_SET_REQUIRED_BITS(cccr); + CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); + if (stag == 0) { + CCCR_SET_PMI_OVF_0(cccr); + } else { + CCCR_SET_PMI_OVF_1(cccr); + } + CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); + return; + } + } + + printk(KERN_ERR + "oprofile: P4 event code 0x%lx no binding, stag %d ctr %d\n", + counter_config[ctr].event, stag, ctr); +} + + +static void p4_setup_ctrs(struct op_msrs const * const msrs) +{ + unsigned int i; + unsigned int low, high; + unsigned int addr; + unsigned int stag; + + stag = get_stagger(); + + rdmsr(MSR_IA32_MISC_ENABLE, low, high); + if (! MISC_PMC_ENABLED_P(low)) { + printk(KERN_ERR "oprofile: P4 PMC not available\n"); + return; + } + + /* clear the cccrs we will use */ + for (i = 0 ; i < num_counters ; i++) { + rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); + CCCR_CLEAR(low); + CCCR_SET_REQUIRED_BITS(low); + wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); + } + + /* clear cccrs outside our concern */ + for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) { + rdmsr(p4_unused_cccr[i], low, high); + CCCR_CLEAR(low); + CCCR_SET_REQUIRED_BITS(low); + wrmsr(p4_unused_cccr[i], low, high); + } + + /* clear all escrs (including those outside our concern) */ + for (addr = MSR_P4_BSU_ESCR0 + stag; + addr < MSR_P4_IQ_ESCR0; addr += addr_increment()) { + wrmsr(addr, 0, 0); + } + + /* On older models clear also MSR_P4_IQ_ESCR0/1 */ + if (boot_cpu_data.x86_model < 0x3) { + wrmsr(MSR_P4_IQ_ESCR0, 0, 0); + wrmsr(MSR_P4_IQ_ESCR1, 0, 0); + } + + for (addr = MSR_P4_RAT_ESCR0 + stag; + addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { + wrmsr(addr, 0, 0); + } + + for (addr = MSR_P4_MS_ESCR0 + stag; + addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ + wrmsr(addr, 0, 0); + } + + for (addr = MSR_P4_IX_ESCR0 + stag; + addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ + wrmsr(addr, 0, 0); + } + + if (num_counters == NUM_COUNTERS_NON_HT) { + wrmsr(MSR_P4_CRU_ESCR4, 0, 0); + wrmsr(MSR_P4_CRU_ESCR5, 0, 0); + } else if (stag == 0) { + wrmsr(MSR_P4_CRU_ESCR4, 0, 0); + } else { + wrmsr(MSR_P4_CRU_ESCR5, 0, 0); + } + + /* setup all counters */ + for (i = 0 ; i < num_counters ; ++i) { + if (counter_config[i].enabled) { + reset_value[i] = counter_config[i].count; + pmc_setup_one_p4_counter(i); + CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); + } else { + reset_value[i] = 0; + } + } +} + + +extern void xenoprof_log_event(struct vcpu *v, unsigned long eip, + int mode, int event); + +static int p4_check_ctrs(unsigned int const cpu, + struct op_msrs const * const msrs, + struct cpu_user_regs * const regs) +{ + unsigned long ctr, low, high, stag, real; + int i; + int ovf = 0; + unsigned long eip = regs->eip; + int mode = 0; + + if (guest_kernel_mode(current, regs)) + mode = 1; + else if (ring_0(regs)) + mode = 2; + + stag = get_stagger(); + + for (i = 0; i < num_counters; ++i) { + + if (!reset_value[i]) + continue; + + /* + * there is some eccentricity in the hardware which + * requires that we perform 2 extra corrections: + * + * - check both the CCCR:OVF flag for overflow and the + * counter high bit for un-flagged overflows. + * + * - write the counter back twice to ensure it gets + * updated properly. + * + * the former seems to be related to extra NMIs happening + * during the current NMI; the latter is reported as errata + * N15 in intel doc 249199-029, pentium 4 specification + * update, though their suggested work-around does not + * appear to solve the problem. + */ + + real = VIRT_CTR(stag, i); + + CCCR_READ(low, high, real); + CTR_READ(ctr, high, real); + if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) { + xenoprof_log_event(current, eip, mode, i); + CTR_WRITE(reset_value[i], real); + CCCR_CLEAR_OVF(low); + CCCR_WRITE(low, high, real); + CTR_WRITE(reset_value[i], real); + ovf = 1; + } + } + + /* P4 quirk: you have to re-unmask the apic vector */ + apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); + + return ovf; +} + + +static void p4_start(struct op_msrs const * const msrs) +{ + unsigned int low, high, stag; + int i; + + stag = get_stagger(); + + for (i = 0; i < num_counters; ++i) { + if (!reset_value[i]) + continue; + CCCR_READ(low, high, VIRT_CTR(stag, i)); + CCCR_SET_ENABLE(low); + CCCR_WRITE(low, high, VIRT_CTR(stag, i)); + } +} + + +static void p4_stop(struct op_msrs const * const msrs) +{ + unsigned int low, high, stag; + int i; + + stag = get_stagger(); + + for (i = 0; i < num_counters; ++i) { + CCCR_READ(low, high, VIRT_CTR(stag, i)); + CCCR_SET_DISABLE(low); + CCCR_WRITE(low, high, VIRT_CTR(stag, i)); + } +} + + +#ifdef CONFIG_SMP +struct op_x86_model_spec const op_p4_ht2_spec = { + .num_counters = NUM_COUNTERS_HT2, + .num_controls = NUM_CONTROLS_HT2, + .fill_in_addresses = &p4_fill_in_addresses, + .setup_ctrs = &p4_setup_ctrs, + .check_ctrs = &p4_check_ctrs, + .start = &p4_start, + .stop = &p4_stop +}; +#endif + +struct op_x86_model_spec const op_p4_spec = { + .num_counters = NUM_COUNTERS_NON_HT, + .num_controls = NUM_CONTROLS_NON_HT, + .fill_in_addresses = &p4_fill_in_addresses, + .setup_ctrs = &p4_setup_ctrs, + .check_ctrs = &p4_check_ctrs, + .start = &p4_start, + .stop = &p4_stop +}; diff --git a/xen/arch/x86/oprofile/op_model_ppro.c b/xen/arch/x86/oprofile/op_model_ppro.c new file mode 100644 index 0000000000..b982443928 --- /dev/null +++ b/xen/arch/x86/oprofile/op_model_ppro.c @@ -0,0 +1,153 @@ +/** + * @file op_model_ppro.h + * pentium pro / P6 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + * @author Philippe Elie + * @author Graydon Hoare + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "op_x86_model.h" +#include "op_counter.h" + +#define NUM_COUNTERS 2 +#define NUM_CONTROLS 2 + +#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0) +#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), -1);} while (0) +#define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) + +#define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), (h));} while (0) +#define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), (h));} while (0) +#define CTRL_SET_ACTIVE(n) (n |= (1<<22)) +#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) +#define CTRL_CLEAR(x) (x &= (1<<21)) +#define CTRL_SET_ENABLE(val) (val |= 1<<20) +#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) +#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) +#define CTRL_SET_UM(val, m) (val |= (m << 8)) +#define CTRL_SET_EVENT(val, e) (val |= e) + +static unsigned long reset_value[NUM_COUNTERS]; + +static void ppro_fill_in_addresses(struct op_msrs * const msrs) +{ + msrs->counters[0].addr = MSR_P6_PERFCTR0; + msrs->counters[1].addr = MSR_P6_PERFCTR1; + + msrs->controls[0].addr = MSR_P6_EVNTSEL0; + msrs->controls[1].addr = MSR_P6_EVNTSEL1; +} + + +static void ppro_setup_ctrs(struct op_msrs const * const msrs) +{ + unsigned int low, high; + int i; + + /* clear all counters */ + for (i = 0 ; i < NUM_CONTROLS; ++i) { + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_WRITE(low, high, msrs, i); + } + + /* avoid a false detection of ctr overflows in NMI handler */ + for (i = 0; i < NUM_COUNTERS; ++i) { + CTR_WRITE(1, msrs, i); + } + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if (counter_config[i].enabled) { + reset_value[i] = counter_config[i].count; + + CTR_WRITE(counter_config[i].count, msrs, i); + + CTRL_READ(low, high, msrs, i); + CTRL_CLEAR(low); + CTRL_SET_ENABLE(low); + CTRL_SET_USR(low, counter_config[i].user); + CTRL_SET_KERN(low, counter_config[i].kernel); + CTRL_SET_UM(low, counter_config[i].unit_mask); + CTRL_SET_EVENT(low, counter_config[i].event); + CTRL_WRITE(low, high, msrs, i); + } + } +} + + +extern void xenoprof_log_event(struct vcpu *v, unsigned long eip, + int mode, int event); + +static int ppro_check_ctrs(unsigned int const cpu, + struct op_msrs const * const msrs, + struct cpu_user_regs * const regs) +{ + unsigned int low, high; + int i; + int ovf = 0; + unsigned long eip = regs->eip; + int mode = 0; + + if ( guest_kernel_mode(current, regs) ) + mode = 1; + else if ( ring_0(regs) ) + mode = 2; + + for (i = 0 ; i < NUM_COUNTERS; ++i) { + CTR_READ(low, high, msrs, i); + if (CTR_OVERFLOWED(low)) { + xenoprof_log_event(current, eip, mode, i); + CTR_WRITE(reset_value[i], msrs, i); + ovf = 1; + } + } + + /* Only P6 based Pentium M need to re-unmask the apic vector but it + * doesn't hurt other P6 variant */ + apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); + + return ovf; +} + + +static void ppro_start(struct op_msrs const * const msrs) +{ + unsigned int low,high; + CTRL_READ(low, high, msrs, 0); + CTRL_SET_ACTIVE(low); + CTRL_WRITE(low, high, msrs, 0); +} + + +static void ppro_stop(struct op_msrs const * const msrs) +{ + unsigned int low,high; + CTRL_READ(low, high, msrs, 0); + CTRL_SET_INACTIVE(low); + CTRL_WRITE(low, high, msrs, 0); +} + + +struct op_x86_model_spec const op_ppro_spec = { + .num_counters = NUM_COUNTERS, + .num_controls = NUM_CONTROLS, + .fill_in_addresses = &ppro_fill_in_addresses, + .setup_ctrs = &ppro_setup_ctrs, + .check_ctrs = &ppro_check_ctrs, + .start = &ppro_start, + .stop = &ppro_stop +}; diff --git a/xen/arch/x86/oprofile/op_x86_model.h b/xen/arch/x86/oprofile/op_x86_model.h new file mode 100644 index 0000000000..2858e8bf90 --- /dev/null +++ b/xen/arch/x86/oprofile/op_x86_model.h @@ -0,0 +1,51 @@ +/** + * @file op_x86_model.h + * interface to x86 model-specific MSR operations + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author Graydon Hoare + */ + +#ifndef OP_X86_MODEL_H +#define OP_X86_MODEL_H + +struct op_saved_msr { + unsigned int high; + unsigned int low; +}; + +struct op_msr { + unsigned long addr; + struct op_saved_msr saved; +}; + +struct op_msrs { + struct op_msr * counters; + struct op_msr * controls; +}; + +struct pt_regs; + +/* The model vtable abstracts the differences between + * various x86 CPU model's perfctr support. + */ +struct op_x86_model_spec { + unsigned int const num_counters; + unsigned int const num_controls; + void (*fill_in_addresses)(struct op_msrs * const msrs); + void (*setup_ctrs)(struct op_msrs const * const msrs); + int (*check_ctrs)(unsigned int const cpu, + struct op_msrs const * const msrs, + struct cpu_user_regs * const regs); + void (*start)(struct op_msrs const * const msrs); + void (*stop)(struct op_msrs const * const msrs); +}; + +extern struct op_x86_model_spec const op_ppro_spec; +extern struct op_x86_model_spec const op_p4_spec; +extern struct op_x86_model_spec const op_p4_ht2_spec; +extern struct op_x86_model_spec const op_athlon_spec; + +#endif /* OP_X86_MODEL_H */ diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c new file mode 100644 index 0000000000..529c67b601 --- /dev/null +++ b/xen/arch/x86/oprofile/xenoprof.c @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2005 Hewlett-Packard Co. + * written by Aravind Menon & Jose Renato Santos + * (email: xenoprof@groups.hp.com) + */ + +#include +#include + +#include "op_counter.h" + +/* Limit amount of pages used for shared buffer (per domain) */ +#define MAX_OPROF_SHARED_PAGES 32 + +int active_domains[MAX_OPROF_DOMAINS]; +int active_ready[MAX_OPROF_DOMAINS]; +unsigned int adomains = 0; +unsigned int activated = 0; +struct domain *primary_profiler = NULL; +int xenoprof_state = XENOPROF_IDLE; + +u64 total_samples = 0; +u64 invalid_buffer_samples = 0; +u64 corrupted_buffer_samples = 0; +u64 lost_samples = 0; +u64 active_samples = 0; +u64 idle_samples = 0; +u64 others_samples = 0; + + +extern int nmi_init(int *num_events, int *is_primary, char *cpu_type); +extern int nmi_reserve_counters(void); +extern int nmi_setup_events(void); +extern int nmi_enable_virq(void); +extern int nmi_start(void); +extern void nmi_stop(void); +extern void nmi_disable_virq(void); +extern void nmi_release_counters(void); + +int is_active(struct domain *d) +{ + xenoprof_t *x = d->xenoprof; + if ( x ) + { + if ( x->domain_type == XENOPROF_DOMAIN_ACTIVE ) + return 1; + else + return 0; + } + else + return 0; +} + +int is_profiled(struct domain *d) +{ + return is_active(d); +} + +static void xenoprof_reset_stat(void) +{ + total_samples = 0; + invalid_buffer_samples = 0; + corrupted_buffer_samples = 0; + lost_samples = 0; + active_samples = 0; + idle_samples = 0; + others_samples = 0; + + return; +} + +static void xenoprof_reset_buf(struct domain *d) +{ + int j; + xenoprof_buf_t *buf; + + if ( !d->xenoprof ) + { + printk("xenoprof_reset_buf: ERROR - Unexpected Xenoprof NULL pointer \n"); + return; + } + + for ( j=0; jxenoprof->vcpu[j].buffer; + if ( buf ) + { + buf->event_head = 0; + buf->event_tail = 0; + } + } +} + +int active_index(struct domain *d) +{ + int i; + int id; + + id = d->domain_id; + for ( i=0; ixenoprof; + if ( x ) + { + x->domain_ready = 1; + x->domain_type = XENOPROF_DOMAIN_ACTIVE; + active_ready[ind] = 1; + activated++; + return 0; + } + else + return -EPERM; +} + +int reset_active(struct domain *d) +{ + int ind; + xenoprof_t *x; + + ind = active_index(d); + if ( ind <0 ) + return -EPERM; + + x = d->xenoprof; + if ( x ) + { + x->domain_ready = 0; + x->domain_type = XENOPROF_DOMAIN_IGNORED; + active_ready[ind] = 0; + activated--; + if ( activated <= 0 ) + adomains = 0; + return 0; + } + else + return -EPERM; +} + +int set_active_domains(int num) +{ + int primary; + int i; + struct domain *d; + + /* reset any existing active domains from previous runs */ + for ( i=0; i= MAX_OPROF_DOMAINS ) + return -E2BIG; + else + { + active_domains[num] = primary_profiler->domain_id; + num++; + } + } + + adomains = num; + activated = 0; + + for ( i=0; idomain) ) + { + others_samples++; + return; + } + + v = &vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id]; + + /* Sanity check. Should never happen */ + if ( !v->buffer ) + { + invalid_buffer_samples++; + return; + } + + buf = vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id].buffer; + + head = buf->event_head; + tail = buf->event_tail; + size = v->event_size; + + /* make sure indexes in shared buffer are sane */ + if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) ) + { + corrupted_buffer_samples++; + return; + } + + if ( (head == tail - 1) || (head == size - 1 && tail == 0) ) + { + buf->lost_samples++; + lost_samples++; + } + else + { + buf->event_log[head].eip = eip; + buf->event_log[head].mode = mode; + buf->event_log[head].event = event; + head++; + if ( head >= size ) + head = 0; + buf->event_head = head; + active_samples++; + if ( mode == 0 ) + buf->user_samples++; + else if ( mode == 1 ) + buf->kernel_samples++; + else + buf->xen_samples++; + } +} + +char *alloc_xenoprof_buf(struct domain *d, int npages) +{ + char *rawbuf; + int i, order; + + /* allocate pages to store sample buffer shared with domain */ + order = get_order_from_pages(npages); + rawbuf = alloc_xenheap_pages(order); + if( rawbuf == NULL ) + { + printk("alloc_xenoprof_buf(): memory allocation failed\n"); + return 0; + } + + /* Share pages so that kernel can map it */ + for ( i=0; ixenoprof = xmalloc(xenoprof_t); + + if ( !d->xenoprof ) + { + printk ("alloc_xenoprof_struct(): memory " + "allocation (xmalloc) failed\n"); + return -ENOMEM; + } + + memset(d->xenoprof, 0, sizeof(*d->xenoprof)); + + nvcpu = 0; + for_each_vcpu(d, v) + nvcpu++; + + /* reduce buffer size if necessary to limit pages allocated */ + bufsize = sizeof(xenoprof_buf_t) + + (max_samples - 1) * sizeof(struct event_log); + max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; + if ( bufsize > max_bufsize ) + { + bufsize = max_bufsize; + max_samples = ( (max_bufsize - sizeof(xenoprof_buf_t)) / + sizeof(struct event_log) ) + 1; + } + + npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; + d->xenoprof->rawbuf = alloc_xenoprof_buf(d, npages); + if ( !d->xenoprof->rawbuf ) + { + xfree(d->xenoprof); + d->xenoprof = NULL; + return -ENOMEM; + } + + d->xenoprof->npages = npages; + d->xenoprof->nbuf = nvcpu; + d->xenoprof->bufsize = bufsize; + d->xenoprof->domain_ready = 0; + d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; + + /* Update buffer pointers for active vcpus */ + i=0; + for_each_vcpu(d, v) + { + d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples; + d->xenoprof->vcpu[v->vcpu_id].buffer = + (xenoprof_buf_t *)&d->xenoprof->rawbuf[i * bufsize]; + d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples; + d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id; + + i++; + /* in the unlikely case that the number of active vcpus changes */ + if ( i >= nvcpu ) + break; + } + + return 0; +} + +void free_xenoprof_pages(struct domain *d) +{ + xenoprof_t *x; + int order; + + x = d->xenoprof; + + if ( x ) + { + if ( x->rawbuf ) + { + order = get_order_from_pages(x->npages); + free_xenheap_pages(x->rawbuf, order); + } + xfree(x); + d->xenoprof = NULL; + } +} + +int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) +{ + xenoprof_init_result_t result; + int is_primary, num_events; + struct domain *d = current->domain; + int ret; + + ret = nmi_init(&num_events, &is_primary, result.cpu_type); + if ( is_primary ) + primary_profiler = current->domain; + + if ( ret < 0 ) + goto err; + + /* we allocate xenoprof struct and buffers only at first time + xenoprof_init is called. Memory is then kept until domain is destroyed */ + if ( !d->xenoprof ) + { + if ( (ret = alloc_xenoprof_struct(d, max_samples)) < 0 ) + goto err; + } + + xenoprof_reset_buf(d); + + d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; + d->xenoprof->domain_ready = 0; + d->xenoprof->is_primary = is_primary; + + result.is_primary = is_primary; + result.num_events = num_events; + result.nbuf = d->xenoprof->nbuf; + result.bufsize = d->xenoprof->bufsize; + result.buf_maddr = __pa(d->xenoprof->rawbuf); + + if ( copy_to_user((void *)init_result, (void *)&result, sizeof(result)) ) + { + ret = -EFAULT; + goto err; + } + + return ret; + + err: + if ( primary_profiler == current->domain ) + primary_profiler = NULL; + return ret; +} + +#define PRIV_OP(op) ( (op == XENOPROF_set_active) \ + || (op == XENOPROF_reserve_counters) \ + || (op == XENOPROF_setup_events) \ + || (op == XENOPROF_start) \ + || (op == XENOPROF_stop) \ + || (op == XENOPROF_release_counters) \ + || (op == XENOPROF_shutdown)) + +int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) +{ + int ret = 0; + + if ( PRIV_OP(op) && current->domain != primary_profiler ) + { + printk("xenoprof: dom %d denied privileged operation %d\n", + current->domain->domain_id, op); + return -EPERM; + } + + switch ( op ) + { + case XENOPROF_init: + ret = xenoprof_init((int)arg1, (xenoprof_init_result_t *)arg2); + break; + + case XENOPROF_set_active: + if ( xenoprof_state != XENOPROF_IDLE ) + return -EPERM; + if ( arg2 > MAX_OPROF_DOMAINS ) + return -E2BIG; + if ( copy_from_user((void *)&active_domains, + (void *)arg1, arg2*sizeof(int)) ) + return -EFAULT; + ret = set_active_domains(arg2); + break; + + case XENOPROF_reserve_counters: + if ( xenoprof_state != XENOPROF_IDLE ) + return -EPERM; + ret = nmi_reserve_counters(); + if ( !ret ) + xenoprof_state = XENOPROF_COUNTERS_RESERVED; + break; + + case XENOPROF_setup_events: + if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) + return -EPERM; + if ( adomains == 0 ) + { + set_active_domains(0); + } + + if ( copy_from_user((void *)&counter_config, (void *)arg1, + arg2 * sizeof(struct op_counter_config)) ) + return -EFAULT; + ret = nmi_setup_events(); + if ( !ret ) + xenoprof_state = XENOPROF_READY; + break; + + case XENOPROF_enable_virq: + if ( current->domain == primary_profiler ) + { + nmi_enable_virq(); + xenoprof_reset_stat(); + } + xenoprof_reset_buf(current->domain); + ret = set_active(current->domain); + break; + + case XENOPROF_start: + if ( (xenoprof_state == XENOPROF_READY) && + (activated == adomains) ) + { + ret = nmi_start(); + } + else + ret= -EPERM; + + if ( !ret ) + xenoprof_state = XENOPROF_PROFILING; + break; + + case XENOPROF_stop: + if ( xenoprof_state != XENOPROF_PROFILING ) + return -EPERM; + nmi_stop(); + xenoprof_state = XENOPROF_READY; + break; + + case XENOPROF_disable_virq: + if ( (xenoprof_state == XENOPROF_PROFILING) && + (is_active(current->domain)) ) + return -EPERM; + ret = reset_active(current->domain); + break; + + case XENOPROF_release_counters: + if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || + (xenoprof_state == XENOPROF_READY) ) + { + xenoprof_state = XENOPROF_IDLE; + nmi_release_counters(); + nmi_disable_virq(); + } + else + ret = -EPERM; + break; + + case XENOPROF_shutdown: + if ( xenoprof_state == XENOPROF_IDLE ) + { + activated = 0; + adomains=0; + primary_profiler = NULL; + ret = 0; + } + else + ret = -EPERM; + break; + + default: + ret = -EINVAL; + } + + if ( ret < 0 ) + printk("xenoprof: operation %d failed for dom %d (status : %d)\n", + op, current->domain->domain_id, ret); + + return ret; +} diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 8efd96fc1d..79689d65be 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -645,6 +645,7 @@ ENTRY(hypercall_table) .long do_nmi_op .long do_arch_sched_op .long do_callback_op /* 30 */ + .long do_xenoprof_op .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -681,6 +682,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ .byte 2 /* do_callback_op */ /* 30 */ + .byte 3 /* do_xenoprof_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 6af4a0162b..266c1c9971 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -553,6 +553,7 @@ ENTRY(hypercall_table) .quad do_nmi_op .quad do_arch_sched_op .quad do_callback_op /* 30 */ + .quad do_xenoprof_op .rept NR_hypercalls-((.-hypercall_table)/8) .quad do_ni_hypercall .endr @@ -589,6 +590,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ .byte 2 /* do_callback_op */ /* 30 */ + .byte 3 /* do_xenoprof_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 8dba3ad541..c79bc6f859 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -61,6 +61,7 @@ #define __HYPERVISOR_nmi_op 28 #define __HYPERVISOR_sched_op 29 #define __HYPERVISOR_callback_op 30 +#define __HYPERVISOR_xenoprof_op 31 /* * VIRTUAL INTERRUPTS @@ -77,7 +78,8 @@ #define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */ #define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */ #define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */ -#define NR_VIRQS 8 +#define VIRQ_XENOPROF 7 /* XenOprofile interrupt: new sample available */ +#define NR_VIRQS 9 /* * MMU-UPDATE REQUESTS diff --git a/xen/include/public/xenoprof.h b/xen/include/public/xenoprof.h new file mode 100644 index 0000000000..b8ea8a8aba --- /dev/null +++ b/xen/include/public/xenoprof.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * xenoprof.h + * + * Interface for enabling system wide profiling based on hardware performance + * counters + * + * Copyright (C) 2005 Hewlett-Packard Co. + * Written by Aravind Menon & Jose Renato Santos + */ + +#ifndef __XEN_PUBLIC_XENOPROF_H__ +#define __XEN_PUBLIC_XENOPROF_H__ + +/* + * Commands to HYPERVISOR_pmc_op(). + */ +#define XENOPROF_init 0 +#define XENOPROF_set_active 1 +#define XENOPROF_reserve_counters 3 +#define XENOPROF_setup_events 4 +#define XENOPROF_enable_virq 5 +#define XENOPROF_start 6 +#define XENOPROF_stop 7 +#define XENOPROF_disable_virq 8 +#define XENOPROF_release_counters 9 +#define XENOPROF_shutdown 10 + +#define MAX_OPROF_EVENTS 32 +#define MAX_OPROF_DOMAINS 25 +#define XENOPROF_CPU_TYPE_SIZE 64 + +/* Xenoprof performance events (not Xen events) */ +struct event_log { + uint64_t eip; + uint8_t mode; + uint8_t event; +}; + +/* Xenoprof buffer shared between Xen and domain - 1 per VCPU */ +typedef struct xenoprof_buf { + uint32_t event_head; + uint32_t event_tail; + uint32_t event_size; + uint32_t vcpu_id; + uint64_t xen_samples; + uint64_t kernel_samples; + uint64_t user_samples; + uint64_t lost_samples; + struct event_log event_log[1]; +} xenoprof_buf_t; + +typedef struct xenoprof_init_result { + int32_t num_events; + int32_t is_primary; + int32_t nbuf; + int32_t bufsize; + uint64_t buf_maddr; + char cpu_type[XENOPROF_CPU_TYPE_SIZE]; +} xenoprof_init_result_t; + + +#endif /* __XEN_PUBLIC_XENOPROF_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 1a74f74a82..791c5665b9 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -14,6 +14,7 @@ #include #include #include +#include extern unsigned long volatile jiffies; extern rwlock_t domlist_lock; @@ -155,6 +156,9 @@ struct domain /* Control-plane tools handle for this domain. */ xen_domain_handle_t handle; + + /* pointer to xenoprof data (oprofile support) */ + xenoprof_t *xenoprof; }; struct domain_setup_info diff --git a/xen/include/xen/xenoprof.h b/xen/include/xen/xenoprof.h new file mode 100644 index 0000000000..f763eb1077 --- /dev/null +++ b/xen/include/xen/xenoprof.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * xenoprof.h + * + * Xenoprof: Xenoprof enables performance profiling in Xen + * + * Copyright (C) 2005 Hewlett-Packard Co. + * written by Aravind Menon & Jose Renato Santos + */ + +#ifndef __XEN_XENOPROF_H__ +#define __XEN_XENOPROF_H__ + +#include + +#define XENOPROF_DOMAIN_IGNORED 0 +#define XENOPROF_DOMAIN_ACTIVE 1 + +#define XENOPROF_IDLE 0 +#define XENOPROF_COUNTERS_RESERVED 1 +#define XENOPROF_READY 2 +#define XENOPROF_PROFILING 3 + + +typedef struct xenoprof_vcpu { + int event_size; + xenoprof_buf_t *buffer; +} xenoprof_vcpu_t; + +typedef struct xenoprof { + char* rawbuf; + int npages; + int nbuf; + int bufsize; + int domain_type; + int domain_ready; + int is_primary; + xenoprof_vcpu_t vcpu [MAX_VIRT_CPUS]; +} xenoprof_t; + +#endif /* __XEN__XENOPROF_H__ */ From 8dbed9810275bec1fb11a08bd18d925480640ee0 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 00:32:54 +0100 Subject: [PATCH 111/151] Support __XEN_INTERFACE_VERSION__ defined to the empty string. This can happen when building Linux with an old .config file which doesn't have a value for CONFIG_XEN_INTERFACE_VERSION. Signed-off-by: Christian Limpach --- xen/include/public/xen-compat.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xen/include/public/xen-compat.h b/xen/include/public/xen-compat.h index c4f235095d..4ef17bbaa8 100644 --- a/xen/include/public/xen-compat.h +++ b/xen/include/public/xen-compat.h @@ -14,8 +14,11 @@ #if defined(__XEN__) /* Xen is built with matching headers and implements the latest interface. */ #define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__ -#elif !defined(__XEN_INTERFACE_VERSION__) +#elif (__XEN_INTERFACE_VERSION__ - 0) == 0 /* Guests which do not specify a version get the legacy interface. */ +#ifdef __XEN_INTERFACE_VERSION__ +#undef __XEN_INTERFACE_VERSION__ +#endif #define __XEN_INTERFACE_VERSION__ 0x00000000 #endif From fa6aa0c4a4b046794a6e3fd47bc1b81e1c12783c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 09:57:36 +0100 Subject: [PATCH 112/151] Do not accept empty definition of __XEN_INTERFACE_VERSION__ in xen-compat.h. It leads to building a broken kernel image where the kernel sources end up using an unexpected interface version. In the case of Linux, the kernel expects to use the new sched_op() hypercall but ends up calling the legacy hypercall -- this breaks poll, reboot, and save/restore. A more acceptable patch would be to detect the empty definition in xen-compat.h and give a reasonable #error message to fail the build: the current error message is confusing. Signed-off-by: Keir Fraser --- xen/include/public/xen-compat.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/xen/include/public/xen-compat.h b/xen/include/public/xen-compat.h index 4ef17bbaa8..c4f235095d 100644 --- a/xen/include/public/xen-compat.h +++ b/xen/include/public/xen-compat.h @@ -14,11 +14,8 @@ #if defined(__XEN__) /* Xen is built with matching headers and implements the latest interface. */ #define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__ -#elif (__XEN_INTERFACE_VERSION__ - 0) == 0 +#elif !defined(__XEN_INTERFACE_VERSION__) /* Guests which do not specify a version get the legacy interface. */ -#ifdef __XEN_INTERFACE_VERSION__ -#undef __XEN_INTERFACE_VERSION__ -#endif #define __XEN_INTERFACE_VERSION__ 0x00000000 #endif From 2ec558319c08c178032bb1fe5ae7d10ff680c56f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 11:00:28 +0100 Subject: [PATCH 113/151] Clean up xenoprof code a bit. The main remaining TODO is to clean up the xenoprof hypercall interface. Signed-off-by: Keir Fraser --- .../arch/i386/oprofile/Makefile | 2 +- .../arch/x86_64/oprofile/Makefile | 2 +- xen/arch/x86/domain.c | 2 - xen/arch/x86/oprofile/nmi_int.c | 22 +- xen/arch/x86/oprofile/xenoprof.c | 225 ++++++++---------- xen/common/event_channel.c | 1 + xen/include/public/xen.h | 4 +- xen/include/public/xenoprof.h | 11 + xen/include/xen/sched.h | 4 +- xen/include/xen/xenoprof.h | 16 +- 10 files changed, 134 insertions(+), 155 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile index d283cd6c4d..e596c39c09 100644 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile @@ -6,7 +6,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -ifdef CONFIG_X86_XEN +ifdef CONFIG_XEN oprofile-y := $(DRIVER_OBJS) xenoprof.o else oprofile-y := $(DRIVER_OBJS) init.o backtrace.o diff --git a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile index 2f9d03b30d..589a7966e8 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile +++ b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile @@ -11,7 +11,7 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -ifdef +ifdef CONFIG_XEN OPROFILE-y := xenoprof.o else OPROFILE-y := init.o backtrace.o diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 8c0bb136fa..a657fba2eb 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -915,8 +915,6 @@ static void relinquish_memory(struct domain *d, struct list_head *list) spin_unlock_recursive(&d->page_alloc_lock); } -extern void free_xenoprof_pages(struct domain *d); - void domain_relinquish_resources(struct domain *d) { struct vcpu *v; diff --git a/xen/arch/x86/oprofile/nmi_int.c b/xen/arch/x86/oprofile/nmi_int.c index d9495b0566..3978428a32 100644 --- a/xen/arch/x86/oprofile/nmi_int.c +++ b/xen/arch/x86/oprofile/nmi_int.c @@ -45,31 +45,23 @@ extern size_t strlcpy(char *dest, const char *src, size_t size); int nmi_callback(struct cpu_user_regs *regs, int cpu) { - int xen_mode = 0; - int ovf; + int xen_mode, ovf; ovf = model->check_ctrs(cpu, &cpu_msrs[cpu], regs); xen_mode = ring_0(regs); - if ( ovf ) - { - if ( is_active(current->domain) ) - { - if ( !xen_mode ) - { - send_guest_vcpu_virq(current, VIRQ_XENOPROF); - } - } - } + if ( ovf && is_active(current->domain) && !xen_mode ) + send_guest_vcpu_virq(current, VIRQ_XENOPROF); + return 1; } -static void nmi_cpu_save_registers(struct op_msrs * msrs) +static void nmi_cpu_save_registers(struct op_msrs *msrs) { unsigned int const nr_ctrs = model->num_counters; unsigned int const nr_ctrls = model->num_controls; - struct op_msr * counters = msrs->counters; - struct op_msr * controls = msrs->controls; + struct op_msr *counters = msrs->counters; + struct op_msr *controls = msrs->controls; unsigned int i; for (i = 0; i < nr_ctrs; ++i) { diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c index 529c67b601..ecd9abd2cf 100644 --- a/xen/arch/x86/oprofile/xenoprof.c +++ b/xen/arch/x86/oprofile/xenoprof.c @@ -14,18 +14,18 @@ int active_domains[MAX_OPROF_DOMAINS]; int active_ready[MAX_OPROF_DOMAINS]; -unsigned int adomains = 0; -unsigned int activated = 0; -struct domain *primary_profiler = NULL; +unsigned int adomains; +unsigned int activated; +struct domain *primary_profiler; int xenoprof_state = XENOPROF_IDLE; -u64 total_samples = 0; -u64 invalid_buffer_samples = 0; -u64 corrupted_buffer_samples = 0; -u64 lost_samples = 0; -u64 active_samples = 0; -u64 idle_samples = 0; -u64 others_samples = 0; +u64 total_samples; +u64 invalid_buffer_samples; +u64 corrupted_buffer_samples; +u64 lost_samples; +u64 active_samples; +u64 idle_samples; +u64 others_samples; extern int nmi_init(int *num_events, int *is_primary, char *cpu_type); @@ -39,16 +39,8 @@ extern void nmi_release_counters(void); int is_active(struct domain *d) { - xenoprof_t *x = d->xenoprof; - if ( x ) - { - if ( x->domain_type == XENOPROF_DOMAIN_ACTIVE ) - return 1; - else - return 0; - } - else - return 0; + struct xenoprof *x = d->xenoprof; + return ((x != NULL) && (x->domain_type == XENOPROF_DOMAIN_ACTIVE)); } int is_profiled(struct domain *d) @@ -65,25 +57,24 @@ static void xenoprof_reset_stat(void) active_samples = 0; idle_samples = 0; others_samples = 0; - - return; } static void xenoprof_reset_buf(struct domain *d) { int j; - xenoprof_buf_t *buf; + struct xenoprof_buf *buf; - if ( !d->xenoprof ) + if ( d->xenoprof == NULL ) { - printk("xenoprof_reset_buf: ERROR - Unexpected Xenoprof NULL pointer \n"); + printk("xenoprof_reset_buf: ERROR - Unexpected " + "Xenoprof NULL pointer \n"); return; } - for ( j=0; jxenoprof->vcpu[j].buffer; - if ( buf ) + if ( buf != NULL ) { buf->event_head = 0; buf->event_tail = 0; @@ -93,62 +84,57 @@ static void xenoprof_reset_buf(struct domain *d) int active_index(struct domain *d) { - int i; - int id; + int i, id = d->domain_id; - id = d->domain_id; - for ( i=0; ixenoprof; - if ( x ) - { - x->domain_ready = 1; - x->domain_type = XENOPROF_DOMAIN_ACTIVE; - active_ready[ind] = 1; - activated++; - return 0; - } - else + if ( x == NULL ) return -EPERM; + + x->domain_ready = 1; + x->domain_type = XENOPROF_DOMAIN_ACTIVE; + active_ready[ind] = 1; + activated++; + + return 0; } int reset_active(struct domain *d) { int ind; - xenoprof_t *x; + struct xenoprof *x; ind = active_index(d); - if ( ind <0 ) + if ( ind < 0 ) return -EPERM; x = d->xenoprof; - if ( x ) - { - x->domain_ready = 0; - x->domain_type = XENOPROF_DOMAIN_IGNORED; - active_ready[ind] = 0; - activated--; - if ( activated <= 0 ) - adomains = 0; - return 0; - } - else + if ( x == NULL ) return -EPERM; + + x->domain_ready = 0; + x->domain_type = XENOPROF_DOMAIN_IGNORED; + active_ready[ind] = 0; + activated--; + if ( activated <= 0 ) + adomains = 0; + + return 0; } int set_active_domains(int num) @@ -157,13 +143,13 @@ int set_active_domains(int num) int i; struct domain *d; - /* reset any existing active domains from previous runs */ - for ( i=0; i= MAX_OPROF_DOMAINS ) return -E2BIG; - else - { - active_domains[num] = primary_profiler->domain_id; - num++; - } + active_domains[num] = primary_profiler->domain_id; + num++; } adomains = num; activated = 0; - for ( i=0; idomain) ) { - others_samples++; - return; + others_samples++; + return; } v = &vcpu->domain->xenoprof->vcpu[vcpu->vcpu_id]; /* Sanity check. Should never happen */ - if ( !v->buffer ) + if ( v->buffer == NULL ) { invalid_buffer_samples++; return; @@ -269,20 +251,19 @@ char *alloc_xenoprof_buf(struct domain *d, int npages) int i, order; /* allocate pages to store sample buffer shared with domain */ - order = get_order_from_pages(npages); - rawbuf = alloc_xenheap_pages(order); - if( rawbuf == NULL ) + order = get_order_from_pages(npages); + rawbuf = alloc_xenheap_pages(order); + if ( rawbuf == NULL ) { printk("alloc_xenoprof_buf(): memory allocation failed\n"); return 0; } /* Share pages so that kernel can map it */ - for ( i=0; ixenoprof = xmalloc(xenoprof_t); + d->xenoprof = xmalloc(struct xenoprof); - if ( !d->xenoprof ) + if ( d->xenoprof == NULL ) { printk ("alloc_xenoprof_struct(): memory " "allocation (xmalloc) failed\n"); @@ -305,23 +286,23 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples) memset(d->xenoprof, 0, sizeof(*d->xenoprof)); nvcpu = 0; - for_each_vcpu(d, v) + for_each_vcpu ( d, v ) nvcpu++; /* reduce buffer size if necessary to limit pages allocated */ - bufsize = sizeof(xenoprof_buf_t) + + bufsize = sizeof(struct xenoprof_buf) + (max_samples - 1) * sizeof(struct event_log); max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu; if ( bufsize > max_bufsize ) { bufsize = max_bufsize; - max_samples = ( (max_bufsize - sizeof(xenoprof_buf_t)) / + max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) / sizeof(struct event_log) ) + 1; } npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1; d->xenoprof->rawbuf = alloc_xenoprof_buf(d, npages); - if ( !d->xenoprof->rawbuf ) + if ( d->xenoprof->rawbuf == NULL ) { xfree(d->xenoprof); d->xenoprof = NULL; @@ -335,12 +316,12 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples) d->xenoprof->domain_type = XENOPROF_DOMAIN_IGNORED; /* Update buffer pointers for active vcpus */ - i=0; - for_each_vcpu(d, v) + i = 0; + for_each_vcpu ( d, v ) { d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples; d->xenoprof->vcpu[v->vcpu_id].buffer = - (xenoprof_buf_t *)&d->xenoprof->rawbuf[i * bufsize]; + (struct xenoprof_buf *)&d->xenoprof->rawbuf[i * bufsize]; d->xenoprof->vcpu[v->vcpu_id].buffer->event_size = max_samples; d->xenoprof->vcpu[v->vcpu_id].buffer->vcpu_id = v->vcpu_id; @@ -355,21 +336,21 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples) void free_xenoprof_pages(struct domain *d) { - xenoprof_t *x; + struct xenoprof *x; int order; x = d->xenoprof; + if ( x == NULL ) + return; - if ( x ) + if ( x->rawbuf != NULL ) { - if ( x->rawbuf ) - { - order = get_order_from_pages(x->npages); - free_xenheap_pages(x->rawbuf, order); - } - xfree(x); - d->xenoprof = NULL; + order = get_order_from_pages(x->npages); + free_xenheap_pages(x->rawbuf, order); } + + xfree(x); + d->xenoprof = NULL; } int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) @@ -386,13 +367,13 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) if ( ret < 0 ) goto err; - /* we allocate xenoprof struct and buffers only at first time - xenoprof_init is called. Memory is then kept until domain is destroyed */ - if ( !d->xenoprof ) - { - if ( (ret = alloc_xenoprof_struct(d, max_samples)) < 0 ) - goto err; - } + /* + * We allocate xenoprof struct and buffers only at first time xenoprof_init + * is called. Memory is then kept until domain is destroyed. + */ + if ( (d->xenoprof == NULL) && + ((ret = alloc_xenoprof_struct(d, max_samples)) < 0) ) + goto err; xenoprof_reset_buf(d); @@ -420,11 +401,11 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) return ret; } -#define PRIV_OP(op) ( (op == XENOPROF_set_active) \ +#define PRIV_OP(op) ( (op == XENOPROF_set_active) \ || (op == XENOPROF_reserve_counters) \ - || (op == XENOPROF_setup_events) \ - || (op == XENOPROF_start) \ - || (op == XENOPROF_stop) \ + || (op == XENOPROF_setup_events) \ + || (op == XENOPROF_start) \ + || (op == XENOPROF_stop) \ || (op == XENOPROF_release_counters) \ || (op == XENOPROF_shutdown)) @@ -432,7 +413,7 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) { int ret = 0; - if ( PRIV_OP(op) && current->domain != primary_profiler ) + if ( PRIV_OP(op) && (current->domain != primary_profiler) ) { printk("xenoprof: dom %d denied privileged operation %d\n", current->domain->domain_id, op); @@ -468,9 +449,7 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) return -EPERM; if ( adomains == 0 ) - { set_active_domains(0); - } if ( copy_from_user((void *)&counter_config, (void *)arg1, arg2 * sizeof(struct op_counter_config)) ) @@ -491,15 +470,12 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) break; case XENOPROF_start: + ret = -EPERM; if ( (xenoprof_state == XENOPROF_READY) && (activated == adomains) ) - { ret = nmi_start(); - } - else - ret= -EPERM; - if ( !ret ) + if ( ret == 0 ) xenoprof_state = XENOPROF_PROFILING; break; @@ -518,18 +494,19 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) break; case XENOPROF_release_counters: + ret = -EPERM; if ( (xenoprof_state == XENOPROF_COUNTERS_RESERVED) || (xenoprof_state == XENOPROF_READY) ) { xenoprof_state = XENOPROF_IDLE; nmi_release_counters(); nmi_disable_virq(); + ret = 0; } - else - ret = -EPERM; break; case XENOPROF_shutdown: + ret = -EPERM; if ( xenoprof_state == XENOPROF_IDLE ) { activated = 0; @@ -537,8 +514,6 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) primary_profiler = NULL; ret = 0; } - else - ret = -EPERM; break; default: diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index ccb96b0f65..a217e1be8b 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -57,6 +57,7 @@ static int virq_is_global(int virq) { case VIRQ_TIMER: case VIRQ_DEBUG: + case VIRQ_XENOPROF: rc = 0; break; default: diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index c79bc6f859..e18fbf9669 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -78,8 +78,8 @@ #define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */ #define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */ #define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */ -#define VIRQ_XENOPROF 7 /* XenOprofile interrupt: new sample available */ -#define NR_VIRQS 9 +#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */ +#define NR_VIRQS 8 /* * MMU-UPDATE REQUESTS diff --git a/xen/include/public/xenoprof.h b/xen/include/public/xenoprof.h index b8ea8a8aba..134df887c4 100644 --- a/xen/include/public/xenoprof.h +++ b/xen/include/public/xenoprof.h @@ -48,6 +48,7 @@ typedef struct xenoprof_buf { uint64_t lost_samples; struct event_log event_log[1]; } xenoprof_buf_t; +DEFINE_GUEST_HANDLE(xenoprof_buf_t); typedef struct xenoprof_init_result { int32_t num_events; @@ -57,7 +58,17 @@ typedef struct xenoprof_init_result { uint64_t buf_maddr; char cpu_type[XENOPROF_CPU_TYPE_SIZE]; } xenoprof_init_result_t; +DEFINE_GUEST_HANDLE(xenoprof_init_result_t); +typedef struct xenoprof_counter_config { + unsigned long count; + unsigned long enabled; + unsigned long event; + unsigned long kernel; + unsigned long user; + unsigned long unit_mask; +} xenoprof_counter_config_t; +DEFINE_GUEST_HANDLE(xenoprof_counter_config_t); #endif /* __XEN_PUBLIC_XENOPROF_H__ */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 791c5665b9..1ea48aae7d 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -157,8 +157,8 @@ struct domain /* Control-plane tools handle for this domain. */ xen_domain_handle_t handle; - /* pointer to xenoprof data (oprofile support) */ - xenoprof_t *xenoprof; + /* OProfile support. */ + struct xenoprof *xenoprof; }; struct domain_setup_info diff --git a/xen/include/xen/xenoprof.h b/xen/include/xen/xenoprof.h index f763eb1077..5ecb755f42 100644 --- a/xen/include/xen/xenoprof.h +++ b/xen/include/xen/xenoprof.h @@ -20,13 +20,12 @@ #define XENOPROF_READY 2 #define XENOPROF_PROFILING 3 - -typedef struct xenoprof_vcpu { +struct xenoprof_vcpu { int event_size; - xenoprof_buf_t *buffer; -} xenoprof_vcpu_t; + struct xenoprof_buf *buffer; +}; -typedef struct xenoprof { +struct xenoprof { char* rawbuf; int npages; int nbuf; @@ -34,7 +33,10 @@ typedef struct xenoprof { int domain_type; int domain_ready; int is_primary; - xenoprof_vcpu_t vcpu [MAX_VIRT_CPUS]; -} xenoprof_t; + struct xenoprof_vcpu vcpu [MAX_VIRT_CPUS]; +}; + +struct domain; +void free_xenoprof_pages(struct domain *d); #endif /* __XEN__XENOPROF_H__ */ From 97a7c0c266c59380eac2552ba211bd0983710d61 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 13:40:22 +0100 Subject: [PATCH 114/151] Power down an x86 system directly within domain0 rather than executing a shutdown hypercall. Domain0 is able to execute ACPI power-off code. Signed-off-by: Harry Butterworth --- linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index ba0b9b9112..7a3d2cc39d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -59,6 +59,10 @@ void machine_power_off(void) { /* We really want to get pending console data out before we die. */ xencons_force_flush(); +#if defined(__i386__) || defined(__x86_64__) + if (pm_power_off) + pm_power_off(); +#endif HYPERVISOR_shutdown(SHUTDOWN_poweroff); } From 9958cf716758bb5f709f09ab32670f4e950a36e0 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 13:41:58 +0100 Subject: [PATCH 115/151] Do not disable spurious irq debugging in i386 xenlinux. It may be masking underlying problems, and the problem it was intended to work around should be fixed properly. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c index b738343e89..bb9b6ed2f1 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c @@ -1848,10 +1848,6 @@ void __init setup_arch(char **cmdline_p) get_smp_config(); #endif - /* XXX Disable irqdebug until we have a way to avoid interrupt - * conflicts. */ - noirqdebug_setup(""); - register_memory(); if (xen_start_info->flags & SIF_INITDOMAIN) { From 28a88159e342cfc5d6986edb7fe3d9f5747cfaad Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 14:26:02 +0100 Subject: [PATCH 116/151] Avoid double slashes in linker object file lists. Signed-off-by: Keir Fraser --- xen/Rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index 66749058d3..1f4687f7fa 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -74,7 +74,7 @@ subdir-n := $(patsubst %,%/,$(patsubst %/,%,$(subdir-n))) subdir-y := $(patsubst %,%/,$(patsubst %/,%,$(subdir-y))) # Add explicitly declared subdirectories to the object list. -obj-y += $(patsubst %,%/built_in.o,$(subdir-y)) +obj-y += $(patsubst %/,%/built_in.o,$(subdir-y)) # Add implicitly declared subdirectories (in the object list) to the # subdirectory list, and rewrite the object-list entry. From f5de363eff322d17f0eecdaad7f653ecb8d338f5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 14:27:46 +0100 Subject: [PATCH 117/151] Turn pirq_mask into a generic bitmap type. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/irq.c | 27 +++++++++++---------------- xen/arch/x86/irq.c | 28 +++++++++++----------------- xen/include/xen/sched.h | 2 +- 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c index c42b5e2944..e7d0862d9c 100644 --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -1358,25 +1358,20 @@ static void __do_IRQ_guest(int irq) int pirq_guest_unmask(struct domain *d) { irq_desc_t *desc; - int i, j, pirq; - u32 m; + int pirq; shared_info_t *s = d->shared_info; - for ( i = 0; i < ARRAY_SIZE(d->pirq_mask); i++ ) + for ( pirq = find_first_bit(d->pirq_mask, NR_PIRQS); + pirq < NR_PIRQS; + pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq) ) { - m = d->pirq_mask[i]; - while ( (j = ffs(m)) != 0 ) - { - m &= ~(1 << --j); - pirq = (i << 5) + j; - desc = &irq_desc[pirq]; - spin_lock_irq(&desc->lock); - if ( !test_bit(d->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) && - test_and_clear_bit(pirq, &d->pirq_mask) && - (--((irq_guest_action_t *)desc->action)->in_flight == 0) ) - desc->handler->end(pirq); - spin_unlock_irq(&desc->lock); - } + desc = &irq_desc[pirq]; + spin_lock_irq(&desc->lock); + if ( !test_bit(d->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) && + test_and_clear_bit(pirq, &d->pirq_mask) && + (--((irq_guest_action_t *)desc->action)->in_flight == 0) ) + desc->handler->end(pirq); + spin_unlock_irq(&desc->lock); } return 0; diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index b260e9d627..0b9d88037b 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -171,26 +171,20 @@ static void __do_IRQ_guest(int vector) int pirq_guest_unmask(struct domain *d) { irq_desc_t *desc; - unsigned int i, j, pirq; - u32 m; + unsigned int pirq; shared_info_t *s = d->shared_info; - for ( i = 0; i < ARRAY_SIZE(d->pirq_mask); i++ ) + for ( pirq = find_first_bit(d->pirq_mask, NR_PIRQS); + pirq < NR_PIRQS; + pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq) ) { - m = d->pirq_mask[i]; - while ( m != 0 ) - { - j = find_first_set_bit(m); - m &= ~(1 << j); - pirq = (i << 5) + j; - desc = &irq_desc[irq_to_vector(pirq)]; - spin_lock_irq(&desc->lock); - if ( !test_bit(d->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) && - test_and_clear_bit(pirq, &d->pirq_mask) && - (--((irq_guest_action_t *)desc->action)->in_flight == 0) ) - desc->handler->end(irq_to_vector(pirq)); - spin_unlock_irq(&desc->lock); - } + desc = &irq_desc[irq_to_vector(pirq)]; + spin_lock_irq(&desc->lock); + if ( !test_bit(d->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) && + test_and_clear_bit(pirq, &d->pirq_mask) && + (--((irq_guest_action_t *)desc->action)->in_flight == 0) ) + desc->handler->end(irq_to_vector(pirq)); + spin_unlock_irq(&desc->lock); } return 0; diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 1ea48aae7d..bd01f83d27 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -134,7 +134,7 @@ struct domain */ #define NR_PIRQS 256 /* Put this somewhere sane! */ u16 pirq_to_evtchn[NR_PIRQS]; - u32 pirq_mask[NR_PIRQS/32]; + DECLARE_BITMAP(pirq_mask, NR_PIRQS); /* I/O capabilities (access to IRQs and memory-mapped I/O). */ struct rangeset *iomem_caps; From 6ca8eebc9bf8131c6adb05b2da5580cd10a9ef5b Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 15:58:00 +0100 Subject: [PATCH 118/151] Additional sanity / compatability checks during guest build. Signed-off-by: Steven Hand --- tools/libxc/xc_linux_build.c | 38 +++++++++++++++++++++++++++++++----- tools/libxc/xc_load_elf.c | 15 ++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 2dbcf9fac6..34338884fe 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -110,10 +110,10 @@ static int parse_features( if ( i == XENFEAT_NR_SUBMAPS*32 ) { - ERROR("Unknown feature \"%.*s\".\n", (int)(p-feats), feats); + ERROR("Unknown feature \"%.*s\".", (int)(p-feats), feats); if ( req ) { - ERROR("Kernel requires an unknown hypervisor feature.\n"); + ERROR("Kernel requires an unknown hypervisor feature."); return -EINVAL; } } @@ -579,6 +579,31 @@ static int setup_guest(int xc_handle, return -1; } #else /* x86 */ + +/* Check if the platform supports the guest kernel format */ +static int compat_check(int xc_handle, struct domain_setup_info *dsi) +{ + xen_capabilities_info_t xen_caps = ""; + + if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) { + ERROR("Cannot determine host capabilities."); + return 0; + } + + if (strstr(xen_caps, "xen-3.0-x86_32p")) { + if (!dsi->pae_kernel) { + ERROR("Non PAE-kernel on PAE host."); + return 0; + } + } else if (dsi->pae_kernel) { + ERROR("PAE-kernel on non-PAE host."); + return 0; + } + + return 1; +} + + static int setup_guest(int xc_handle, uint32_t dom, const char *image, unsigned long image_size, @@ -635,10 +660,13 @@ static int setup_guest(int xc_handle, if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 ) { - PERROR("Guest OS must load to a page boundary.\n"); + PERROR("Guest OS must load to a page boundary."); goto error_out; } + if (!compat_check(xc_handle, &dsi)) + goto error_out; + /* Parse and validate kernel features. */ p = strstr(dsi.xen_guest_string, "FEATURES="); if ( p != NULL ) @@ -647,7 +675,7 @@ static int setup_guest(int xc_handle, supported_features, required_features) ) { - ERROR("Failed to parse guest kernel features.\n"); + ERROR("Failed to parse guest kernel features."); goto error_out; } @@ -659,7 +687,7 @@ static int setup_guest(int xc_handle, { if ( (supported_features[i]&required_features[i]) != required_features[i] ) { - ERROR("Guest kernel does not support a required feature.\n"); + ERROR("Guest kernel does not support a required feature."); goto error_out; } } diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c index 94c5c8708c..ee4b2f9a71 100644 --- a/tools/libxc/xc_load_elf.c +++ b/tools/libxc/xc_load_elf.c @@ -69,6 +69,21 @@ static int parseelfimage(const char *image, return -EINVAL; } + if ( +#if defined(__i386__) + (ehdr->e_ident[EI_CLASS] != ELFCLASS32) || + (ehdr->e_machine != EM_386) || +#elif defined(__x86_64__) + (ehdr->e_ident[EI_CLASS] != ELFCLASS64) || + (ehdr->e_machine != EM_X86_64) || +#endif + (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) || + (ehdr->e_type != ET_EXEC) ) + { + ERROR("Kernel not a Xen-compatible Elf image."); + return -EINVAL; + } + if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize ) { ERROR("ELF program headers extend beyond end of image."); From 41dca18e001ad9657ec6cf284dbda003c3822375 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 16:15:44 +0100 Subject: [PATCH 119/151] Fix my slightly broken change to pirq_mask logic -- we must pass the last seen bit *plus 1* to find_next_bit(). Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/irq.c | 2 +- xen/arch/x86/irq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c index e7d0862d9c..350ec72435 100644 --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -1363,7 +1363,7 @@ int pirq_guest_unmask(struct domain *d) for ( pirq = find_first_bit(d->pirq_mask, NR_PIRQS); pirq < NR_PIRQS; - pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq) ) + pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq+1) ) { desc = &irq_desc[pirq]; spin_lock_irq(&desc->lock); diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 0b9d88037b..5a0749fb4e 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -176,7 +176,7 @@ int pirq_guest_unmask(struct domain *d) for ( pirq = find_first_bit(d->pirq_mask, NR_PIRQS); pirq < NR_PIRQS; - pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq) ) + pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq+1) ) { desc = &irq_desc[irq_to_vector(pirq)]; spin_lock_irq(&desc->lock); From b59014bf578e547db1903d3f432e41a8eb3e942f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Apr 2006 18:41:28 +0100 Subject: [PATCH 120/151] Robustify and add tracing to the IO-APIC update hypercall. If this patch, and any others that follow it, fix some of the prblems that various users have been seeing then they may be good candidates for backporting to 3.0.2 (assuming no regressions for other users). Signed-off-by: Keir Fraser --- xen/arch/x86/io_apic.c | 156 ++++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 39 deletions(-) diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index 18d8ed961c..ca180d3bf7 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -75,6 +75,7 @@ int disable_timer_pin_1 __initdata; static struct irq_pin_list { int apic, pin, next; } irq_2_pin[PIN_MAP_SIZE]; +static int irq_2_pin_free_entry = NR_IRQS; int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; @@ -85,22 +86,54 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; */ static void add_pin_to_irq(unsigned int irq, int apic, int pin) { - static int first_free_entry = NR_IRQS; struct irq_pin_list *entry = irq_2_pin + irq; - while (entry->next) + while (entry->next) { + BUG_ON((entry->apic == apic) && (entry->pin == pin)); entry = irq_2_pin + entry->next; + } + + BUG_ON((entry->apic == apic) && (entry->pin == pin)); if (entry->pin != -1) { - entry->next = first_free_entry; - entry = irq_2_pin + entry->next; - if (++first_free_entry >= PIN_MAP_SIZE) + if (irq_2_pin_free_entry >= PIN_MAP_SIZE) panic("io_apic.c: whoops"); + entry->next = irq_2_pin_free_entry; + entry = irq_2_pin + entry->next; + irq_2_pin_free_entry = entry->next; + entry->next = 0; } entry->apic = apic; entry->pin = pin; } +static void remove_pin_at_irq(unsigned int irq, int apic, int pin) +{ + struct irq_pin_list *entry, *prev; + int idx; + + for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) { + if ((entry->apic == apic) && (entry->pin == pin)) + break; + if (!entry->next) + BUG(); + } + + entry->pin = -1; + entry->apic = -1; + + idx = entry - irq_2_pin; + if (idx >= NR_IRQS) { + while (prev->next != idx) + prev = &irq_2_pin[prev->next]; + prev->next = entry->next; + entry->next = irq_2_pin_free_entry; + irq_2_pin_free_entry = idx; + } else { + entry->next = 0; + } +} + /* * Reroute an IRQ to a different pin. */ @@ -959,6 +992,10 @@ static void __init enable_IO_APIC(void) irq_2_pin[i].next = 0; } + /* Initialise dynamic irq_2_pin free list. */ + for (i = NR_IRQS; i < PIN_MAP_SIZE; i++) + irq_2_pin[i].next = i + 1; + /* * The number of IO-APIC IRQ registers (== #pins): */ @@ -1854,11 +1891,18 @@ int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval) return 0; } +#define WARN_BOGUS_WRITE(f, a...) \ + printk("%s: apic=%d,pin=%d,oirq=%d,nirq=%d\n" \ + "%s: oent=%08x:%08x,nent=%08x:%08x\n" \ + "%s: " f, __FUNCTION__, apic, pin, old_irq, new_irq, \ + __FUNCTION__, *(u32 *)&old_rte, *((u32 *)&old_rte+1), \ + *(u32 *)&new_rte, *((u32 *)&new_rte+1), \ + __FUNCTION__ , ##a ) + int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) { - int apic, pin, irq; - struct IO_APIC_route_entry rte = { 0 }; - struct irq_pin_list *entry; + int apic, pin, old_irq = -1, new_irq = -1; + struct IO_APIC_route_entry old_rte = { 0 }, new_rte = { 0 }; unsigned long flags; if ( (apic = ioapic_physbase_to_id(physbase)) < 0 ) @@ -1870,8 +1914,9 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) pin = (reg - 0x10) >> 1; - *(u32 *)&rte = val; - rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); + /* Write first half from guest; second half is target info. */ + *(u32 *)&new_rte = val; + new_rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); /* * What about weird destination types? @@ -1881,7 +1926,7 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) * ExtINT: Ignore? Linux only asserts this at start of day. * For now, print a message and return an error. We can fix up on demand. */ - if ( rte.delivery_mode > dest_LowestPrio ) + if ( new_rte.delivery_mode > dest_LowestPrio ) { printk("ERROR: Attempt to write weird IOAPIC destination mode!\n"); printk(" APIC=%d/%d, lo-reg=%x\n", apic, pin, val); @@ -1892,36 +1937,69 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) * The guest does not know physical APIC arrangement (flat vs. cluster). * Apply genapic conventions for this platform. */ - rte.delivery_mode = INT_DELIVERY_MODE; - rte.dest_mode = INT_DEST_MODE; - - if ( rte.vector >= FIRST_DEVICE_VECTOR ) - { - /* Is there a valid irq mapped to this vector? */ - irq = vector_irq[rte.vector]; - if ( !IO_APIC_IRQ(irq) ) - return 0; - - /* Set the correct irq-handling type. */ - irq_desc[IO_APIC_VECTOR(irq)].handler = rte.trigger ? - &ioapic_level_type: &ioapic_edge_type; - - /* Record the pin<->irq mapping. */ - for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] ) - { - if ( (entry->apic == apic) && (entry->pin == pin) ) - break; - if ( !entry->next ) - { - add_pin_to_irq(irq, apic, pin); - break; - } - } - } + new_rte.delivery_mode = INT_DELIVERY_MODE; + new_rte.dest_mode = INT_DEST_MODE; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0)); - io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1)); + + /* Read first (interesting) half of current routing entry. */ + *(u32 *)&old_rte = io_apic_read(apic, 0x10 + 2 * pin); + + /* No change to the first half of the routing entry? Bail quietly. */ + if ( *(u32 *)&old_rte == *(u32 *)&new_rte ) + { + spin_unlock_irqrestore(&ioapic_lock, flags); + return 0; + } + + if ( old_rte.vector >= FIRST_DEVICE_VECTOR ) + old_irq = vector_irq[old_rte.vector]; + if ( new_rte.vector >= FIRST_DEVICE_VECTOR ) + new_irq = vector_irq[new_rte.vector]; + + if ( (old_irq != new_irq) && (old_irq != -1) && IO_APIC_IRQ(old_irq) ) + { + if ( irq_desc[IO_APIC_VECTOR(old_irq)].action ) + { + WARN_BOGUS_WRITE("Attempt to remove IO-APIC pin of in-use IRQ!\n"); + spin_unlock_irqrestore(&ioapic_lock, flags); + return 0; + } + + remove_pin_at_irq(old_irq, apic, pin); + } + + if ( (new_irq != -1) && IO_APIC_IRQ(new_irq) ) + { + if ( irq_desc[IO_APIC_VECTOR(new_irq)].action ) + { + WARN_BOGUS_WRITE("Attempt to %s IO-APIC pin for in-use IRQ!\n", + (old_irq != new_irq) ? "add" : "modify"); + spin_unlock_irqrestore(&ioapic_lock, flags); + return 0; + } + + /* Set the correct irq-handling type. */ + irq_desc[IO_APIC_VECTOR(new_irq)].handler = new_rte.trigger ? + &ioapic_level_type: &ioapic_edge_type; + + if ( old_irq != new_irq ) + add_pin_to_irq(new_irq, apic, pin); + + /* Mask iff level triggered. */ + new_rte.mask = new_rte.trigger; + } + else if ( !new_rte.mask ) + { + /* This pin leads nowhere but the guest has not masked it. */ + WARN_BOGUS_WRITE("Installing bogus unmasked IO-APIC entry!\n"); + new_rte.mask = 1; + } + + + io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&new_rte) + 0)); + io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&new_rte) + 1)); + spin_unlock_irqrestore(&ioapic_lock, flags); return 0; From b766b4774afbaf01a0b2291e4d9add1df953dc11 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 8 Apr 2006 09:05:53 +0100 Subject: [PATCH 121/151] Added trace buffer virtual irq to implement non-polling trace record access. Signed-off-by: Rob Gardner --- xen/common/trace.c | 23 +++++++++++++++++++++++ xen/include/public/xen.h | 1 + xen/include/xen/softirq.h | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/xen/common/trace.c b/xen/common/trace.c index b0594aa0a8..dbd0f7e7a0 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -40,6 +42,11 @@ static struct t_buf *t_bufs[NR_CPUS]; static struct t_rec *t_recs[NR_CPUS]; static int nr_recs; +/* High water mark for trace buffers; */ +/* Send virtual interrupt when buffer level reaches this point */ +static int t_buf_highwater; + + /* a flag recording whether initialization has been done */ /* or more properly, if the tbuf subsystem is enabled right now */ int tb_init_done; @@ -50,6 +57,12 @@ static unsigned long tb_cpu_mask = (~0UL); /* which tracing events are enabled */ static u32 tb_event_mask = TRC_ALL; +static void trace_notify_guest(void) +{ + send_guest_global_virq(dom0, VIRQ_TBUF); +} + + /** * alloc_trace_bufs - performs initialization of the per-cpu trace buffers. * @@ -93,6 +106,9 @@ static int alloc_trace_bufs(void) t_recs[i] = (struct t_rec *)(buf + 1); } + t_buf_highwater = nr_recs >> 1; /* 50% high water */ + open_softirq(TRACE_SOFTIRQ, trace_notify_guest); + return 0; } @@ -272,6 +288,13 @@ void trace(u32 event, unsigned long d1, unsigned long d2, buf->prod++; local_irq_restore(flags); + + /* + * Notify trace buffer consumer that we've reached the high water mark. + * + */ + if ( (buf->prod - buf->cons) == t_buf_highwater ) + raise_softirq(TRACE_SOFTIRQ); } /* diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index e18fbf9669..8b2faffc6f 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -77,6 +77,7 @@ #define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */ #define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */ #define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */ +#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */ #define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */ #define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */ #define NR_VIRQS 8 diff --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h index 9293b3168e..f4d484f43b 100644 --- a/xen/include/xen/softirq.h +++ b/xen/include/xen/softirq.h @@ -9,7 +9,8 @@ #define NMI_SOFTIRQ 4 #define PAGE_SCRUB_SOFTIRQ 5 #define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ 6 -#define NR_SOFTIRQS 7 +#define TRACE_SOFTIRQ 7 +#define NR_SOFTIRQS 8 #ifndef __ASSEMBLY__ From ee29f146c33b704a5e256fe0a36b851d021c1225 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 8 Apr 2006 11:01:17 +0100 Subject: [PATCH 122/151] Fix remove_pin_at_irq(), introduced with changeset 9586:f84a333d8aa6e1a25e2b73b07610e95007267f6a. Signed-off-by: Keir Fraser --- xen/arch/x86/io_apic.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index ca180d3bf7..97aae7a77d 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -110,7 +110,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) static void remove_pin_at_irq(unsigned int irq, int apic, int pin) { struct irq_pin_list *entry, *prev; - int idx; for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) { if ((entry->apic == apic) && (entry->pin == pin)) @@ -119,18 +118,24 @@ static void remove_pin_at_irq(unsigned int irq, int apic, int pin) BUG(); } - entry->pin = -1; - entry->apic = -1; + entry->pin = entry->apic = -1; - idx = entry - irq_2_pin; - if (idx >= NR_IRQS) { - while (prev->next != idx) + if (entry != &irq_2_pin[irq]) { + /* Removed entry is not at head of list. */ + prev = &irq_2_pin[irq]; + while (&irq_2_pin[prev->next] != entry) prev = &irq_2_pin[prev->next]; prev->next = entry->next; entry->next = irq_2_pin_free_entry; - irq_2_pin_free_entry = idx; - } else { - entry->next = 0; + irq_2_pin_free_entry = entry - irq_2_pin; + } else if (entry->next != 0) { + /* Removed entry is at head of multi-item list. */ + prev = entry; + entry = &irq_2_pin[entry->next]; + *prev = *entry; + entry->pin = entry->apic = -1; + entry->next = irq_2_pin_free_entry; + irq_2_pin_free_entry = entry - irq_2_pin; } } From ea121d62ab22604f2adc008d6a8740fa3d186b11 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 8 Apr 2006 12:09:25 +0100 Subject: [PATCH 123/151] Clean up IO-APIC update tracing and demote to DPRINTK(). Signed-off-by: Keir Fraser --- xen/arch/x86/io_apic.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index 97aae7a77d..715b7d294d 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -1897,12 +1897,11 @@ int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval) } #define WARN_BOGUS_WRITE(f, a...) \ - printk("%s: apic=%d,pin=%d,oirq=%d,nirq=%d\n" \ - "%s: oent=%08x:%08x,nent=%08x:%08x\n" \ - "%s: " f, __FUNCTION__, apic, pin, old_irq, new_irq, \ - __FUNCTION__, *(u32 *)&old_rte, *((u32 *)&old_rte+1), \ - *(u32 *)&new_rte, *((u32 *)&new_rte+1), \ - __FUNCTION__ , ##a ) + DPRINTK("\n%s: apic=%d, pin=%d, old_irq=%d, new_irq=%d\n" \ + "%s: old_entry=%08x, new_entry=%08x\n" \ + "%s: " f, __FUNCTION__, apic, pin, old_irq, new_irq, \ + __FUNCTION__, *(u32 *)&old_rte, *(u32 *)&new_rte, \ + __FUNCTION__ , ##a ) int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val) { From 90027f708a554da0cf6f572883482b499714c697 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 8 Apr 2006 12:10:04 +0100 Subject: [PATCH 124/151] Build CONFIG_PNP_ACPI by default. Signed-off-by: Keir Fraser --- buildconfigs/linux-defconfig_xen0_x86_32 | 26 +++++++++++++++--------- buildconfigs/linux-defconfig_xen0_x86_64 | 8 +++++++- buildconfigs/linux-defconfig_xen_x86_32 | 4 ++-- buildconfigs/linux-defconfig_xen_x86_64 | 8 +++++++- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32 index c520622e1e..fe24dacce5 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_32 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc3-xen0 -# Thu Feb 16 22:52:42 2006 +# Linux kernel version: 2.6.16-xen0 +# Sat Apr 8 11:34:07 2006 # CONFIG_X86_32=y CONFIG_SEMAPHORE_SLEEPERS=y @@ -208,7 +208,6 @@ CONFIG_ACPI_BLACKLIST_YEAR=0 CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y CONFIG_ACPI_SYSTEM=y -# CONFIG_X86_PM_TIMER is not set # CONFIG_ACPI_CONTAINER is not set # @@ -392,7 +391,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # -# CONFIG_PNP is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG=y + +# +# Protocols +# +CONFIG_PNPACPI=y # # Block devices @@ -440,6 +445,7 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_IDEPNP is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set @@ -623,6 +629,7 @@ CONFIG_NETDEVICES=y # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=y +# CONFIG_NET_SB1000 is not set # # ARCnet devices @@ -1064,11 +1071,7 @@ CONFIG_USB_MON=y # CONFIG_INFINIBAND is not set # -# SN Devices -# - -# -# EDAC - error detection and reporting (RAS) +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # CONFIG_EDAC is not set @@ -1306,7 +1309,7 @@ CONFIG_CRYPTO_CRC32C=m # # CONFIG_CRYPTO_DEV_PADLOCK is not set CONFIG_XEN=y -CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_INTERFACE_VERSION=0x00030101 # # XEN @@ -1332,6 +1335,7 @@ CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_NO_IDLE_HZ=y # # Library routines @@ -1344,4 +1348,6 @@ CONFIG_ZLIB_INFLATE=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y CONFIG_KTIME_SCALAR=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index 04e992076d..25cc732d0b 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -327,7 +327,13 @@ CONFIG_STANDALONE=y # # Plug and Play support # -# CONFIG_PNP is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG=y + +# +# Protocols +# +CONFIG_PNPACPI=y # # Block devices diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index 59baf22bb2..27a102a80c 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -912,12 +912,12 @@ CONFIG_PARPORT_1284=y # Plug and Play support # CONFIG_PNP=y -# CONFIG_PNP_DEBUG is not set +CONFIG_PNP_DEBUG=y # # Protocols # -# CONFIG_PNPACPI is not set +CONFIG_PNPACPI=y # # Block devices diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index 8e97389570..ba7c616d8c 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -776,7 +776,13 @@ CONFIG_PARPORT_1284=y # # Plug and Play support # -# CONFIG_PNP is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG=y + +# +# Protocols +# +CONFIG_PNPACPI=y # # Block devices From 72c295faefc8c2c156a4d0d6fd513be1e5448160 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sun, 9 Apr 2006 18:23:16 +0100 Subject: [PATCH 125/151] Remove various compile-time options from SEDF scheduler and clean up formatting. Signed-off-by: Keir Fraser --- xen/common/sched_sedf.c | 729 +++++++++++++++------------------------- 1 file changed, 263 insertions(+), 466 deletions(-) diff --git a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c index 6e216195a8..71e6b9ba36 100644 --- a/xen/common/sched_sedf.c +++ b/xen/common/sched_sedf.c @@ -15,35 +15,24 @@ /*verbosity settings*/ #define SEDFLEVEL 0 -#define PRINT(_f, _a...) \ - if ((_f)<=SEDFLEVEL) printk(_a ); +#define PRINT(_f, _a...) \ + do { \ + if ( (_f) <= SEDFLEVEL ) \ + printk(_a ); \ + } while ( 0 ) #ifndef NDEBUG #define SEDF_STATS -#define CHECK(_p) if ( !(_p) ) \ - { printk("Check '%s' failed, line %d, file %s\n", #_p , __LINE__,\ - __FILE__);} +#define CHECK(_p) \ + do { \ + if ( !(_p) ) \ + printk("Check '%s' failed, line %d, file %s\n", \ + #_p , __LINE__, __FILE__); \ + } while ( 0 ) #else #define CHECK(_p) ((void)0) #endif -/*various ways of unblocking domains*/ -#define UNBLOCK_ISOCHRONOUS_EDF 1 -#define UNBLOCK_EDF 2 -#define UNBLOCK_ATROPOS 3 -#define UNBLOCK_SHORT_RESUME 4 -#define UNBLOCK_BURST 5 -#define UNBLOCK_EXTRA_SUPPORT 6 -#define UNBLOCK UNBLOCK_EXTRA_SUPPORT - -/*various ways of treating extra-time*/ -#define EXTRA_OFF 1 -#define EXTRA_ROUNDR 2 -#define EXTRA_SLICE_WEIGHT 3 -#define EXTRA_BLOCK_WEIGHT 4 - -#define EXTRA EXTRA_BLOCK_WEIGHT - #define EXTRA_NONE (0) #define EXTRA_AWARE (1) #define EXTRA_RUN_PEN (2) @@ -68,8 +57,8 @@ struct sedf_dom_info { struct domain *domain; }; -struct sedf_vcpu_info -{ + +struct sedf_vcpu_info { struct vcpu *vcpu; struct list_head list; struct list_head extralist[2]; @@ -85,10 +74,10 @@ struct sedf_vcpu_info s_time_t latency; /*status of domain*/ - int status; + int status; /*weights for "Scheduling for beginners/ lazy/ etc." ;)*/ - short weight; - short extraweight; + short weight; + short extraweight; /*Bookkeeping*/ s_time_t deadl_abs; s_time_t sched_start_abs; @@ -123,28 +112,29 @@ struct sedf_cpu_info { s_time_t current_slice_expires; }; -#define EDOM_INFO(d) ((struct sedf_vcpu_info *)((d)->sched_priv)) -#define CPU_INFO(cpu) ((struct sedf_cpu_info *)schedule_data[cpu].sched_priv) -#define LIST(d) (&EDOM_INFO(d)->list) -#define EXTRALIST(d,i) (&(EDOM_INFO(d)->extralist[i])) -#define RUNQ(cpu) (&CPU_INFO(cpu)->runnableq) +#define EDOM_INFO(d) ((struct sedf_vcpu_info *)((d)->sched_priv)) +#define CPU_INFO(cpu) ((struct sedf_cpu_info *)schedule_data[cpu].sched_priv) +#define LIST(d) (&EDOM_INFO(d)->list) +#define EXTRALIST(d,i) (&(EDOM_INFO(d)->extralist[i])) +#define RUNQ(cpu) (&CPU_INFO(cpu)->runnableq) #define WAITQ(cpu) (&CPU_INFO(cpu)->waitq) -#define EXTRAQ(cpu,i) (&(CPU_INFO(cpu)->extraq[i])) +#define EXTRAQ(cpu,i) (&(CPU_INFO(cpu)->extraq[i])) #define IDLETASK(cpu) ((struct vcpu *)schedule_data[cpu].idle) #define PERIOD_BEGIN(inf) ((inf)->deadl_abs - (inf)->period) -#define MIN(x,y) (((x)<(y))?(x):(y)) +#define MIN(x,y) (((x)<(y))?(x):(y)) #define DIV_UP(x,y) (((x) + (y) - 1) / y) -#define extra_runs(inf) ((inf->status) & 6) +#define extra_runs(inf) ((inf->status) & 6) #define extra_get_cur_q(inf) (((inf->status & 6) >> 1)-1) -#define sedf_runnable(edom) (!(EDOM_INFO(edom)->status & SEDF_ASLEEP)) +#define sedf_runnable(edom) (!(EDOM_INFO(edom)->status & SEDF_ASLEEP)) static void sedf_dump_cpu_state(int i); -static inline int extraq_on(struct vcpu *d, int i) { +static inline int extraq_on(struct vcpu *d, int i) +{ return ((EXTRALIST(d,i)->next != NULL) && (EXTRALIST(d,i)->next != EXTRALIST(d,i))); } @@ -165,8 +155,8 @@ static inline void extraq_del(struct vcpu *d, int i) { struct list_head *list = EXTRALIST(d,i); ASSERT(extraq_on(d,i)); - PRINT(3, "Removing domain %i.%i from L%i extraq\n", d->domain->domain_id, - d->vcpu_id, i); + PRINT(3, "Removing domain %i.%i from L%i extraq\n", + d->domain->domain_id, d->vcpu_id, i); list_del(list); list->next = NULL; ASSERT(!extraq_on(d, i)); @@ -178,94 +168,96 @@ static inline void extraq_del(struct vcpu *d, int i) each entry, in order to avoid overflow. The algorithm works by simply charging each domain that recieved extratime with an inverse of its weight. */ -static inline void extraq_add_sort_update(struct vcpu *d, int i, int sub) { +static inline void extraq_add_sort_update(struct vcpu *d, int i, int sub) +{ struct list_head *cur; struct sedf_vcpu_info *curinf; ASSERT(!extraq_on(d,i)); + PRINT(3, "Adding domain %i.%i (score= %i, short_pen= %"PRIi64")" " to L%i extraq\n", d->domain->domain_id, d->vcpu_id, EDOM_INFO(d)->score[i], EDOM_INFO(d)->short_block_lost_tot, i); - /*iterate through all elements to find our "hole" and on our way - update all the other scores*/ - list_for_each(cur,EXTRAQ(d->processor,i)){ + + /* + * Iterate through all elements to find our "hole" and on our way + * update all the other scores. + */ + list_for_each ( cur, EXTRAQ(d->processor, i) ) + { curinf = list_entry(cur,struct sedf_vcpu_info,extralist[i]); curinf->score[i] -= sub; - if (EDOM_INFO(d)->score[i] < curinf->score[i]) + if ( EDOM_INFO(d)->score[i] < curinf->score[i] ) break; - else - PRINT(4,"\tbehind domain %i.%i (score= %i)\n", - curinf->vcpu->domain->domain_id, - curinf->vcpu->vcpu_id, curinf->score[i]); + PRINT(4,"\tbehind domain %i.%i (score= %i)\n", + curinf->vcpu->domain->domain_id, + curinf->vcpu->vcpu_id, curinf->score[i]); } - /*cur now contains the element, before which we'll enqueue*/ + + /* cur now contains the element, before which we'll enqueue. */ PRINT(3, "\tlist_add to %p\n", cur->prev); list_add(EXTRALIST(d,i),cur->prev); - /*continue updating the extraq*/ - if ((cur != EXTRAQ(d->processor,i)) && sub) - for (cur = cur->next; cur != EXTRAQ(d->processor,i); - cur = cur-> next) { - curinf = list_entry(cur,struct sedf_vcpu_info, - extralist[i]); + /* Continue updating the extraq. */ + if ( (cur != EXTRAQ(d->processor,i)) && sub ) + { + for ( cur = cur->next; cur != EXTRAQ(d->processor,i); cur = cur->next ) + { + curinf = list_entry(cur,struct sedf_vcpu_info, extralist[i]); curinf->score[i] -= sub; PRINT(4, "\tupdating domain %i.%i (score= %u)\n", curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id, curinf->score[i]); } + } + ASSERT(extraq_on(d,i)); } -static inline void extraq_check(struct vcpu *d) { - if (extraq_on(d, EXTRA_UTIL_Q)) { - PRINT(2,"Dom %i.%i is on L1 extraQ\n",d->domain->domain_id, d->vcpu_id); - if (!(EDOM_INFO(d)->status & EXTRA_AWARE) && - !extra_runs(EDOM_INFO(d))) { +static inline void extraq_check(struct vcpu *d) +{ + if ( extraq_on(d, EXTRA_UTIL_Q) ) + { + PRINT(2,"Dom %i.%i is on L1 extraQ\n", + d->domain->domain_id, d->vcpu_id); + + if ( !(EDOM_INFO(d)->status & EXTRA_AWARE) && + !extra_runs(EDOM_INFO(d)) ) + { extraq_del(d, EXTRA_UTIL_Q); PRINT(2,"Removed dom %i.%i from L1 extraQ\n", d->domain->domain_id, d->vcpu_id); } - } else { - PRINT(2,"Dom %i.%i is NOT on L1 extraQ\n",d->domain->domain_id, + } + else + { + PRINT(2, "Dom %i.%i is NOT on L1 extraQ\n", + d->domain->domain_id, d->vcpu_id); - if ((EDOM_INFO(d)->status & EXTRA_AWARE) && sedf_runnable(d)) + + if ( (EDOM_INFO(d)->status & EXTRA_AWARE) && sedf_runnable(d) ) { -#if (EXTRA == EXTRA_ROUNDR) - extraq_add_tail(d, EXTRA_UTIL_Q); -#elif (EXTRA == EXTRA_SLICE_WEIGHT || \ - EXTRA == EXTRA_BLOCK_WEIGHT) extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); -#elif - ; -#endif - PRINT(2,"Added dom %i.%i to L1 extraQ\n",d->domain->domain_id, - d->vcpu_id); + PRINT(2,"Added dom %i.%i to L1 extraQ\n", + d->domain->domain_id, d->vcpu_id); } } } -static inline void extraq_check_add_unblocked(struct vcpu *d, - int priority) { +static inline void extraq_check_add_unblocked(struct vcpu *d, int priority) +{ struct sedf_vcpu_info *inf = EDOM_INFO(d); - if (inf->status & EXTRA_AWARE) -#if (EXTRA == EXTRA_ROUNDR) - if (priority) - extraq_add_head(d,EXTRA_UTIL_Q); - else - extraq_add_tail(d,EXTRA_UTIL_Q); -#elif (EXTRA == EXTRA_SLICE_WEIGHT \ - || EXTRA == EXTRA_BLOCK_WEIGHT) - /*put in on the weighted extraq, - without updating any scores*/ - extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); -#else - ; -#endif + + if ( inf->status & EXTRA_AWARE ) + /* Put on the weighted extraq without updating any scores. */ + extraq_add_sort_update(d, EXTRA_UTIL_Q, 0); } -static inline int __task_on_queue(struct vcpu *d) { +static inline int __task_on_queue(struct vcpu *d) +{ return (((LIST(d))->next != NULL) && (LIST(d)->next != LIST(d))); } + static inline void __del_from_queue(struct vcpu *d) { struct list_head *list = LIST(d); @@ -279,42 +271,47 @@ static inline void __del_from_queue(struct vcpu *d) typedef int(*list_comparer)(struct list_head* el1, struct list_head* el2); -static inline void list_insert_sort(struct list_head *list, - struct list_head *element, list_comparer comp) { +static inline void list_insert_sort( + struct list_head *list, struct list_head *element, list_comparer comp) +{ struct list_head *cur; - /*iterate through all elements to find our "hole"*/ - list_for_each(cur,list){ - if (comp(element, cur) < 0) + + /* Iterate through all elements to find our "hole". */ + list_for_each( cur, list ) + if ( comp(element, cur) < 0 ) break; - } - /*cur now contains the element, before which we'll enqueue*/ + + /* cur now contains the element, before which we'll enqueue. */ PRINT(3,"\tlist_add to %p\n",cur->prev); list_add(element, cur->prev); -} +} + #define DOMAIN_COMPARER(name, field, comp1, comp2) \ int name##_comp(struct list_head* el1, struct list_head* el2) \ { \ - struct sedf_vcpu_info *d1, *d2; \ - d1 = list_entry(el1,struct sedf_vcpu_info, field); \ - d2 = list_entry(el2,struct sedf_vcpu_info, field); \ - if ((comp1) == (comp2)) \ - return 0; \ - if ((comp1) < (comp2)) \ - return -1; \ - else \ - return 1; \ + struct sedf_vcpu_info *d1, *d2; \ + d1 = list_entry(el1,struct sedf_vcpu_info, field); \ + d2 = list_entry(el2,struct sedf_vcpu_info, field); \ + if ( (comp1) == (comp2) ) \ + return 0; \ + if ( (comp1) < (comp2) ) \ + return -1; \ + else \ + return 1; \ } + /* adds a domain to the queue of processes which wait for the beginning of the next period; this list is therefore sortet by this time, which is simply absol. deadline - period */ -DOMAIN_COMPARER(waitq, list, PERIOD_BEGIN(d1), PERIOD_BEGIN(d2)) - static inline void __add_to_waitqueue_sort(struct vcpu *d) { - ASSERT(!__task_on_queue(d)); +DOMAIN_COMPARER(waitq, list, PERIOD_BEGIN(d1), PERIOD_BEGIN(d2)); +static inline void __add_to_waitqueue_sort(struct vcpu *v) +{ + ASSERT(!__task_on_queue(v)); PRINT(3,"Adding domain %i.%i (bop= %"PRIu64") to waitq\n", - d->domain->domain_id, d->vcpu_id, PERIOD_BEGIN(EDOM_INFO(d))); - list_insert_sort(WAITQ(d->processor), LIST(d), waitq_comp); - ASSERT(__task_on_queue(d)); + v->domain->domain_id, v->vcpu_id, PERIOD_BEGIN(EDOM_INFO(v))); + list_insert_sort(WAITQ(v->processor), LIST(v), waitq_comp); + ASSERT(__task_on_queue(v)); } /* adds a domain to the queue of processes which have started their current @@ -322,60 +319,62 @@ DOMAIN_COMPARER(waitq, list, PERIOD_BEGIN(d1), PERIOD_BEGIN(d2)) on this list is running on the processor, if the list is empty the idle task will run. As we are implementing EDF, this list is sorted by deadlines. */ -DOMAIN_COMPARER(runq, list, d1->deadl_abs, d2->deadl_abs) - static inline void __add_to_runqueue_sort(struct vcpu *d) { +DOMAIN_COMPARER(runq, list, d1->deadl_abs, d2->deadl_abs); +static inline void __add_to_runqueue_sort(struct vcpu *v) +{ PRINT(3,"Adding domain %i.%i (deadl= %"PRIu64") to runq\n", - d->domain->domain_id, d->vcpu_id, EDOM_INFO(d)->deadl_abs); - list_insert_sort(RUNQ(d->processor), LIST(d), runq_comp); + v->domain->domain_id, v->vcpu_id, EDOM_INFO(v)->deadl_abs); + list_insert_sort(RUNQ(v->processor), LIST(v), runq_comp); } /* Allocates memory for per domain private scheduling data*/ -static int sedf_alloc_task(struct vcpu *d) +static int sedf_alloc_task(struct vcpu *v) { PRINT(2, "sedf_alloc_task was called, domain-id %i.%i\n", - d->domain->domain_id, d->vcpu_id); + v->domain->domain_id, v->vcpu_id); - if ( d->domain->sched_priv == NULL ) + if ( v->domain->sched_priv == NULL ) { - d->domain->sched_priv = xmalloc(struct sedf_dom_info); - if ( d->domain->sched_priv == NULL ) + v->domain->sched_priv = xmalloc(struct sedf_dom_info); + if ( v->domain->sched_priv == NULL ) return -1; - memset(d->domain->sched_priv, 0, sizeof(struct sedf_dom_info)); + memset(v->domain->sched_priv, 0, sizeof(struct sedf_dom_info)); } - if ( (d->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL ) + if ( (v->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL ) return -1; - memset(d->sched_priv, 0, sizeof(struct sedf_vcpu_info)); + memset(v->sched_priv, 0, sizeof(struct sedf_vcpu_info)); return 0; } /* Setup the sedf_dom_info */ -static void sedf_add_task(struct vcpu *d) +static void sedf_add_task(struct vcpu *v) { - struct sedf_vcpu_info *inf = EDOM_INFO(d); - inf->vcpu = d; + struct sedf_vcpu_info *inf = EDOM_INFO(v); + + inf->vcpu = v; - PRINT(2,"sedf_add_task was called, domain-id %i.%i\n",d->domain->domain_id, - d->vcpu_id); + PRINT(2,"sedf_add_task was called, domain-id %i.%i\n", + v->domain->domain_id, v->vcpu_id); /* Allocate per-CPU context if this is the first domain to be added. */ - if ( unlikely(schedule_data[d->processor].sched_priv == NULL) ) + if ( unlikely(schedule_data[v->processor].sched_priv == NULL) ) { - schedule_data[d->processor].sched_priv = + schedule_data[v->processor].sched_priv = xmalloc(struct sedf_cpu_info); - BUG_ON(schedule_data[d->processor].sched_priv == NULL); - memset(CPU_INFO(d->processor), 0, sizeof(*CPU_INFO(d->processor))); - INIT_LIST_HEAD(WAITQ(d->processor)); - INIT_LIST_HEAD(RUNQ(d->processor)); - INIT_LIST_HEAD(EXTRAQ(d->processor,EXTRA_PEN_Q)); - INIT_LIST_HEAD(EXTRAQ(d->processor,EXTRA_UTIL_Q)); + BUG_ON(schedule_data[v->processor].sched_priv == NULL); + memset(CPU_INFO(v->processor), 0, sizeof(*CPU_INFO(v->processor))); + INIT_LIST_HEAD(WAITQ(v->processor)); + INIT_LIST_HEAD(RUNQ(v->processor)); + INIT_LIST_HEAD(EXTRAQ(v->processor,EXTRA_PEN_Q)); + INIT_LIST_HEAD(EXTRAQ(v->processor,EXTRA_UTIL_Q)); } - if ( d->domain->domain_id == 0 ) + if ( v->domain->domain_id == 0 ) { /*set dom0 to something useful to boot the machine*/ inf->period = MILLISECS(20); @@ -400,14 +399,14 @@ static void sedf_add_task(struct vcpu *d) INIT_LIST_HEAD(&(inf->extralist[EXTRA_PEN_Q])); INIT_LIST_HEAD(&(inf->extralist[EXTRA_UTIL_Q])); - if ( !is_idle_vcpu(d) ) + if ( !is_idle_vcpu(v) ) { - extraq_check(d); + extraq_check(v); } else { - EDOM_INFO(d)->deadl_abs = 0; - EDOM_INFO(d)->status &= ~SEDF_ASLEEP; + EDOM_INFO(v)->deadl_abs = 0; + EDOM_INFO(v)->status &= ~SEDF_ASLEEP; } } @@ -418,17 +417,11 @@ static void sedf_free_task(struct domain *d) PRINT(2,"sedf_free_task was called, domain-id %i\n",d->domain_id); - ASSERT(d->sched_priv != NULL); xfree(d->sched_priv); for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - { if ( d->vcpu[i] ) - { - ASSERT(d->vcpu[i]->sched_priv != NULL); xfree(d->vcpu[i]->sched_priv); - } - } } /* @@ -438,64 +431,60 @@ static void sedf_free_task(struct domain *d) static void desched_edf_dom(s_time_t now, struct vcpu* d) { struct sedf_vcpu_info* inf = EDOM_INFO(d); - /*current domain is running in real time mode*/ - + + /* Current domain is running in real time mode. */ ASSERT(__task_on_queue(d)); - /*update the domains cputime*/ + + /* Update the domain's cputime. */ inf->cputime += now - inf->sched_start_abs; - /*scheduling decisions, which don't remove the running domain - from the runq*/ + /* + * Scheduling decisions which don't remove the running domain from the + * runq. + */ if ( (inf->cputime < inf->slice) && sedf_runnable(d) ) return; __del_from_queue(d); - /*manage bookkeeping (i.e. calculate next deadline, - memorize overun-time of slice) of finished domains*/ + /* + * Manage bookkeeping (i.e. calculate next deadline, memorise + * overrun-time of slice) of finished domains. + */ if ( inf->cputime >= inf->slice ) { inf->cputime -= inf->slice; if ( inf->period < inf->period_orig ) { - /*this domain runs in latency scaling or burst mode*/ -#if (UNBLOCK == UNBLOCK_BURST) - /*if we are runnig in burst scaling wait for two periods - before scaling periods up again*/ - if ( (now - inf->unblock_abs) >= (2 * inf->period) ) -#endif + /* This domain runs in latency scaling or burst mode. */ + inf->period *= 2; + inf->slice *= 2; + if ( (inf->period > inf->period_orig) || + (inf->slice > inf->slice_orig) ) { - inf->period *= 2; inf->slice *= 2; - if ( (inf->period > inf->period_orig) || - (inf->slice > inf->slice_orig) ) - { - /*reset slice & period*/ - inf->period = inf->period_orig; - inf->slice = inf->slice_orig; - } + /* Reset slice and period. */ + inf->period = inf->period_orig; + inf->slice = inf->slice_orig; } } - /*set next deadline*/ + + /* Set next deadline. */ inf->deadl_abs += inf->period; } - /*add a runnable domain to the waitqueue*/ + /* Add a runnable domain to the waitqueue. */ if ( sedf_runnable(d) ) { __add_to_waitqueue_sort(d); } else { - /*we have a blocked realtime task -> remove it from exqs too*/ -#if (EXTRA > EXTRA_OFF) -#if (EXTRA == EXTRA_BLOCK_WEIGHT) + /* We have a blocked realtime task -> remove it from exqs too. */ if ( extraq_on(d, EXTRA_PEN_Q) ) extraq_del(d, EXTRA_PEN_Q); -#endif if ( extraq_on(d, EXTRA_UTIL_Q) ) extraq_del(d, EXTRA_UTIL_Q); -#endif } ASSERT(EQ(sedf_runnable(d), __task_on_queue(d))); @@ -513,58 +502,57 @@ static void update_queues( PRINT(3,"Updating waitq..\n"); - /*check for the first elements of the waitqueue, whether their - next period has already started*/ - list_for_each_safe(cur, tmp, waitq) { + /* + * Check for the first elements of the waitqueue, whether their + * next period has already started. + */ + list_for_each_safe ( cur, tmp, waitq ) + { curinf = list_entry(cur, struct sedf_vcpu_info, list); PRINT(4,"\tLooking @ dom %i.%i\n", curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id); - if ( PERIOD_BEGIN(curinf) <= now ) - { - __del_from_queue(curinf->vcpu); - __add_to_runqueue_sort(curinf->vcpu); - } - else + if ( PERIOD_BEGIN(curinf) > now ) break; + __del_from_queue(curinf->vcpu); + __add_to_runqueue_sort(curinf->vcpu); } PRINT(3,"Updating runq..\n"); - /*process the runq, find domains that are on - the runqueue which shouldn't be there*/ - list_for_each_safe(cur, tmp, runq) { + /* Process the runq, find domains that are on the runq that shouldn't. */ + list_for_each_safe ( cur, tmp, runq ) + { curinf = list_entry(cur,struct sedf_vcpu_info,list); PRINT(4,"\tLooking @ dom %i.%i\n", curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id); if ( unlikely(curinf->slice == 0) ) { - /*ignore domains with empty slice*/ + /* Ignore domains with empty slice. */ PRINT(4,"\tUpdating zero-slice domain %i.%i\n", curinf->vcpu->domain->domain_id, curinf->vcpu->vcpu_id); __del_from_queue(curinf->vcpu); - /*move them to their next period*/ + /* Move them to their next period. */ curinf->deadl_abs += curinf->period; - /*ensure that the start of the next period is in the future*/ + + /* Ensure that the start of the next period is in the future. */ if ( unlikely(PERIOD_BEGIN(curinf) < now) ) - { curinf->deadl_abs += (DIV_UP(now - PERIOD_BEGIN(curinf), - curinf->period)) * curinf->period; - } - /*and put them back into the queue*/ - __add_to_waitqueue_sort(curinf->vcpu); - continue; - } + curinf->period)) * curinf->period; - if ( unlikely((curinf->deadl_abs < now) || - (curinf->cputime > curinf->slice)) ) + /* Put them back into the queue. */ + __add_to_waitqueue_sort(curinf->vcpu); + } + else if ( unlikely((curinf->deadl_abs < now) || + (curinf->cputime > curinf->slice)) ) { - /*we missed the deadline or the slice was - already finished... might hapen because - of dom_adj.*/ + /* + * We missed the deadline or the slice was already finished. + * Might hapen because of dom_adj. + */ PRINT(4,"\tDomain %i.%i exceeded it's deadline/" "slice (%"PRIu64" / %"PRIu64") now: %"PRIu64 " cputime: %"PRIu64"\n", @@ -573,20 +561,23 @@ static void update_queues( curinf->deadl_abs, curinf->slice, now, curinf->cputime); __del_from_queue(curinf->vcpu); - /*common case: we miss one period!*/ + + /* Common case: we miss one period. */ curinf->deadl_abs += curinf->period; - /*if we are still behind: modulo arithmetic, - force deadline to be in future and - aligned to period borders!*/ - if (unlikely(curinf->deadl_abs < now)) + /* + * If we are still behind: modulo arithmetic, force deadline + * to be in future and aligned to period borders. + */ + if ( unlikely(curinf->deadl_abs < now) ) curinf->deadl_abs += DIV_UP(now - curinf->deadl_abs, curinf->period) * curinf->period; ASSERT(curinf->deadl_abs >= now); - /*give a fresh slice*/ + + /* Give a fresh slice. */ curinf->cputime = 0; - if (PERIOD_BEGIN(curinf) > now) + if ( PERIOD_BEGIN(curinf) > now ) __add_to_waitqueue_sort(curinf->vcpu); else __add_to_runqueue_sort(curinf->vcpu); @@ -594,43 +585,36 @@ static void update_queues( else break; } + PRINT(3,"done updating the queues\n"); } -#if (EXTRA > EXTRA_OFF) /* removes a domain from the head of the according extraQ and requeues it at a specified position: round-robin extratime: end of extraQ weighted ext.: insert in sorted list by score if the domain is blocked / has regained its short-block-loss time it is not put on any queue */ -static void desched_extra_dom(s_time_t now, struct vcpu* d) +static void desched_extra_dom(s_time_t now, struct vcpu *d) { struct sedf_vcpu_info *inf = EDOM_INFO(d); int i = extra_get_cur_q(inf); - -#if (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) - unsigned long oldscore; -#endif + unsigned long oldscore; + ASSERT(extraq_on(d, i)); - /*unset all running flags*/ + + /* Unset all running flags. */ inf->status &= ~(EXTRA_RUN_PEN | EXTRA_RUN_UTIL); - /*fresh slice for the next run*/ + /* Fresh slice for the next run. */ inf->cputime = 0; - /*accumulate total extratime*/ + /* Accumulate total extratime. */ inf->extra_time_tot += now - inf->sched_start_abs; - /*remove extradomain from head of the queue*/ + /* Remove extradomain from head of the queue. */ extraq_del(d, i); -#if (EXTRA == EXTRA_ROUNDR) - if ( sedf_runnable(d) && (inf->status & EXTRA_AWARE) ) - /*add to the tail if it is runnable => round-robin*/ - extraq_add_tail(d, EXTRA_UTIL_Q); -#elif (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) - /*update the score*/ + /* Update the score. */ oldscore = inf->score[i]; -#if (EXTRA == EXTRA_BLOCK_WEIGHT) if ( i == EXTRA_PEN_Q ) { /*domain was running in L0 extraq*/ @@ -640,7 +624,8 @@ static void desched_extra_dom(s_time_t now, struct vcpu* d) PRINT(3,"Domain %i.%i: Short_block_loss: %"PRIi64"\n", inf->vcpu->domain->domain_id, inf->vcpu->vcpu_id, inf->short_block_lost_tot); - if (inf->short_block_lost_tot <= 0) { + if ( inf->short_block_lost_tot <= 0 ) + { PRINT(4,"Domain %i.%i compensated short block loss!\n", inf->vcpu->domain->domain_id, inf->vcpu->vcpu_id); /*we have (over-)compensated our block penalty*/ @@ -649,6 +634,7 @@ static void desched_extra_dom(s_time_t now, struct vcpu* d) inf->status &= ~EXTRA_WANT_PEN_Q; goto check_extra_queues; } + /*we have to go again for another try in the block-extraq, the score is not used incremantally here, as this is already done by recalculating the block_lost*/ @@ -657,7 +643,6 @@ static void desched_extra_dom(s_time_t now, struct vcpu* d) oldscore = 0; } else -#endif { /*domain was running in L1 extraq => score is inverse of utilization and is used somewhat incremental!*/ @@ -684,7 +669,6 @@ static void desched_extra_dom(s_time_t now, struct vcpu* d) { /*remove this blocked domain from the waitq!*/ __del_from_queue(d); -#if (EXTRA == EXTRA_BLOCK_WEIGHT) /*make sure that we remove a blocked domain from the other extraq too*/ if ( i == EXTRA_PEN_Q ) @@ -697,14 +681,12 @@ static void desched_extra_dom(s_time_t now, struct vcpu* d) if ( extraq_on(d, EXTRA_PEN_Q) ) extraq_del(d, EXTRA_PEN_Q); } -#endif } -#endif + ASSERT(EQ(sedf_runnable(d), __task_on_queue(d))); ASSERT(IMPLY(extraq_on(d, EXTRA_UTIL_Q) || extraq_on(d, EXTRA_PEN_Q), sedf_runnable(d))); } -#endif static struct task_slice sedf_do_extra_schedule( @@ -718,7 +700,6 @@ static struct task_slice sedf_do_extra_schedule( if ( end_xt - now < EXTRA_QUANTUM ) goto return_idle; -#if (EXTRA == EXTRA_BLOCK_WEIGHT) if ( !list_empty(extraq[EXTRA_PEN_Q]) ) { /*we still have elements on the level 0 extraq @@ -733,7 +714,6 @@ static struct task_slice sedf_do_extra_schedule( #endif } else -#endif { if ( !list_empty(extraq[EXTRA_UTIL_Q]) ) { @@ -772,11 +752,9 @@ static struct task_slice sedf_do_schedule(s_time_t now) int cpu = smp_processor_id(); struct list_head *runq = RUNQ(cpu); struct list_head *waitq = WAITQ(cpu); -#if (EXTRA > EXTRA_OFF) struct sedf_vcpu_info *inf = EDOM_INFO(current); struct list_head *extraq[] = { EXTRAQ(cpu, EXTRA_PEN_Q), EXTRAQ(cpu, EXTRA_UTIL_Q)}; -#endif struct sedf_vcpu_info *runinf, *waitinf; struct task_slice ret; @@ -793,14 +771,12 @@ static struct task_slice sedf_do_schedule(s_time_t now) if ( inf->status & SEDF_ASLEEP ) inf->block_abs = now; -#if (EXTRA > EXTRA_OFF) if ( unlikely(extra_runs(inf)) ) { /*special treatment of domains running in extra time*/ desched_extra_dom(now, current); } else -#endif { desched_edf_dom(now, current); } @@ -837,13 +813,8 @@ static struct task_slice sedf_do_schedule(s_time_t now) waitinf = list_entry(waitq->next,struct sedf_vcpu_info, list); /*we could not find any suitable domain => look for domains that are aware of extratime*/ -#if (EXTRA > EXTRA_OFF) ret = sedf_do_extra_schedule(now, PERIOD_BEGIN(waitinf), extraq, cpu); -#else - ret.task = IDLETASK(cpu); - ret.time = PERIOD_BEGIN(waitinf) - now; -#endif CHECK(ret.time > 0); } else @@ -891,14 +862,10 @@ static void sedf_sleep(struct vcpu *d) { if ( __task_on_queue(d) ) __del_from_queue(d); -#if (EXTRA > EXTRA_OFF) if ( extraq_on(d, EXTRA_UTIL_Q) ) extraq_del(d, EXTRA_UTIL_Q); -#endif -#if (EXTRA == EXTRA_BLOCK_WEIGHT) if ( extraq_on(d, EXTRA_PEN_Q) ) extraq_del(d, EXTRA_PEN_Q); -#endif } } @@ -939,7 +906,7 @@ static void sedf_sleep(struct vcpu *d) * -addition: experiments have shown that this may have a HUGE impact on * performance of other domains, becaus it can lead to excessive context * switches - + * * Part2: Long Unblocking * Part 2a * -it is obvious that such accounting of block time, applied when @@ -974,32 +941,6 @@ static void sedf_sleep(struct vcpu *d) * -either behaviour can lead to missed deadlines in other domains as * opposed to approaches 1,2a,2b */ -#if (UNBLOCK <= UNBLOCK_SHORT_RESUME) -static void unblock_short_vcons(struct sedf_vcpu_info* inf, s_time_t now) -{ - inf->deadl_abs += inf->period; - inf->cputime = 0; -} -#endif - -#if (UNBLOCK == UNBLOCK_SHORT_RESUME) -static void unblock_short_cons(struct sedf_vcpu_info* inf, s_time_t now) -{ - /*treat blocked time as consumed by the domain*/ - inf->cputime += now - inf->block_abs; - if ( (inf->cputime + EXTRA_QUANTUM) > inf->slice ) - { - /*we don't have a reasonable amount of time in - our slice left :( => start in next period!*/ - unblock_short_vcons(inf, now); - } -#ifdef SEDF_STATS - else - inf->short_cont++; -#endif -} -#endif - static void unblock_short_extra_support( struct sedf_vcpu_info* inf, s_time_t now) { @@ -1051,33 +992,6 @@ static void unblock_short_extra_support( } -#if (UNBLOCK == UNBLOCK_ISOCHRONOUS_EDF) -static void unblock_long_vcons(struct sedf_vcpu_info* inf, s_time_t now) -{ - /* align to next future period */ - inf->deadl_abs += (DIV_UP(now - inf->deadl_abs, inf->period) +1) - * inf->period; - inf->cputime = 0; -} -#endif - - -#if 0 -static void unblock_long_cons_a (struct sedf_vcpu_info* inf, s_time_t now) -{ - /*treat the time the domain was blocked in the - CURRENT period as consumed by the domain*/ - inf->cputime = (now - inf->deadl_abs) % inf->period; - if ( (inf->cputime + EXTRA_QUANTUM) > inf->slice ) - { - /*we don't have a reasonable amount of time in our slice - left :( => start in next period!*/ - unblock_long_vcons(inf, now); - } -} -#endif - - static void unblock_long_cons_b(struct sedf_vcpu_info* inf,s_time_t now) { /*Conservative 2b*/ @@ -1087,110 +1001,6 @@ static void unblock_long_cons_b(struct sedf_vcpu_info* inf,s_time_t now) } -#if (UNBLOCK == UNBLOCK_ATROPOS) -static void unblock_long_cons_c(struct sedf_vcpu_info* inf,s_time_t now) -{ - if ( likely(inf->latency) ) - { - /*scale the slice and period accordingly to the latency hint*/ - /*reduce period temporarily to the latency hint*/ - inf->period = inf->latency; - /*this results in max. 4s slice/period length*/ - ASSERT((inf->period < ULONG_MAX) - && (inf->slice_orig < ULONG_MAX)); - /*scale slice accordingly, so that utilisation stays the same*/ - inf->slice = (inf->period * inf->slice_orig) - / inf->period_orig; - inf->deadl_abs = now + inf->period; - inf->cputime = 0; - } - else - { - /*we don't have a latency hint.. use some other technique*/ - unblock_long_cons_b(inf, now); - } -} -#endif - - -#if (UNBLOCK == UNBLOCK_BURST) -/*a new idea of dealing with short blocks: burst period scaling*/ -static void unblock_short_burst(struct sedf_vcpu_info* inf, s_time_t now) -{ - /*treat blocked time as consumed by the domain*/ - inf->cputime += now - inf->block_abs; - - if ( (inf->cputime + EXTRA_QUANTUM) <= inf->slice ) - { - /*if we can still use some time in the current slice - then use it!*/ -#ifdef SEDF_STATS - /*we let the domain run in the current period*/ - inf->short_cont++; -#endif - } - else - { - /*we don't have a reasonable amount of time in - our slice left => switch to burst mode*/ - if ( likely(inf->unblock_abs) ) - { - /*set the period-length to the current blocking - interval, possible enhancements: average over last - blocking intervals, user-specified minimum,...*/ - inf->period = now - inf->unblock_abs; - /*check for overflow on multiplication*/ - ASSERT((inf->period < ULONG_MAX) - && (inf->slice_orig < ULONG_MAX)); - /*scale slice accordingly, so that utilisation - stays the same*/ - inf->slice = (inf->period * inf->slice_orig) - / inf->period_orig; - /*set new (shorter) deadline*/ - inf->deadl_abs += inf->period; - } - else - { - /*in case we haven't unblocked before - start in next period!*/ - inf->cputime=0; - inf->deadl_abs += inf->period; - } - } - - inf->unblock_abs = now; -} - - -static void unblock_long_burst(struct sedf_vcpu_info* inf, s_time_t now) -{ - if ( unlikely(inf->latency && (inf->period > inf->latency)) ) - { - /*scale the slice and period accordingly to the latency hint*/ - inf->period = inf->latency; - /*check for overflows on multiplication*/ - ASSERT((inf->period < ULONG_MAX) - && (inf->slice_orig < ULONG_MAX)); - /*scale slice accordingly, so that utilisation stays the same*/ - inf->slice = (inf->period * inf->slice_orig) - / inf->period_orig; - inf->deadl_abs = now + inf->period; - inf->cputime = 0; - } - else - { - /*we don't have a latency hint.. or we are currently in - "burst mode": use some other technique - NB: this should be in fact the normal way of operation, - when we are in sync with the device!*/ - unblock_long_cons_b(inf, now); - } - - inf->unblock_abs = now; -} -#endif /* UNBLOCK == UNBLOCK_BURST */ - - #define DOMAIN_EDF 1 #define DOMAIN_EXTRA_PEN 2 #define DOMAIN_EXTRA_UTIL 3 @@ -1225,32 +1035,31 @@ static inline int should_switch(struct vcpu *cur, cur_inf = EDOM_INFO(cur); other_inf = EDOM_INFO(other); - /*check whether we need to make an earlier sched-decision*/ - if (PERIOD_BEGIN(other_inf) < - CPU_INFO(other->processor)->current_slice_expires) + /* Check whether we need to make an earlier scheduling decision. */ + if ( PERIOD_BEGIN(other_inf) < + CPU_INFO(other->processor)->current_slice_expires ) return 1; - /*no timing-based switches need to be taken into account here*/ - switch (get_run_type(cur)) { + + /* No timing-based switches need to be taken into account here. */ + switch ( get_run_type(cur) ) + { case DOMAIN_EDF: - /* do not interrupt a running EDF domain */ + /* Do not interrupt a running EDF domain. */ return 0; case DOMAIN_EXTRA_PEN: - /*check whether we also want - the L0 ex-q with lower score*/ - if ((other_inf->status & EXTRA_WANT_PEN_Q) - && (other_inf->score[EXTRA_PEN_Q] < - cur_inf->score[EXTRA_PEN_Q])) - return 1; - else return 0; + /* Check whether we also want the L0 ex-q with lower score. */ + return ((other_inf->status & EXTRA_WANT_PEN_Q) && + (other_inf->score[EXTRA_PEN_Q] < + cur_inf->score[EXTRA_PEN_Q])); case DOMAIN_EXTRA_UTIL: - /*check whether we want the L0 extraq, don't - switch if both domains want L1 extraq */ - if (other_inf->status & EXTRA_WANT_PEN_Q) - return 1; - else return 0; + /* Check whether we want the L0 extraq. Don't + * switch if both domains want L1 extraq. + */ + return !!(other_inf->status & EXTRA_WANT_PEN_Q); case DOMAIN_IDLE: return 1; } + return 1; } @@ -1295,7 +1104,6 @@ void sedf_wake(struct vcpu *d) { PRINT(4,"extratime unblock\n"); /* unblocking in extra-time! */ -#if (EXTRA == EXTRA_BLOCK_WEIGHT) if ( inf->status & EXTRA_WANT_PEN_Q ) { /*we have a domain that wants compensation @@ -1304,7 +1112,6 @@ void sedf_wake(struct vcpu *d) chance!*/ extraq_add_sort_update(d, EXTRA_PEN_Q, 0); } -#endif extraq_check_add_unblocked(d, 0); } else @@ -1316,15 +1123,7 @@ void sedf_wake(struct vcpu *d) #ifdef SEDF_STATS inf->short_block_tot++; #endif -#if (UNBLOCK <= UNBLOCK_ATROPOS) - unblock_short_vcons(inf, now); -#elif (UNBLOCK == UNBLOCK_SHORT_RESUME) - unblock_short_cons(inf, now); -#elif (UNBLOCK == UNBLOCK_BURST) - unblock_short_burst(inf, now); -#elif (UNBLOCK == UNBLOCK_EXTRA_SUPPORT) unblock_short_extra_support(inf, now); -#endif extraq_check_add_unblocked(d, 1); } @@ -1335,18 +1134,7 @@ void sedf_wake(struct vcpu *d) #ifdef SEDF_STATS inf->long_block_tot++; #endif -#if (UNBLOCK == UNBLOCK_ISOCHRONOUS_EDF) - unblock_long_vcons(inf, now); -#elif (UNBLOCK == UNBLOCK_EDF \ - || UNBLOCK == UNBLOCK_EXTRA_SUPPORT) unblock_long_cons_b(inf, now); -#elif (UNBLOCK == UNBLOCK_ATROPOS) - unblock_long_cons_c(inf, now); -#elif (UNBLOCK == UNBLOCK_SHORT_RESUME) - unblock_long_cons_b(inf, now); -#elif (UNBLOCK == UNBLOCK_BURST) - unblock_long_burst(inf, now); -#endif extraq_check_add_unblocked(d, 1); } @@ -1528,7 +1316,7 @@ static int sedf_adjust_weights(struct sched_adjdom_cmd *cmd) sumt[cpu] = 0; } - /* sum up all weights */ + /* Sum across all weights. */ for_each_domain( d ) { for_each_vcpu( d, p ) @@ -1553,7 +1341,7 @@ static int sedf_adjust_weights(struct sched_adjdom_cmd *cmd) } } - /* adjust all slices (and periods) to the new weight */ + /* Adjust all slices (and periods) to the new weight. */ for_each_domain( d ) { for_each_vcpu ( d, p ) @@ -1580,35 +1368,42 @@ static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { struct vcpu *v; - PRINT(2,"sedf_adjdom was called, domain-id %i new period %"PRIu64" "\ + PRINT(2,"sedf_adjdom was called, domain-id %i new period %"PRIu64" " "new slice %"PRIu64"\nlatency %"PRIu64" extra:%s\n", p->domain_id, cmd->u.sedf.period, cmd->u.sedf.slice, cmd->u.sedf.latency, (cmd->u.sedf.extratime)?"yes":"no"); if ( cmd->direction == SCHED_INFO_PUT ) { - /*check for sane parameters*/ - if (!cmd->u.sedf.period && !cmd->u.sedf.weight) + /* Check for sane parameters. */ + if ( !cmd->u.sedf.period && !cmd->u.sedf.weight ) return -EINVAL; - if (cmd->u.sedf.weight) { - if ((cmd->u.sedf.extratime & EXTRA_AWARE) && - (! cmd->u.sedf.period)) { - /*weight driven domains with xtime ONLY!*/ - for_each_vcpu(p, v) { + if ( cmd->u.sedf.weight ) + { + if ( (cmd->u.sedf.extratime & EXTRA_AWARE) && + (!cmd->u.sedf.period) ) + { + /* Weight-driven domains with extratime only. */ + for_each_vcpu ( p, v ) + { EDOM_INFO(v)->extraweight = cmd->u.sedf.weight; EDOM_INFO(v)->weight = 0; EDOM_INFO(v)->slice = 0; EDOM_INFO(v)->period = WEIGHT_PERIOD; } - } else { - /*weight driven domains with real-time execution*/ - for_each_vcpu(p, v) + } + else + { + /* Weight-driven domains with real-time execution. */ + for_each_vcpu ( p, v ) EDOM_INFO(v)->weight = cmd->u.sedf.weight; } } - else { - /*time driven domains*/ - for_each_vcpu(p, v) { + else + { + /* Time-driven domains. */ + for_each_vcpu ( p, v ) + { /* * Sanity checking: note that disabling extra weight requires * that we set a non-zero slice. @@ -1626,10 +1421,12 @@ static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) EDOM_INFO(v)->slice = cmd->u.sedf.slice; } } - if (sedf_adjust_weights(cmd)) + + if ( sedf_adjust_weights(cmd) ) return -EINVAL; - - for_each_vcpu(p, v) { + + for_each_vcpu ( p, v ) + { EDOM_INFO(v)->status = (EDOM_INFO(v)->status & ~EXTRA_AWARE) | (cmd->u.sedf.extratime & EXTRA_AWARE); @@ -1641,11 +1438,11 @@ static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { cmd->u.sedf.period = EDOM_INFO(p->vcpu[0])->period; cmd->u.sedf.slice = EDOM_INFO(p->vcpu[0])->slice; - cmd->u.sedf.extratime = EDOM_INFO(p->vcpu[0])->status - & EXTRA_AWARE; + cmd->u.sedf.extratime = EDOM_INFO(p->vcpu[0])->status & EXTRA_AWARE; cmd->u.sedf.latency = EDOM_INFO(p->vcpu[0])->latency; cmd->u.sedf.weight = EDOM_INFO(p->vcpu[0])->weight; } + PRINT(2,"sedf_adjdom_finished\n"); return 0; } From d36204c3835c794d014c0da489eaf41c517f4fe6 Mon Sep 17 00:00:00 2001 From: "ack@kneesa.uk.xensource.com" Date: Mon, 10 Apr 2006 10:57:38 +0100 Subject: [PATCH 126/151] fix x86_32 default linux builds --- buildconfigs/linux-defconfig_xen0_x86_64 | 2 ++ buildconfigs/linux-defconfig_xen_x86_64 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index 25cc732d0b..94d81d5ae3 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -381,6 +381,7 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_IDEPNP is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set @@ -565,6 +566,7 @@ CONFIG_NETDEVICES=y # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=y +# CONFIG_NET_SB1000 is not set # # ARCnet devices diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index ba7c616d8c..5d95052289 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -863,6 +863,7 @@ CONFIG_BLK_DEV_IDESCSI=m CONFIG_IDE_GENERIC=y CONFIG_BLK_DEV_CMD640=y CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_BLK_DEV_OFFBOARD is not set @@ -1094,6 +1095,7 @@ CONFIG_DUMMY=m CONFIG_BONDING=m CONFIG_EQUALIZER=m CONFIG_TUN=m +CONFIG_NET_SB1000=m # # ARCnet devices From d033b064ca456423fc0c55822497aa9354f6ecd8 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 11:39:32 +0100 Subject: [PATCH 127/151] Introduce page_to_bus() and use it in pci-dma-xen.c and swiotlb.c. On xen/ia64 with the P2M/VP model pseudo physical address(gpaddr) is fully virtualized so it defines xen_features(XENFEAT_auto_translated_physmap) = 1. In this case page_to_phys(page) should return pseudo physical address like pfn_to_mfn() and its families. However dma is not virtualized, it can't be used for pci-dma-xen.c, swiotlb.c. Signed-off-by: Isaku Yamahata --- linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c | 4 ++-- linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c | 4 ++-- linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h | 1 + linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c index 4d96270261..eb616232c7 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c @@ -69,7 +69,7 @@ dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, } else { for (i = 0; i < nents; i++ ) { sg[i].dma_address = - page_to_phys(sg[i].page) + sg[i].offset; + page_to_bus(sg[i].page) + sg[i].offset; sg[i].dma_length = sg[i].length; BUG_ON(!sg[i].page); IOMMU_BUG_ON(address_needs_mapping( @@ -105,7 +105,7 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset, dma_addr = swiotlb_map_page( dev, page, offset, size, direction); } else { - dma_addr = page_to_phys(page) + offset; + dma_addr = page_to_bus(page) + offset; IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr)); } diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c index e493e345c5..da0a0981ca 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c @@ -32,7 +32,7 @@ EXPORT_SYMBOL(swiotlb); #define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1))) -#define SG_ENT_PHYS_ADDRESS(sg) (page_to_phys((sg)->page) + (sg)->offset) +#define SG_ENT_PHYS_ADDRESS(sg) (page_to_bus((sg)->page) + (sg)->offset) /* * Maximum allowable number of contiguous slabs to map, @@ -607,7 +607,7 @@ swiotlb_map_page(struct device *hwdev, struct page *page, dma_addr_t dev_addr; char *map; - dev_addr = page_to_phys(page) + offset; + dev_addr = page_to_bus(page) + offset; if (address_needs_mapping(hwdev, dev_addr)) { buffer.page = page; buffer.offset = offset; diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h index 5961a42a89..7f9b7cdd36 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h @@ -102,6 +102,7 @@ static inline void * phys_to_virt(unsigned long address) */ #define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) #define page_to_phys(page) (phys_to_machine(page_to_pseudophys(page))) +#define page_to_bus(page) (phys_to_machine(page_to_pseudophys(page))) #define bio_to_pseudophys(bio) (page_to_pseudophys(bio_page((bio))) + \ (unsigned long) bio_offset((bio))) diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h index c024447ae6..1ae9c89ba9 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h @@ -130,6 +130,7 @@ static inline void * phys_to_virt(unsigned long address) */ #define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) #define page_to_phys(page) (phys_to_machine(page_to_pseudophys(page))) +#define page_to_bus(page) (phys_to_machine(page_to_pseudophys(page))) #define bio_to_pseudophys(bio) (page_to_pseudophys(bio_page((bio))) + \ (unsigned long) bio_offset((bio))) From 5dfbb5affbd3e7ba8fd8493da4325d33915465d8 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 13:24:58 +0100 Subject: [PATCH 128/151] 'make mkpatches' diffs against pristine tree rather than ref tree, so it includes extra patches under patches/ subdirectory. Signed-off-by: Keir Fraser --- buildconfigs/Rules.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildconfigs/Rules.mk b/buildconfigs/Rules.mk index e4cb40def8..0a6804bc7e 100644 --- a/buildconfigs/Rules.mk +++ b/buildconfigs/Rules.mk @@ -124,14 +124,14 @@ linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref rm -rf tmp-$@ cp -al $( $@ || true + diff -Nurp $(patsubst ref%,pristine%,$( $@ || true rm -rf tmp-$@ %-xen.patch: ref-%/.valid-ref rm -rf tmp-$@ cp -al $( $@ || true + diff -Nurp $(patsubst ref%,pristine%,$( $@ || true rm -rf tmp-$@ %-mrproper: %-mrproper-extra From 9a74026a08cea9910e704b687148172805b4b86a Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 10 Apr 2006 14:47:51 +0100 Subject: [PATCH 129/151] I used the wrong operator in a couple places for putting together some error messages out of format strings. This patch corrects those operators and fixes the strings. Signed-off-by: Ryan Wilson --- tools/python/xen/xend/server/pciif.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xend/server/pciif.py b/tools/python/xen/xend/server/pciif.py index aa222691f6..053b66adcb 100644 --- a/tools/python/xen/xend/server/pciif.py +++ b/tools/python/xen/xend/server/pciif.py @@ -115,7 +115,7 @@ class PciController(DevController): dev = PciDevice(domain, bus, slot, func) except Exception, e: raise VmError("pci: failed to locate device and "+ - "parse it's resources - %s"+str(e)) + "parse it's resources - "+str(e)) if dev.driver!='pciback': raise VmError(("pci: PCI Backend does not own device "+ \ @@ -131,7 +131,7 @@ class PciController(DevController): nr_ports = size, allow_access = True) if rc<0: raise VmError(('pci: failed to configure I/O ports on device '+ - '%s - errno=%d')&(dev.name,rc)) + '%s - errno=%d')%(dev.name,rc)) for (start, size) in dev.iomem: # Convert start/size from bytes to page frame sizes @@ -147,7 +147,7 @@ class PciController(DevController): allow_access = True) if rc<0: raise VmError(('pci: failed to configure I/O memory on device '+ - '%s - errno=%d')&(dev.name,rc)) + '%s - errno=%d')%(dev.name,rc)) if dev.irq>0: log.debug('pci: enabling irq %d'%dev.irq) @@ -155,7 +155,7 @@ class PciController(DevController): allow_access = True) if rc<0: raise VmError(('pci: failed to configure irq on device '+ - '%s - errno=%d')&(dev.name,rc)) + '%s - errno=%d')%(dev.name,rc)) def waitForBackend(self,devid): return (0, "ok - no hotplug") From cfca4d6941023d678d99e6fbd2a88f411b77e690 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 10 Apr 2006 14:51:10 +0000 Subject: [PATCH 130/151] fix bug #609 - error: PIC register `bx' clobbered in `asm' Signed-off-by: Vincent Hanquez --- tools/ioemu/hw/vga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index 3120ebac5d..11daaa27a2 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1369,10 +1369,10 @@ static inline unsigned int cpuid_edx(unsigned int op) { unsigned int eax, edx; - __asm__("cpuid" + __asm__("pushl %%ebx; cpuid; popl %%ebx" : "=a" (eax), "=d" (edx) : "0" (op) - : "bx", "cx"); + : "cx"); return edx; } From a03c61b2f7018b36d600491754123a8bd07da1e0 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 10 Apr 2006 16:21:44 +0100 Subject: [PATCH 131/151] Updated to reflect new KERNELS defaults, and properly describe make install and make dist. --- README | 334 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 176 insertions(+), 158 deletions(-) diff --git a/README b/README index 34ee02040c..b3ab351f52 100644 --- a/README +++ b/README @@ -1,158 +1,176 @@ -################################ - __ __ _____ ___ - \ \/ /___ _ __ |___ / / _ \ - \ // _ \ '_ \ |_ \| | | | - / \ __/ | | | ___) | |_| | - /_/\_\___|_| |_| |____(_)___/ - -################################ - -http://www.xensource.com/xen/about.html - -What is Xen? -============ - -Xen is a Virtual Machine Monitor (VMM) originally developed by the -Systems Research Group of the University of Cambridge Computer -Laboratory, as part of the UK-EPSRC funded XenoServers project. Xen -is freely-distributable Open Source software, released under the GNU -GPL. Since its initial public release, Xen has grown a large -development community, spearheaded by XenSource Inc, a company created -by the original Xen development team to build enterprise products -around Xen. - -The 3.0 release offers excellent performance, hardware support and -enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and -live relocation of VMs. This install tree contains source for a Linux -2.6 guest; ports to Linux 2.4, NetBSD, FreeBSD and Solaris will follow -later (and are already available for previous Xen releases). - -This file contains some quick-start instructions to install Xen on -your system. For full documentation, see the Xen User Manual. If this -is a pre-built release then you can find the manual at: - dist/install/usr/share/doc/xen/pdf/user.pdf -If you have a source release, then 'make -C docs' will build the -manual at docs/pdf/user.pdf. - -Quick-Start Guide - Pre-Built Binary Release -============================================ - -[NB. Unless noted otherwise, all the following steps should be -performed with root privileges.] - -1. Install the binary distribution onto your filesystem: - - # sh ./install.sh - - Among other things, this will install Xen and Xen-ready Linux - kernel files in /boot, kernel modules and Python packages in /lib, - and various control tools in standard 'bin' directories. - -2. Configure your bootloader to boot Xen and an initial Linux virtual - machine. Note that Xen currently only works with GRUB and pxelinux - derived boot loaders: less common alternatives such as LILO are - *not* supported. You can most likely find your GRUB menu file at - /boot/grub/menu.lst: edit this file to include an entry like the - following: - - title Xen 3.0 / XenLinux 2.6 - kernel /boot/xen-3.0.gz console=vga - module /boot/vmlinuz-2.6-xen root= ro console=tty0 - module /boot/initrd-2.6-xen.img - - NB: Not all kernel configs need an initial ram disk (initrd), but - if you do specify one you'll need to use the 'module' grub directive - rather than 'initrd'. - - The linux command line takes all the usual options, such as - root= to specify your usual root partition (e.g., - /dev/hda1). - - The Xen command line takes a number of optional arguments described - in the manual. The most common is 'dom0_mem=xxxM' which sets the - amount of memory to allocate for use by your initial virtual - machine (known as domain 0). Note that Xen itself reserves about - 32MB memory for internal use, which is not available for allocation - to virtual machines. - -3. Reboot your system and select the "Xen 3.0 / XenLinux 2.6" menu - option. After booting Xen, Linux will start and your initialisation - scripts should execute in the usual way. - -Quick-Start Guide - Source Release -================================== - -First, there are a number of prerequisites for building a Xen source -release. Make sure you have all the following installed, either by -visiting the project webpage or installing a pre-built package -provided by your Linux distributor: - * GCC (preferably v3.2.x or v3.3.x; older versions are unsupported) - * GNU Make - * GNU Binutils - * Development install of zlib (e.g., zlib-dev) - * Development install of Python v2.3 or later (e.g., python-dev) - * bridge-utils package (/sbin/brctl) - * iproute package (/sbin/ip) - * hotplug or udev - -[NB. Unless noted otherwise, all the following steps should be -performed with root privileges.] - -1. Download and untar the source tarball file. This will be a - file named xen-unstable-src.tgz, or xen-$version-src.tgz. - You can also pull the current version from the SCMS - that is being used (Bitkeeper, scheduled to change shortly). - - # tar xzf xen-unstable-src.tgz - - Assuming you are using the unstable tree, this will - untar into xen-unstable. The rest of the instructions - use the unstable tree as an example, substitute the - version for unstable. - -2. cd to xen-unstable (or whatever you sensibly rename it to). - The Linux, netbsd and freebsd kernel source trees are in - the $os-$version-xen-sparse directories. - -On Linux: - -3. For the very first build, or if you want to destroy existing - .configs and build trees, perform the following steps: - - # make KERNELS=linux-2.6-xen world - # make install - - It will create and install into the dist/ directory which is the - default install location. It will build the xen binary (xen.gz), - and a linux kernel and modules that can be used in both dom0 and an - unprivileged guest kernel (vmlinuz-2.6.x-xen), the tools and the - documentation. - - If you don't specify KERNELS= on the make command line it will - default to building two kernels, vmlinuz-2.6.x-xen0 and - vmlinuz-2.6.x-xenU. These are smaller builds with just selected - modules, intended primarilly for developers that don't like to wait - for a -xen kernel to build. The -xenU kernel is particularly small - as it does not contain any physical device drivers, and hence is - only useful for guest domains. - - If you want to build an x86_32 PAE capable xen and kernel to work - on machines with >= 4GB of memory, use XEN_TARGET_X86_PAE=y on the - make command line. - -4. To rebuild an existing tree without modifying the config: - # make dist - - This will build and install xen, kernels, tools, and - docs into the local dist/ directory. - -5. To rebuild a kernel with a modified config: - - # make linux-2.6-xen-config CONFIGMODE=menuconfig (or xconfig) - # make linux-2.6-xen-build - # make linux-2.6-xen-install - - Depending on your config, you may need to use 'mkinitrd' to create - an initial ram disk, just like a native system e.g. - # depmod 2.6.12.6-xen - # mkinitrd -v -f --with=aacraid --with=sd_mod --with=scsi_mod initrd-2.6.12.6-xen.img 2.6.12.6-xen +################################ + __ __ _____ ___ + \ \/ /___ _ __ |___ / / _ \ + \ // _ \ '_ \ |_ \| | | | + / \ __/ | | | ___) | |_| | + /_/\_\___|_| |_| |____(_)___/ + +################################ + +http://www.xensource.com/xen/about.html + +What is Xen? +============ + +Xen is a Virtual Machine Monitor (VMM) originally developed by the +Systems Research Group of the University of Cambridge Computer +Laboratory, as part of the UK-EPSRC funded XenoServers project. Xen +is freely-distributable Open Source software, released under the GNU +GPL. Since its initial public release, Xen has grown a large +development community, spearheaded by XenSource Inc, a company created +by the original Xen development team to build enterprise products +around Xen. + +The 3.0 release offers excellent performance, hardware support and +enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and +live relocation of VMs. This install tree contains source for a Linux +2.6 guest; ports to Linux 2.4, NetBSD, FreeBSD and Solaris will follow +later (and are already available for previous Xen releases). + +This file contains some quick-start instructions to install Xen on +your system. For full documentation, see the Xen User Manual. If this +is a pre-built release then you can find the manual at: + dist/install/usr/share/doc/xen/pdf/user.pdf +If you have a source release, then 'make -C docs' will build the +manual at docs/pdf/user.pdf. + +Quick-Start Guide - Pre-Built Binary Release +============================================ + +[NB. Unless noted otherwise, all the following steps should be +performed with root privileges.] + +1. Install the binary distribution onto your filesystem: + + # sh ./install.sh + + Among other things, this will install Xen and Xen-ready Linux + kernel files in /boot, kernel modules and Python packages in /lib, + and various control tools in standard 'bin' directories. + +2. Configure your bootloader to boot Xen and an initial Linux virtual + machine. Note that Xen currently only works with GRUB and pxelinux + derived boot loaders: less common alternatives such as LILO are + *not* supported. You can most likely find your GRUB menu file at + /boot/grub/menu.lst: edit this file to include an entry like the + following: + + title Xen 3.0 / XenLinux 2.6 + kernel /boot/xen-3.0.gz console=vga + module /boot/vmlinuz-2.6-xen root= ro console=tty0 + module /boot/initrd-2.6-xen.img + + NB: Not all kernel configs need an initial ram disk (initrd), but + if you do specify one you'll need to use the 'module' grub directive + rather than 'initrd'. + + The linux command line takes all the usual options, such as + root= to specify your usual root partition (e.g., + /dev/hda1). + + The Xen command line takes a number of optional arguments described + in the manual. The most common is 'dom0_mem=xxxM' which sets the + amount of memory to allocate for use by your initial virtual + machine (known as domain 0). Note that Xen itself reserves about + 32MB memory for internal use, which is not available for allocation + to virtual machines. + +3. Reboot your system and select the "Xen 3.0 / XenLinux 2.6" menu + option. After booting Xen, Linux will start and your initialisation + scripts should execute in the usual way. + +Quick-Start Guide - Source Release +================================== + +First, there are a number of prerequisites for building a Xen source +release. Make sure you have all the following installed, either by +visiting the project webpage or installing a pre-built package +provided by your Linux distributor: + * GCC (preferably v3.2.x or v3.3.x; older versions are unsupported) + * GNU Make + * GNU Binutils + * Development install of zlib (e.g., zlib-dev) + * Development install of Python v2.3 or later (e.g., python-dev) + * bridge-utils package (/sbin/brctl) + * iproute package (/sbin/ip) + * hotplug or udev + +[NB. Unless noted otherwise, all the following steps should be +performed with root privileges.] + +1. Download and untar the source tarball file. This will be a + file named xen-unstable-src.tgz, or xen-$version-src.tgz. + You can also pull the current version from the SCMS + that is being used (Bitkeeper, scheduled to change shortly). + + # tar xzf xen-unstable-src.tgz + + Assuming you are using the unstable tree, this will + untar into xen-unstable. The rest of the instructions + use the unstable tree as an example, substitute the + version for unstable. + +2. cd to xen-unstable (or whatever you sensibly rename it to). + The Linux, netbsd and freebsd kernel source trees are in + the $os-$version-xen-sparse directories. + +On Linux: + +3. For the very first build, or if you want to destroy existing + .configs and build trees, perform the following steps: + + # make world + # make install + + This will create and install onto the local machine. It will build + the xen binary (xen.gz), and a linux kernel and modules that can be + used in both dom0 and an unprivileged guest kernel (vmlinuz-2.6.x-xen), + the tools and the documentation. + + You can override the destination for make install by setting DESTDIR + to some value. + + The make command line defaults to building the kernel vmlinuz-2.6.x-xen. + You can override this default by specifying KERNELS=kernelname. For + example, you can make two kernels - linux-2.6.16-xen0 + and linux-2.6.16-xenU - which are smaller builds containing only selected + modules, intended primarilly for developers that don't like to wait + for a full -xen kernel to build. The -xenU kernel is particularly small, + as it does not contain any physical device drivers, and hence is + only useful for guest domains. + + To make these two kernels, simply specify + + KERNELS="linux-2.6.16-xen0 linux-2.6.16-xenU" + + in the make command line. + + If you want to build an x86_32 PAE capable xen and kernel to work + on machines with >= 4GB of memory, use XEN_TARGET_X86_PAE=y on the + make command line. + +4. To rebuild an existing tree without modifying the config: + # make dist + + This will build and install xen, kernels, tools, and + docs into the local dist/ directory. + + You can override the destination for make install by setting DISTDIR + to some value. + + make install and make dist differ in that make install does the + right things for your local machine (installing the appropriate + version of hotplug or udev scripts, for example), but make dist + includes all versions of those scripts, so that you can copy the dist + directory to another machine and install from that distribution. + +5. To rebuild a kernel with a modified config: + + # make linux-2.6-xen-config CONFIGMODE=menuconfig (or xconfig) + # make linux-2.6-xen-build + # make linux-2.6-xen-install + + Depending on your config, you may need to use 'mkinitrd' to create + an initial ram disk, just like a native system e.g. + # depmod 2.6.12.6-xen + # mkinitrd -v -f --with=aacraid --with=sd_mod --with=scsi_mod initrd-2.6.12.6-xen.img 2.6.12.6-xen From 913843e16be954239d3cea10c6cb511597bdb48b Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 10 Apr 2006 16:26:23 +0100 Subject: [PATCH 132/151] Fix call to server, using new XendClient syntax. Signed-off-by: Ewan Mellor --- tools/python/xen/util/diagnose.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/util/diagnose.py b/tools/python/xen/util/diagnose.py index 51c59fdfff..d2d51eb626 100644 --- a/tools/python/xen/util/diagnose.py +++ b/tools/python/xen/util/diagnose.py @@ -41,7 +41,7 @@ def diagnose(dom): global dompath try: - domain = server.xend_domain(dom) + domain = server.xend.domain(dom) state = sxp.child_value(domain, 'state') domid = int(sxp.child_value(domain, 'domid')) name = sxp.child_value(domain, 'name') From 312aae5cfc804b627bdbdeacc73e483fe18a2760 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 16:26:52 +0100 Subject: [PATCH 133/151] Remove unused netbsd build fragments. Signed-Off-By: Homrs --- buildconfigs/Rules.mk | 32 +------------------------------- buildconfigs/mk.linux-2.6-xen | 9 +++------ 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/buildconfigs/Rules.mk b/buildconfigs/Rules.mk index 0a6804bc7e..57df05e06b 100644 --- a/buildconfigs/Rules.mk +++ b/buildconfigs/Rules.mk @@ -40,29 +40,6 @@ patch-%.bz2: @echo "Cannot find $(@F) in path $(LINUX_SRC_PATH)" wget $(KERNEL_REPO)/pub/linux/kernel/v$(_LINUX_VDIR)/$(_LINUX_XDIR)/$(@F) -O./$@ -# Expand NetBSD release to NetBSD version -NETBSD_RELEASE ?= 2.0 -NETBSD_VER ?= $(patsubst netbsd-%-xen-sparse,%,$(wildcard netbsd-$(NETBSD_RELEASE)*-xen-sparse)) -NETBSD_CVSSNAP ?= 20050309 - -# Setup NetBSD search path -NETBSD_SRC_PATH ?= .:.. -vpath netbsd-%.tar.bz2 $(NETBSD_SRC_PATH) - -# download a pristine NetBSD tarball if there isn't one in NETBSD_SRC_PATH -netbsd-%-xen-kernel-$(NETBSD_CVSSNAP).tar.bz2: - @echo "Cannot find $@ in path $(NETBSD_SRC_PATH)" - wget http://www.cl.cam.ac.uk/Research/SRG/netos/xen/downloads/$@ -O./$@ - -netbsd-%.tar.bz2: netbsd-%-xen-kernel-$(NETBSD_CVSSNAP).tar.bz2 - ln -fs $< $@ - -ifeq ($(OS),linux) -OS_VER = $(LINUX_VER) -else -OS_VER = $(NETBSD_VER) -endif - pristine-%: pristine-%/.valid-pristine @true @@ -134,17 +111,10 @@ linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref diff -Nurp $(patsubst ref%,pristine%,$( $@ || true rm -rf tmp-$@ -%-mrproper: %-mrproper-extra +%-mrproper: rm -rf pristine-$(*)* ref-$(*)* $*.tar.bz2 rm -rf $*-xen.patch -netbsd-%-mrproper-extra: - rm -rf netbsd-$*-tools netbsd-$*-tools.tar.bz2 - rm -f netbsd-$*-xen-kernel-$(NETBSD_CVSSNAP).tar.bz2 - -%-mrproper-extra: - @: # do nothing - config-update-pae: ifeq ($(XEN_TARGET_X86_PAE),y) sed -e 's!^CONFIG_HIGHMEM4G=y$$!\# CONFIG_HIGHMEM4G is not set!;s!^\# CONFIG_HIGHMEM64G is not set$$!CONFIG_HIGHMEM64G=y!' $(CONFIG_FILE) > $(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE) diff --git a/buildconfigs/mk.linux-2.6-xen b/buildconfigs/mk.linux-2.6-xen index 69b3f5b554..10cba291e5 100644 --- a/buildconfigs/mk.linux-2.6-xen +++ b/buildconfigs/mk.linux-2.6-xen @@ -1,13 +1,10 @@ - -OS = linux - LINUX_SERIES = 2.6 LINUX_VER = 2.6.16 LINUX_SRCS = linux-2.6.16.tar.bz2 EXTRAVERSION ?= xen -LINUX_DIR = $(OS)-$(LINUX_VER)-$(EXTRAVERSION) +LINUX_DIR = linux-$(LINUX_VER)-$(EXTRAVERSION) include buildconfigs/Rules.mk @@ -22,7 +19,7 @@ build: $(LINUX_DIR)/include/linux/autoconf.h $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) vmlinuz $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) install -$(LINUX_DIR)/include/linux/autoconf.h: ref-$(OS)-$(LINUX_VER)/.valid-ref +$(LINUX_DIR)/include/linux/autoconf.h: ref-linux-$(LINUX_VER)/.valid-ref rm -rf $(LINUX_DIR) cp -al $( Date: Mon, 10 Apr 2006 16:27:46 +0100 Subject: [PATCH 134/151] build: Remove iptables and python loging helper targets These targets don't really fit into the build infastructure, for instance there is no faclilty for them to be removed on make distclean. I posted a patch that fleshed out the targets, but Christian Limpach suggested to me that removing them would be a better idea. Signed-Off-By: Horms --- Makefile | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Makefile b/Makefile index 3cd9d53b99..4159ba4c67 100644 --- a/Makefile +++ b/Makefile @@ -115,18 +115,6 @@ distclean: clean # Linux name for GNU distclean mrproper: distclean -install-logging: LOGGING=logging-0.4.9.2 -install-logging: - [ -f $(LOGGING).tar.gz ] || wget http://www.red-dove.com/$(LOGGING).tar.gz - tar -zxf $(LOGGING).tar.gz - cd $(LOGGING) && python setup.py install - -# handy target to upgrade iptables (use rpm or apt-get in preference) -install-iptables: - wget http://www.netfilter.org/files/iptables-1.2.11.tar.bz2 - tar -jxf iptables-1.2.11.tar.bz2 - $(MAKE) -C iptables-1.2.11 PREFIX= KERNEL_DIR=../linux-$(LINUX_VER)-xen0 install - help: @echo 'Installation targets:' @echo ' install - build and install everything' @@ -154,10 +142,6 @@ help: @echo ' kdelete - delete guest kernel build trees' @echo ' kclean - clean guest kernel build trees' @echo '' - @echo 'Dependency installation targets:' - @echo ' install-logging - install the Python Logging package' - @echo ' install-iptables - install iptables tools' - @echo '' @echo 'Miscellaneous targets:' @echo ' prep-kernels - prepares kernel directories, does not build' @echo ' mkpatches - make patches against vanilla kernels from' From 02e0e0d9bb791264722682d5dc26691e3a338803 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 10 Apr 2006 16:28:52 +0100 Subject: [PATCH 135/151] Initialise offsetopt when offset == 0. Closes bug #599. Report and diagnosis by Robert Hendrickx . Signed-off-by: Ewan Mellor --- tools/pygrub/src/fsys/ext2/ext2module.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/pygrub/src/fsys/ext2/ext2module.c b/tools/pygrub/src/fsys/ext2/ext2module.c index 63d20f2983..57f1a83eaf 100644 --- a/tools/pygrub/src/fsys/ext2/ext2module.c +++ b/tools/pygrub/src/fsys/ext2/ext2module.c @@ -228,7 +228,10 @@ ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs) } #ifdef HAVE_EXT2FS_OPEN2 - if (offset != 0) { + if (offset == 0) { + offsetopt[0] = '\0'; + } + else { snprintf(offsetopt, 29, "offset=%d", offset); } From 4886bb64c1ab8f5c0884a6ebc5c9c7591149684b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 16:31:53 +0100 Subject: [PATCH 136/151] build: Make sure that DESTDIR is set In the case where XEN_PYTHON_NATIVE_INSTALL is in effect, if DESTDIR is not set then the install will go into a relative directory rather than under the default prefix (usually /usr). An alternate solution would be to update the fragments that do the python install to use $(DESTDIR)/ instead of $(DESTDIR). This is not an incredible burden as there are only two such fragments in the tree. However, it seems prone to error as new makefiles are created in the future. Signed-Off-By: Horms --- Config.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Config.mk b/Config.mk index 7cea3953c5..2b15addd12 100644 --- a/Config.mk +++ b/Config.mk @@ -24,6 +24,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump DISTDIR ?= $(XEN_ROOT)/dist +DESTDIR ?= / INSTALL = install INSTALL_DIR = $(INSTALL) -d -m0755 From f2bc7f94025a2f2d511c9da03edd56584c0055ba Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 16:34:59 +0100 Subject: [PATCH 137/151] build: clean up output of make help a little bit Signed-Off-By: Horms --- Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 4159ba4c67..e9dcdfccac 100644 --- a/Makefile +++ b/Makefile @@ -135,10 +135,9 @@ help: @echo ' dev-docs - build developer-only documentation' @echo '' @echo 'Cleaning targets:' - @echo ' clean - clean the Xen, tools and docs (but not' - @echo ' guest kernel) trees' - @echo ' distclean - clean plus delete kernel tarballs and kernel' - @echo ' build trees' + @echo ' clean - clean the Xen, tools and docs (but not guest kernel trees)' + @echo ' distclean - clean plus delete kernel build trees and' + @echo ' local downloaded files' @echo ' kdelete - delete guest kernel build trees' @echo ' kclean - clean guest kernel build trees' @echo '' @@ -146,8 +145,8 @@ help: @echo ' prep-kernels - prepares kernel directories, does not build' @echo ' mkpatches - make patches against vanilla kernels from' @echo ' sparse trees' - @echo ' uninstall - attempt to remove installed Xen tools (use' - @echo ' with extreme care!)' + @echo ' uninstall - attempt to remove installed Xen tools' + @echo ' (use with extreme care!)' # Use this target with extreme care! uninstall: D=$(DESTDIR) From 9ffd98fa29fd8dc997529fa120d25446dbbc1bdd Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 16:35:30 +0100 Subject: [PATCH 138/151] build: Document the use of XEN_PYTHON_NATIVE_INSTALL Document the use of the XEN_PYTHON_NATIVE_INSTALL environment variable Signed-Off-By: Horms --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index e9dcdfccac..71a7c7d342 100644 --- a/Makefile +++ b/Makefile @@ -147,6 +147,13 @@ help: @echo ' sparse trees' @echo ' uninstall - attempt to remove installed Xen tools' @echo ' (use with extreme care!)' + @echo + @echo 'Environment:' + @echo ' XEN_PYTHON_NATIVE_INSTALL=y' + @echo ' - native python install or dist' + @echo ' install into prefix/lib/python' + @echo ' instead of /lib/python' + @echo ' true if set to non-empty value, false otherwise' # Use this target with extreme care! uninstall: D=$(DESTDIR) From 0198288b1f5f296f043439bd647877effb870df7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 16:36:38 +0100 Subject: [PATCH 139/151] build: Clean pygrub's a.out Signed-Off-By: Magnus Damm Signed-Off-By: Horms --- tools/pygrub/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pygrub/Makefile b/tools/pygrub/Makefile index fbe27a9bf1..197b89a1a8 100644 --- a/tools/pygrub/Makefile +++ b/tools/pygrub/Makefile @@ -15,4 +15,4 @@ install: all endif clean: - rm -rf build tmp *.pyc *.pyo *.o *.a *~ + rm -rf build tmp *.pyc *.pyo *.o *.a *~ a.out From 73004d34e4efc04bf0fc798615202361b39dd9a8 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 17:16:25 +0100 Subject: [PATCH 140/151] If the 'cdrom=' option is specified in the definition file but media is not found in the CD drive then main() in vl.c exits and the guest appears to hang. This patch modifies vl.c slightly to check for the presents of media. If the cdrom cannot be opened then the cd entry is removed from hd_filename[] and bs_table[] allowing the guest to continue initializing. If the guest requires the CD media then the guest should report, gracefully or otherwise, that it's missing. From: Ross Maxfield Signed-off-by: Keir Fraser --- tools/ioemu/vl.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index da009dd11b..d4f305f178 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -3245,8 +3245,17 @@ int main(int argc, char **argv) /* we always create the cdrom drive, even if no disk is there */ bdrv_init(); if (has_cdrom) { - bs_table[2] = bdrv_new("cdrom"); - bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM); + int fd; + if ( (fd = open(hd_filename[2], O_RDONLY | O_BINARY)) < 0) { + hd_filename[2]=NULL; + bs_table[2]=NULL; + fprintf(logfile, "Could not open CD %s.\n", hd_filename[i]); + } + else { + close(fd); + bs_table[2] = bdrv_new("cdrom"); + bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM); + } } /* open the virtual block devices */ From 4f32cad22c9faaf10470b22eb117b0c06d57f909 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 17:25:42 +0100 Subject: [PATCH 141/151] Fix push/pop usage in tools/ioemu for x86/64. Signed-off-by: Keir Fraser --- tools/ioemu/hw/vga.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index 11daaa27a2..c6fca32ae4 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1369,10 +1369,16 @@ static inline unsigned int cpuid_edx(unsigned int op) { unsigned int eax, edx; - __asm__("pushl %%ebx; cpuid; popl %%ebx" +#ifdef __x86_64__ +#define __bx "rbx" +#else +#define __bx "ebx" +#endif + __asm__("push %%"__bx"; cpuid; pop %%"__bx : "=a" (eax), "=d" (edx) : "0" (op) : "cx"); +#undef __ebx return edx; } From 201c3aa978b9874d91af95c19f8f36e112b4cccb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 17:28:02 +0100 Subject: [PATCH 142/151] Fix a couple of typos. Signed-off-by: Keir Fraser --- tools/ioemu/hw/vga.c | 2 +- xen/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index c6fca32ae4..c04befca3b 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1378,7 +1378,7 @@ static inline unsigned int cpuid_edx(unsigned int op) : "=a" (eax), "=d" (edx) : "0" (op) : "cx"); -#undef __ebx +#undef __bx return edx; } diff --git a/xen/Makefile b/xen/Makefile index 3bda17760f..631f0c791f 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -48,7 +48,7 @@ clean:: delete-unfresh-files endif -.PHONY: install +.PHONY: dist dist: install .PHONY: debug From 7ddc2369b20e6b9e4f067585d8c7389b33b00abb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 17:32:30 +0100 Subject: [PATCH 143/151] Fail the build if NR_hypercalls is not a power of two. Making this requirement clearer originally suggested by Muli Ben Yehuda. Signed-off-by: Keir Fraser --- xen/include/asm-x86/config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 23aabeb2b9..35efb1ba63 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -65,8 +65,13 @@ #define barrier() __asm__ __volatile__("": : :"memory") +/* A power-of-two value greater than or equal to number of hypercalls. */ #define NR_hypercalls 32 +#if NR_hypercalls & (NR_hypercalls - 1) +#error "NR_hypercalls must be a power-of-two value" +#endif + #ifndef NDEBUG #define MEMORY_GUARD #ifdef __x86_64__ From 45fe4ec419c8bb411674575e1f0f706a92072a99 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Mon, 10 Apr 2006 18:17:54 +0100 Subject: [PATCH 144/151] Fix the test inside all_devices_ready, and move it from xenbus_probe (a postcore_initcall) to a new late_initcall, so that it happens after the drivers have initialised. Fixes the reopened bug #549 (I hope). Signed-off-by: Ewan Mellor --- .../drivers/xen/xenbus/xenbus_probe.c | 63 +++++++++++-------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index e9c8315856..945a129cf1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -3,7 +3,7 @@ * * Copyright (C) 2005 Rusty Russell, IBM Corporation * Copyright (C) 2005 Mike Wray, Hewlett-Packard - * Copyright (C) 2005 XenSource Ltd + * Copyright (C) 2005, 2006 XenSource Ltd * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -883,7 +883,7 @@ static int all_devices_ready_(struct device *dev, void *data) int *result = data; if (xendev->state != XenbusStateConnected) { - result = 0; + *result = 0; return 1; } @@ -902,8 +902,6 @@ static int all_devices_ready(void) void xenbus_probe(void *unused) { - int i; - BUG_ON((xenstored_ready <= 0)); /* Enumerate devices in xenstore. */ @@ -916,28 +914,6 @@ void xenbus_probe(void *unused) /* Notify others that xenstore is up */ notifier_call_chain(&xenstore_chain, 0, NULL); - - /* On a 10 second timeout, waiting for all devices currently - configured. We need to do this to guarantee that the filesystems - and / or network devices needed for boot are available, before we - can allow the boot to proceed. - - A possible improvement here would be to have the tools add a - per-device flag to the store entry, indicating whether it is needed - at boot time. This would allow people who knew what they were - doing to accelerate their boot slightly, but of course needs tools - or manual intervention to set up those flags correctly. - */ - for (i = 0; i < 10 * HZ; i++) { - if (all_devices_ready()) - return; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - printk(KERN_WARNING - "XENBUS: Timeout connecting to devices!\n"); } @@ -1072,6 +1048,41 @@ static int __init xenbus_probe_init(void) postcore_initcall(xenbus_probe_init); + +/* + * On a 10 second timeout, wait for all devices currently configured. We need + * to do this to guarantee that the filesystems and / or network devices + * needed for boot are available, before we can allow the boot to proceed. + * + * This needs to be on a late_initcall, to happen after the frontend device + * drivers have been initialised, but before the root fs is mounted. + * + * A possible improvement here would be to have the tools add a per-device + * flag to the store entry, indicating whether it is needed at boot time. + * This would allow people who knew what they were doing to accelerate their + * boot slightly, but of course needs tools or manual intervention to set up + * those flags correctly. + */ +static int __init wait_for_devices(void) +{ + int i; + + for (i = 0; i < 10 * HZ; i++) { + if (all_devices_ready()) { + return; + } + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + printk(KERN_WARNING + "XENBUS: Timeout connecting to devices!\n"); +} + +late_initcall(wait_for_devices); + + /* * Local variables: * c-file-style: "linux" From 6c33dc47820160b8dc0fb9b8de0400cb83805563 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 18:30:07 +0100 Subject: [PATCH 145/151] Add a new config option for all backend drivers. This has two benefits: 1. All backend drivers can be disabled or modularised via one config option. 2. Backend helper routines that are not specific to any particular driver can be disabled or modularised based on this config option. In particular this may allow backend drivers plus the service module to be upgraded separate from the kernel core as and when the backend interfaces change (and they will). Signed-off-by: Keir Fraser --- buildconfigs/linux-defconfig_xen0_ia64 | 1 + buildconfigs/linux-defconfig_xen0_x86_32 | 1 + buildconfigs/linux-defconfig_xen0_x86_64 | 1 + buildconfigs/linux-defconfig_xenU_ia64 | 1 + buildconfigs/linux-defconfig_xenU_x86_32 | 6 +- buildconfigs/linux-defconfig_xenU_x86_64 | 6 +- buildconfigs/linux-defconfig_xen_ia64 | 1 + buildconfigs/linux-defconfig_xen_x86_32 | 1 + buildconfigs/linux-defconfig_xen_x86_64 | 1 + linux-2.6-xen-sparse/arch/ia64/Kconfig | 7 +- linux-2.6-xen-sparse/drivers/xen/Kconfig | 13 +- .../drivers/xen/xenbus/Makefile | 4 + .../xen/xenbus/xenbus_backend_client.c | 173 ++++++++++++++++++ .../drivers/xen/xenbus/xenbus_client.c | 128 ------------- 14 files changed, 204 insertions(+), 140 deletions(-) create mode 100644 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64 index 2dbb12644e..b77e462d8d 100644 --- a/buildconfigs/linux-defconfig_xen0_ia64 +++ b/buildconfigs/linux-defconfig_xen0_ia64 @@ -95,6 +95,7 @@ CONFIG_ARCH_XEN=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_BLKDEV_GRANT=y CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_BACKEND=y CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_SYSFS=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32 index fe24dacce5..4c040a58ae 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_32 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 @@ -1316,6 +1316,7 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030101 # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index 94d81d5ae3..e99e956803 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -1246,6 +1246,7 @@ CONFIG_NO_IDLE_HZ=y # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y diff --git a/buildconfigs/linux-defconfig_xenU_ia64 b/buildconfigs/linux-defconfig_xenU_ia64 index da7a4e5b0c..d1d330b8ef 100644 --- a/buildconfigs/linux-defconfig_xenU_ia64 +++ b/buildconfigs/linux-defconfig_xenU_ia64 @@ -92,6 +92,7 @@ CONFIG_ARCH_XEN=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_BLKDEV_GRANT=y CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_BACKEND=y CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_SYSFS=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/buildconfigs/linux-defconfig_xenU_x86_32 b/buildconfigs/linux-defconfig_xenU_x86_32 index cca500a2e4..950220c079 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_32 +++ b/buildconfigs/linux-defconfig_xenU_x86_32 @@ -859,13 +859,9 @@ CONFIG_NO_IDLE_HZ=y # # CONFIG_XEN_PRIVILEGED_GUEST is not set CONFIG_XEN_UNPRIVILEGED_GUEST=y -# CONFIG_XEN_PCIDEV_BACKEND is not set -# CONFIG_XEN_BLKDEV_BACKEND is not set -# CONFIG_XEN_NETDEV_BACKEND is not set -# CONFIG_XEN_TPMDEV_BACKEND is not set +# CONFIG_XEN_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_TPMDEV_FRONTEND is not set CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y diff --git a/buildconfigs/linux-defconfig_xenU_x86_64 b/buildconfigs/linux-defconfig_xenU_x86_64 index 68893b915e..5b61581ddf 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_64 +++ b/buildconfigs/linux-defconfig_xenU_x86_64 @@ -1135,13 +1135,9 @@ CONFIG_NO_IDLE_HZ=y # # CONFIG_XEN_PRIVILEGED_GUEST is not set CONFIG_XEN_UNPRIVILEGED_GUEST=y -# CONFIG_XEN_PCIDEV_BACKEND is not set -# CONFIG_XEN_BLKDEV_BACKEND is not set -# CONFIG_XEN_NETDEV_BACKEND is not set -# CONFIG_XEN_TPMDEV_BACKEND is not set +# CONFIG_XEN_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_TPMDEV_FRONTEND is not set CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64 index 6592742e37..3c3c6e5206 100644 --- a/buildconfigs/linux-defconfig_xen_ia64 +++ b/buildconfigs/linux-defconfig_xen_ia64 @@ -95,6 +95,7 @@ CONFIG_ARCH_XEN=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_BLKDEV_GRANT=y CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_BACKEND=y CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_SYSFS=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index 27a102a80c..b5dfca04c3 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -2979,6 +2979,7 @@ CONFIG_NO_IDLE_HZ=y # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index 5d95052289..60e1c7dded 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -2656,6 +2656,7 @@ CONFIG_NO_IDLE_HZ=y # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y diff --git a/linux-2.6-xen-sparse/arch/ia64/Kconfig b/linux-2.6-xen-sparse/arch/ia64/Kconfig index db86da7611..4f3c58cb71 100644 --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig @@ -79,11 +79,16 @@ config XEN_BLKDEV_FRONTEND bool default y -config XEN_BLKDEV_BACKEND +config XEN_BACKEND depends on XEN bool default y +config XEN_BLKDEV_BACKEND + depends on XEN && XEN_BACKEND + bool + default y + config XEN_SYSFS bool "Export Xen attributes in sysfs" depends on XEN && SYSFS diff --git a/linux-2.6-xen-sparse/drivers/xen/Kconfig b/linux-2.6-xen-sparse/drivers/xen/Kconfig index 6518ff821a..0595eb0028 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig @@ -28,9 +28,16 @@ config XEN_UNPRIVILEGED_GUEST bool default !XEN_PRIVILEGED_GUEST +config XEN_BACKEND + tristate "Backend driver support" + default y + help + Support for backend device drivers that provide I/O services + to other virtual machines. + config XEN_PCIDEV_BACKEND tristate "PCI device backend driver" - depends PCI + depends on PCI && XEN_BACKEND default XEN_PRIVILEGED_GUEST help The PCI device backend driver allows the kernel to export arbitrary @@ -70,6 +77,7 @@ config XEN_PCIDEV_BE_DEBUG config XEN_BLKDEV_BACKEND tristate "Block-device backend driver" + depends on XEN_BACKEND default y help The block-device backend driver allows the kernel to export its @@ -91,6 +99,7 @@ config XEN_BLKDEV_TAP_BE config XEN_NETDEV_BACKEND tristate "Network-device backend driver" + depends on XEN_BACKEND default y help The network-device backend driver allows the kernel to export its @@ -120,6 +129,7 @@ config XEN_NETDEV_LOOPBACK config XEN_TPMDEV_BACKEND tristate "TPM-device backend driver" + depends on XEN_BACKEND default n help The TPM-device backend driver @@ -155,6 +165,7 @@ config XEN_NETDEV_FRONTEND config XEN_BLKDEV_TAP tristate "Block device tap driver" + depends on XEN_BACKEND default n help This driver allows a VM to interact on block device channels diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile index 4ef620cd7c..899cc3133d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile @@ -1,4 +1,8 @@ obj-y += xenbus.o +obj-$(CONFIG_XEN_BACKEND) += xenbus_be.o + +xenbus_be-objs = +xenbus_be-objs += xenbus_backend_client.o xenbus-objs = xenbus-objs += xenbus_client.o diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c new file mode 100644 index 0000000000..72327ec692 --- /dev/null +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_backend_client.c @@ -0,0 +1,173 @@ +/****************************************************************************** + * Backend-client-facing interface for the Xenbus driver. In other words, the + * interface between the Xenbus and the device-specific code in the backend + * driver. + * + * Copyright (C) 2005-2006 XenSource Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include + +/* Based on Rusty Russell's skeleton driver's map_page */ +int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) +{ + struct gnttab_map_grant_ref op = { + .flags = GNTMAP_host_map, + .ref = gnt_ref, + .dom = dev->otherend_id, + }; + struct vm_struct *area; + + *vaddr = NULL; + + area = alloc_vm_area(PAGE_SIZE); + if (!area) + return -ENOMEM; + + op.host_addr = (unsigned long)area->addr; + + lock_vm_area(area); + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)); + unlock_vm_area(area); + + if (op.status != GNTST_okay) { + free_vm_area(area); + xenbus_dev_fatal(dev, op.status, + "mapping in shared page %d from domain %d", + gnt_ref, dev->otherend_id); + return op.status; + } + + /* Stuff the handle in an unused field */ + area->phys_addr = (unsigned long)op.handle; + + *vaddr = area->addr; + return 0; +} +EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc); + + +int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref, + grant_handle_t *handle, void *vaddr) +{ + struct gnttab_map_grant_ref op = { + .host_addr = (unsigned long)vaddr, + .flags = GNTMAP_host_map, + .ref = gnt_ref, + .dom = dev->otherend_id, + }; + + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)); + + if (op.status != GNTST_okay) { + xenbus_dev_fatal(dev, op.status, + "mapping in shared page %d from domain %d", + gnt_ref, dev->otherend_id); + } else + *handle = op.handle; + + return op.status; +} +EXPORT_SYMBOL_GPL(xenbus_map_ring); + + +/* Based on Rusty Russell's skeleton driver's unmap_page */ +int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) +{ + struct vm_struct *area; + struct gnttab_unmap_grant_ref op = { + .host_addr = (unsigned long)vaddr, + }; + + /* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr) + * method so that we don't have to muck with vmalloc internals here. + * We could force the user to hang on to their struct vm_struct from + * xenbus_map_ring_valloc, but these 6 lines considerably simplify + * this API. + */ + read_lock(&vmlist_lock); + for (area = vmlist; area != NULL; area = area->next) { + if (area->addr == vaddr) + break; + } + read_unlock(&vmlist_lock); + + if (!area) { + xenbus_dev_error(dev, -ENOENT, + "can't find mapped virtual address %p", vaddr); + return GNTST_bad_virt_addr; + } + + op.handle = (grant_handle_t)area->phys_addr; + + lock_vm_area(area); + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); + unlock_vm_area(area); + + if (op.status == GNTST_okay) + free_vm_area(area); + else + xenbus_dev_error(dev, op.status, + "unmapping page at handle %d error %d", + (int16_t)area->phys_addr, op.status); + + return op.status; +} +EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree); + + +int xenbus_unmap_ring(struct xenbus_device *dev, + grant_handle_t handle, void *vaddr) +{ + struct gnttab_unmap_grant_ref op = { + .host_addr = (unsigned long)vaddr, + .handle = handle, + }; + + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); + + if (op.status != GNTST_okay) + xenbus_dev_error(dev, op.status, + "unmapping page at handle %d error %d", + handle, op.status); + + return op.status; +} +EXPORT_SYMBOL_GPL(xenbus_unmap_ring); + + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c index 38ac7f2c49..d4059b18c2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @@ -261,134 +261,6 @@ int xenbus_free_evtchn(struct xenbus_device *dev, int port) } -/* Based on Rusty Russell's skeleton driver's map_page */ -int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr) -{ - struct gnttab_map_grant_ref op = { - .flags = GNTMAP_host_map, - .ref = gnt_ref, - .dom = dev->otherend_id, - }; - struct vm_struct *area; - - *vaddr = NULL; - - area = alloc_vm_area(PAGE_SIZE); - if (!area) - return -ENOMEM; - - op.host_addr = (unsigned long)area->addr; - - lock_vm_area(area); - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)); - unlock_vm_area(area); - - if (op.status != GNTST_okay) { - free_vm_area(area); - xenbus_dev_fatal(dev, op.status, - "mapping in shared page %d from domain %d", - gnt_ref, dev->otherend_id); - return op.status; - } - - /* Stuff the handle in an unused field */ - area->phys_addr = (unsigned long)op.handle; - - *vaddr = area->addr; - return 0; -} -EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc); - - -int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref, - grant_handle_t *handle, void *vaddr) -{ - struct gnttab_map_grant_ref op = { - .host_addr = (unsigned long)vaddr, - .flags = GNTMAP_host_map, - .ref = gnt_ref, - .dom = dev->otherend_id, - }; - - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)); - - if (op.status != GNTST_okay) { - xenbus_dev_fatal(dev, op.status, - "mapping in shared page %d from domain %d", - gnt_ref, dev->otherend_id); - } else - *handle = op.handle; - - return op.status; -} -EXPORT_SYMBOL_GPL(xenbus_map_ring); - - -/* Based on Rusty Russell's skeleton driver's unmap_page */ -int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) -{ - struct vm_struct *area; - struct gnttab_unmap_grant_ref op = { - .host_addr = (unsigned long)vaddr, - }; - - /* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr) - * method so that we don't have to muck with vmalloc internals here. - * We could force the user to hang on to their struct vm_struct from - * xenbus_map_ring_valloc, but these 6 lines considerably simplify - * this API. - */ - read_lock(&vmlist_lock); - for (area = vmlist; area != NULL; area = area->next) { - if (area->addr == vaddr) - break; - } - read_unlock(&vmlist_lock); - - if (!area) { - xenbus_dev_error(dev, -ENOENT, - "can't find mapped virtual address %p", vaddr); - return GNTST_bad_virt_addr; - } - - op.handle = (grant_handle_t)area->phys_addr; - - lock_vm_area(area); - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); - unlock_vm_area(area); - - if (op.status == GNTST_okay) - free_vm_area(area); - else - xenbus_dev_error(dev, op.status, - "unmapping page at handle %d error %d", - (int16_t)area->phys_addr, op.status); - - return op.status; -} -EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree); - - -int xenbus_unmap_ring(struct xenbus_device *dev, - grant_handle_t handle, void *vaddr) -{ - struct gnttab_unmap_grant_ref op = { - .host_addr = (unsigned long)vaddr, - .handle = handle, - }; - - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); - - if (op.status != GNTST_okay) - xenbus_dev_error(dev, op.status, - "unmapping page at handle %d error %d", - handle, op.status); - - return op.status; -} -EXPORT_SYMBOL_GPL(xenbus_unmap_ring); - - XenbusState xenbus_read_driver_state(const char *path) { XenbusState result; From 72344c0921c6db5091d0f94af98babb77b89caae Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 10 Apr 2006 18:56:34 +0100 Subject: [PATCH 146/151] Netfront must switch state using xenbus_switch_state() or this is not picked up by the waiting code in xenbus_probe.c. Also clean up the waiting code a little. Signed-off-by: Keir Fraser --- .../drivers/xen/netfront/netfront.c | 9 ++------- .../drivers/xen/xenbus/xenbus_probe.c | 17 +++++++---------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 1336be5432..9a1aebefd7 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -300,13 +300,6 @@ again: goto abort_transaction; } - err = xenbus_printf(xbt, dev->nodename, - "state", "%d", XenbusStateConnected); - if (err) { - message = "writing frontend XenbusStateConnected"; - goto abort_transaction; - } - err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) @@ -315,6 +308,8 @@ again: goto destroy_ring; } + xenbus_switch_state(dev, XenbusStateConnected); + return 0; abort_transaction: diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 945a129cf1..94fd44f7f9 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -1065,19 +1065,16 @@ postcore_initcall(xenbus_probe_init); */ static int __init wait_for_devices(void) { - int i; + unsigned long timeout = jiffies + 10*HZ; - for (i = 0; i < 10 * HZ; i++) { - if (all_devices_ready()) { - return; - } - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + while (time_before(jiffies, timeout)) { + if (all_devices_ready()) + return 0; + schedule_timeout_interruptible(HZ/10); } - printk(KERN_WARNING - "XENBUS: Timeout connecting to devices!\n"); + printk(KERN_WARNING "XENBUS: Timeout connecting to devices!\n"); + return 0; } late_initcall(wait_for_devices); From 5c0356ec6f4a9897bfcc9fb08418ff82e61f1cf6 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 11 Apr 2006 09:58:04 +0100 Subject: [PATCH 147/151] Remove some bogus .PHONY Makefile declarations. Fixes xentop installation. Signed-off-by: Keir Fraser --- tools/xenstat/xentop/Makefile | 3 --- tools/xenstore/Makefile | 2 -- xen/arch/ia64/tools/privop/Makefile | 1 - xen/tools/Makefile | 1 - 4 files changed, 7 deletions(-) diff --git a/tools/xenstat/xentop/Makefile b/tools/xenstat/xentop/Makefile index d3b7671bdb..273cb31e4e 100644 --- a/tools/xenstat/xentop/Makefile +++ b/tools/xenstat/xentop/Makefile @@ -34,9 +34,6 @@ LDLIBS += -lxenstat -lncurses .PHONY: all all: xentop -.PHONY: xentop -xentop: xentop.o - .PHONY: install install: xentop xentop.1 $(INSTALL_PROG) xentop $(DESTDIR)$(sbindir)/xentop diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile index 708662e8fc..84c08d8626 100644 --- a/tools/xenstore/Makefile +++ b/tools/xenstore/Makefile @@ -57,14 +57,12 @@ xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_te xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ -.PHONY: xs_test xs_random xs_stress xs_crashme xs_test xs_random xs_stress xs_crashme: LDFLAGS+=-lpthread xs_test: xs_test.o xs_lib.o utils.o xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o -.PHONY: speedtest speedtest: speedtest.o xs.o xs_lib.o utils.o talloc.o .PHONY: check-speed diff --git a/xen/arch/ia64/tools/privop/Makefile b/xen/arch/ia64/tools/privop/Makefile index fb64e9087e..fbe5f0ad3e 100644 --- a/xen/arch/ia64/tools/privop/Makefile +++ b/xen/arch/ia64/tools/privop/Makefile @@ -4,7 +4,6 @@ CFLAGS=-O -Wall .PHONY: all all: postat -.PHONY: postat postat: postat.c pohcalls.o .PHONY: clean diff --git a/xen/tools/Makefile b/xen/tools/Makefile index 67c48ce168..70a37092db 100644 --- a/xen/tools/Makefile +++ b/xen/tools/Makefile @@ -11,6 +11,5 @@ clean: $(MAKE) -C figlet clean rm -f *.o symbols -.PHONY: symbols symbols: symbols.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< From 89bbff5329afc3b05ccc14ef3cf733f35d8ea4d3 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 11 Apr 2006 10:40:03 +0100 Subject: [PATCH 148/151] Make event_pending() architecture-specific. PowerPC needs this because the domain can directly modify the hardware's "interrupts enabled" bit, and we don't want to patch Linux to replace all those accesses to use evtchn_upcall_mask instead. Signed-off-by: Hollis Blanchard --- xen/include/asm-ia64/event.h | 5 +++++ xen/include/asm-x86/event.h | 5 +++++ xen/include/xen/event.h | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/xen/include/asm-ia64/event.h b/xen/include/asm-ia64/event.h index 297351072d..32afe39795 100644 --- a/xen/include/asm-ia64/event.h +++ b/xen/include/asm-ia64/event.h @@ -32,4 +32,9 @@ static inline void evtchn_notify(struct vcpu *v) vcpu_pend_interrupt(v, v->vcpu_info->arch.evtchn_vector); } +/* Note: Bitwise operations result in fast code with no branches. */ +#define event_pending(v) \ + (!!(v)->vcpu_info->evtchn_upcall_pending & \ + !(v)->vcpu_info->evtchn_upcall_mask) + #endif diff --git a/xen/include/asm-x86/event.h b/xen/include/asm-x86/event.h index d491d24313..ad1b9b245a 100644 --- a/xen/include/asm-x86/event.h +++ b/xen/include/asm-x86/event.h @@ -26,4 +26,9 @@ static inline void evtchn_notify(struct vcpu *v) smp_send_event_check_cpu(v->processor); } +/* Note: Bitwise operations result in fast code with no branches. */ +#define event_pending(v) \ + (!!(v)->vcpu_info->evtchn_upcall_pending & \ + !(v)->vcpu_info->evtchn_upcall_mask) + #endif diff --git a/xen/include/xen/event.h b/xen/include/xen/event.h index 13b2b5f9be..f7dee3b75d 100644 --- a/xen/include/xen/event.h +++ b/xen/include/xen/event.h @@ -38,11 +38,6 @@ extern void send_guest_global_virq(struct domain *d, int virq); */ extern void send_guest_pirq(struct domain *d, int pirq); -/* Note: Bitwise operations result in fast code with no branches. */ -#define event_pending(v) \ - (!!(v)->vcpu_info->evtchn_upcall_pending & \ - !(v)->vcpu_info->evtchn_upcall_mask) - #define evtchn_pending(d, p) \ (test_bit((p), &(d)->shared_info->evtchn_pending[0])) From f65a2c89be92aadb157ef225864322174a3d51e4 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 11 Apr 2006 10:41:08 +0100 Subject: [PATCH 149/151] When running test 5 in Memtest86+ v1.65, I got a "this opcode is not supported", so I decided to add it. It's a compare operation, and it's just the opposite of the already supported one (opcode 0x39), so it's nothing spectacular. Why there's a page-fault when this instruction gets executed, I haven't got a clue, but I have a feeling that Memtest86 is doing something wrong :-( However, this fix may help some other code to run too... With this, Test 5 passes all the way through without crashing. I did see some occassional memory errors in some other tests, and I'm not 100% sure whether those are caused by the system or they are "real" memory errors. At some time in the future I may get round to memory testing my target system... Signed off by: Mats Petersson (mats.petersson@amd.com).=20 --- xen/arch/x86/hvm/platform.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index c36360bcb3..1e78470d34 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -401,6 +401,11 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); return reg_mem(instr->op_size, opcode, instr, rex); + case 0x3B: /* cmp m32/16, r32/16 */ + instr->instr = INSTR_CMP; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return mem_reg(instr->op_size, opcode, instr, rex); + case 0x80: case 0x81: { From 4878a87b440b782f2753f217c3e37d959717023a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 11 Apr 2006 10:44:07 +0100 Subject: [PATCH 150/151] The maximum instruction length for both x86-32 and x86-64 is 15 bytes (including all prefixes, opcode, ModRM, SIB, displacement, and immediate bytes). This patch adjusts the MAX_INST_LEN to the correct value. This should reduce the size of some variables in the hypervisor code. This patch also does some minor code clean-up in the vm exit handler for VMX. Signed-off-by: Khoa Huynh --- xen/arch/x86/hvm/vmx/vmx.c | 10 ++++------ xen/include/asm-x86/hvm/io.h | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 5f7fa0221e..059b188f91 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1947,7 +1947,7 @@ static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs) && !(vector & INTR_INFO_VALID_MASK)) __hvm_bug(regs); - vector &= 0xff; + vector &= INTR_INFO_VECTOR_MASK; local_irq_disable(); TRACE_VMEXIT(1,vector); @@ -2077,10 +2077,8 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) return; } - { - __vmread(GUEST_RIP, &eip); - TRACE_VMEXIT(0,exit_reason); - } + __vmread(GUEST_RIP, &eip); + TRACE_VMEXIT(0,exit_reason); switch (exit_reason) { case EXIT_REASON_EXCEPTION_NMI: @@ -2097,7 +2095,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) if ((error = __vmread(VM_EXIT_INTR_INFO, &vector)) || !(vector & INTR_INFO_VALID_MASK)) __hvm_bug(®s); - vector &= 0xff; + vector &= INTR_INFO_VECTOR_MASK; TRACE_VMEXIT(1,vector); perfc_incra(cause_vector, vector); diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index b315997102..0d4b36b0ad 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -77,7 +77,7 @@ struct instruction { __u32 flags; }; -#define MAX_INST_LEN 32 +#define MAX_INST_LEN 15 /* Maximum instruction length = 15 bytes */ struct mmio_op { int flags; From 0dc4b1f3011f0ac549d901f0746ab99a733f8283 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Tue, 11 Apr 2006 12:46:39 +0100 Subject: [PATCH 151/151] Fix KERNELS example, mkinitrd example. Signed-off-by: Ewan Mellor --- README | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README b/README index b3ab351f52..b295c300ed 100644 --- a/README +++ b/README @@ -132,16 +132,16 @@ On Linux: The make command line defaults to building the kernel vmlinuz-2.6.x-xen. You can override this default by specifying KERNELS=kernelname. For - example, you can make two kernels - linux-2.6.16-xen0 - and linux-2.6.16-xenU - which are smaller builds containing only selected - modules, intended primarilly for developers that don't like to wait + example, you can make two kernels - linux-2.6-xen0 + and linux-2.6-xenU - which are smaller builds containing only selected + modules, intended primarily for developers that don't like to wait for a full -xen kernel to build. The -xenU kernel is particularly small, as it does not contain any physical device drivers, and hence is only useful for guest domains. To make these two kernels, simply specify - KERNELS="linux-2.6.16-xen0 linux-2.6.16-xenU" + KERNELS="linux-2.6-xen0 linux-2.6-xenU" in the make command line. @@ -172,5 +172,5 @@ On Linux: Depending on your config, you may need to use 'mkinitrd' to create an initial ram disk, just like a native system e.g. - # depmod 2.6.12.6-xen - # mkinitrd -v -f --with=aacraid --with=sd_mod --with=scsi_mod initrd-2.6.12.6-xen.img 2.6.12.6-xen + # depmod 2.6.16-xen + # mkinitrd -v -f --with=aacraid --with=sd_mod --with=scsi_mod initrd-2.6.16-xen.img 2.6.16-xen