WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Merged.

# HG changeset patch
# User emellor@xxxxxxxxxxxxxxxxxxxxxx
# Node ID 8f722ac17efa4ba84eb6c678c7f33dab82fceb3e
# Parent  1577043d8e362633f94b30e3c267aaeaec71be88
# Parent  bddcfe70fbef16ff1d2391c41943853245627c4a
Merged.

diff -r 1577043d8e36 -r 8f722ac17efa 
linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c   Thu Mar 23 16:27:48 2006
+++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c   Thu Mar 23 16:37:37 2006
@@ -32,13 +32,13 @@
 #endif
 
 static int direct_remap_area_pte_fn(pte_t *pte, 
-                                   struct page *pte_page,
+                                   struct page *pmd_page,
                                    unsigned long address, 
                                    void *data)
 {
        mmu_update_t **v = (mmu_update_t **)data;
 
-       (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pte_page)) <<
+       (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
                     PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
        (*v)++;
 
@@ -67,9 +67,9 @@
        for (i = 0; i < size; i += PAGE_SIZE) {
                if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) {
                        /* Fill in the PTE pointers. */
-                       rc = generic_page_range(mm, start_address, 
-                                               address - start_address,
-                                               direct_remap_area_pte_fn, &w);
+                       rc = apply_to_page_range(mm, start_address, 
+                                                address - start_address,
+                                                direct_remap_area_pte_fn, &w);
                        if (rc)
                                goto out;
                        w = u;
@@ -93,8 +93,9 @@
 
        if (v != u) {
                /* get the ptep's filled in */
-               rc = generic_page_range(mm, start_address, address - 
start_address,
-                                  direct_remap_area_pte_fn, &w);
+               rc = apply_to_page_range(mm, start_address,
+                                        address - start_address,
+                                        direct_remap_area_pte_fn, &w);
                if (rc)
                        goto out;
                rc = -EFAULT;
@@ -142,11 +143,11 @@
 EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
 
 static int lookup_pte_fn(
-       pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
+       pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
 {
        uint64_t *ptep = (uint64_t *)data;
        if (ptep)
-               *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pte_page)) <<
+               *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) <<
                         PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
        return 0;
 }
@@ -155,13 +156,14 @@
                           unsigned long address,
                           uint64_t *ptep)
 {
-       return generic_page_range(mm, address, PAGE_SIZE, lookup_pte_fn, ptep);
+       return apply_to_page_range(mm, address, PAGE_SIZE,
+                                  lookup_pte_fn, ptep);
 }
 
 EXPORT_SYMBOL(create_lookup_pte_addr);
 
 static int noop_fn(
-       pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
+       pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
 {
        return 0;
 }
@@ -170,7 +172,7 @@
                    unsigned long address,
                    unsigned long size)
 {
-       return generic_page_range(mm, address, size, noop_fn, NULL);
+       return apply_to_page_range(mm, address, size, noop_fn, NULL);
 } 
 
 EXPORT_SYMBOL(touch_pte_range);
diff -r 1577043d8e36 -r 8f722ac17efa 
linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c        Thu Mar 23 
16:27:48 2006
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c        Thu Mar 23 
16:37:37 2006
@@ -114,8 +114,6 @@
        irq_exit();
 }
 
-int __initdata unsync_tsc_on_multicluster;
-
 /*
  * This interrupt should _never_ happen with our APIC/SMP architecture
  */
diff -r 1577043d8e36 -r 8f722ac17efa 
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Thu Mar 23 
16:27:48 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Thu Mar 23 
16:37:37 2006
@@ -517,7 +517,7 @@
 }
 
 static int dealloc_pte_fn(
-       pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
+       pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
 {
        unsigned long mfn = pte_mfn(*pte);
        int ret;
@@ -547,8 +547,8 @@
        scrub_pages(vstart, 1 << order);
 
        balloon_lock(flags);
-       ret = generic_page_range(
-               &init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL);
+       ret = apply_to_page_range(&init_mm, vstart,
+                                 PAGE_SIZE << order, dealloc_pte_fn, NULL);
        BUG_ON(ret);
        current_pages -= 1UL << order;
        totalram_pages = current_pages;
diff -r 1577043d8e36 -r 8f722ac17efa 
linux-2.6-xen-sparse/drivers/xen/core/gnttab.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c    Thu Mar 23 16:27:48 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c    Thu Mar 23 16:37:37 2006
@@ -360,7 +360,7 @@
 }
 
 #ifndef __ia64__
-static int map_pte_fn(pte_t *pte, struct page *pte_page,
+static int map_pte_fn(pte_t *pte, struct page *pmd_page,
                      unsigned long addr, void *data)
 {
        unsigned long **frames = (unsigned long **)data;
@@ -370,7 +370,7 @@
        return 0;
 }
 
-static int unmap_pte_fn(pte_t *pte, struct page *pte_page,
+static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
                      unsigned long addr, void *data)
 {
 
@@ -384,6 +384,7 @@
 {
        gnttab_setup_table_t setup;
        unsigned long frames[NR_GRANT_FRAMES];
+       int rc;
 #ifndef __ia64__
        void *pframes = frames;
        struct vm_struct *area;
@@ -393,8 +394,8 @@
        setup.nr_frames  = NR_GRANT_FRAMES;
        setup.frame_list = frames;
 
-       BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1));
-       BUG_ON(setup.status != 0);
+       rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+       BUG_ON(rc || setup.status);
 
 #ifndef __ia64__
        if (shared == NULL) {
@@ -402,9 +403,10 @@
                BUG_ON(area == NULL);
                shared = area->addr;
        }
-       BUG_ON(generic_page_range(&init_mm, (unsigned long)shared,
-                                 PAGE_SIZE * NR_GRANT_FRAMES,
-                                 map_pte_fn, &pframes));
+       rc = apply_to_page_range(&init_mm, (unsigned long)shared,
+                                PAGE_SIZE * NR_GRANT_FRAMES,
+                                map_pte_fn, &pframes);
+       BUG_ON(rc);
 #else
        shared = __va(frames[0] << PAGE_SHIFT);
        printk("grant table at %p\n", shared);
@@ -418,9 +420,9 @@
 {
 
 #ifndef __ia64__
-       generic_page_range(&init_mm, (unsigned long)shared,
-                          PAGE_SIZE * NR_GRANT_FRAMES,
-                          unmap_pte_fn, NULL);
+       apply_to_page_range(&init_mm, (unsigned long)shared,
+                           PAGE_SIZE * NR_GRANT_FRAMES,
+                           unmap_pte_fn, NULL);
 #endif
 
        return 0;
diff -r 1577043d8e36 -r 8f722ac17efa linux-2.6-xen-sparse/drivers/xen/util.c
--- a/linux-2.6-xen-sparse/drivers/xen/util.c   Thu Mar 23 16:27:48 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/util.c   Thu Mar 23 16:37:37 2006
@@ -6,9 +6,9 @@
 #include <asm/uaccess.h>
 #include <xen/driver_util.h>
 
-static int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
+static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
 {
-       /* generic_page_range() does all the hard work. */
+       /* apply_to_page_range() does all the hard work. */
        return 0;
 }
 
@@ -24,8 +24,8 @@
         * This ensures that page tables are constructed for this region
         * of kernel virtual address space and mapped into init_mm.
         */
-       if (generic_page_range(&init_mm, (unsigned long)area->addr,
-                              area->size, f, NULL)) {
+       if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
+                               area->size, f, NULL)) {
                free_vm_area(area);
                return NULL;
        }
diff -r 1577043d8e36 -r 8f722ac17efa linux-2.6-xen-sparse/include/linux/mm.h
--- a/linux-2.6-xen-sparse/include/linux/mm.h   Thu Mar 23 16:27:48 2006
+++ b/linux-2.6-xen-sparse/include/linux/mm.h   Thu Mar 23 16:37:37 2006
@@ -1020,10 +1020,10 @@
 #define FOLL_ANON      0x08    /* give ZERO_PAGE if no pgtable */
 
 #ifdef CONFIG_XEN
-typedef int (*pte_fn_t)(pte_t *pte, struct page *pte_page, unsigned long addr,
-                        void *data);
-extern int generic_page_range(struct mm_struct *mm, unsigned long address,
-                              unsigned long size, pte_fn_t fn, void *data);
+typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr,
+                       void *data);
+extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
+                              unsigned long size, pte_fn_t fn, void *data);
 #endif
 
 #ifdef CONFIG_PROC_FS
diff -r 1577043d8e36 -r 8f722ac17efa linux-2.6-xen-sparse/mm/memory.c
--- a/linux-2.6-xen-sparse/mm/memory.c  Thu Mar 23 16:27:48 2006
+++ b/linux-2.6-xen-sparse/mm/memory.c  Thu Mar 23 16:37:37 2006
@@ -1378,36 +1378,39 @@
 EXPORT_SYMBOL(remap_pfn_range);
 
 #ifdef CONFIG_XEN
-static inline int generic_pte_range(struct mm_struct *mm, pmd_t *pmd,
-                                   unsigned long addr, unsigned long end,
-                                   pte_fn_t fn, void *data)
+static inline int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
+                                    unsigned long addr, unsigned long end,
+                                    pte_fn_t fn, void *data)
 {
        pte_t *pte;
        int err;
-       struct page *pte_page;
+       struct page *pmd_page;
+       spinlock_t *ptl;
 
        pte = (mm == &init_mm) ?
                pte_alloc_kernel(pmd, addr) :
-               pte_alloc_map(mm, pmd, addr);
+               pte_alloc_map_lock(mm, pmd, addr, &ptl);
        if (!pte)
                return -ENOMEM;
 
-       pte_page = pmd_page(*pmd);
+       BUG_ON(pmd_huge(*pmd));
+
+       pmd_page = pmd_page(*pmd);
 
        do {
-               err = fn(pte, pte_page, addr, data);
+               err = fn(pte, pmd_page, addr, data);
                if (err)
                        break;
        } while (pte++, addr += PAGE_SIZE, addr != end);
 
        if (mm != &init_mm)
-               pte_unmap(pte-1);
+               pte_unmap_unlock(pte-1, ptl);
        return err;
 }
 
-static inline int generic_pmd_range(struct mm_struct *mm, pud_t *pud,
-                                   unsigned long addr, unsigned long end,
-                                   pte_fn_t fn, void *data)
+static inline int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
+                                    unsigned long addr, unsigned long end,
+                                    pte_fn_t fn, void *data)
 {
        pmd_t *pmd;
        unsigned long next;
@@ -1418,16 +1421,16 @@
                return -ENOMEM;
        do {
                next = pmd_addr_end(addr, end);
-               err = generic_pte_range(mm, pmd, addr, next, fn, data);
+               err = apply_to_pte_range(mm, pmd, addr, next, fn, data);
                if (err)
                        break;
        } while (pmd++, addr = next, addr != end);
        return err;
 }
 
-static inline int generic_pud_range(struct mm_struct *mm, pgd_t *pgd,
-                                   unsigned long addr, unsigned long end,
-                                   pte_fn_t fn, void *data)
+static inline int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd,
+                                    unsigned long addr, unsigned long end,
+                                    pte_fn_t fn, void *data)
 {
        pud_t *pud;
        unsigned long next;
@@ -1438,7 +1441,7 @@
                return -ENOMEM;
        do {
                next = pud_addr_end(addr, end);
-               err = generic_pmd_range(mm, pud, addr, next, fn, data);
+               err = apply_to_pmd_range(mm, pud, addr, next, fn, data);
                if (err)
                        break;
        } while (pud++, addr = next, addr != end);
@@ -1449,8 +1452,8 @@
  * Scan a region of virtual memory, filling in page tables as necessary
  * and calling a provided function on each leaf page table.
  */
-int generic_page_range(struct mm_struct *mm, unsigned long addr,
-                      unsigned long size, pte_fn_t fn, void *data)
+int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
+                       unsigned long size, pte_fn_t fn, void *data)
 {
        pgd_t *pgd;
        unsigned long next;
@@ -1461,12 +1464,13 @@
        pgd = pgd_offset(mm, addr);
        do {
                next = pgd_addr_end(addr, end);
-               err = generic_pud_range(mm, pgd, addr, next, fn, data);
+               err = apply_to_pud_range(mm, pgd, addr, next, fn, data);
                if (err)
                        break;
        } while (pgd++, addr = next, addr != end);
        return err;
 }
+EXPORT_SYMBOL_GPL(apply_to_page_range);
 #endif
 
 /*
diff -r 1577043d8e36 -r 8f722ac17efa xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c   Thu Mar 23 16:27:48 2006
+++ b/xen/arch/x86/dom0_ops.c   Thu Mar 23 16:37:37 2006
@@ -460,8 +460,7 @@
 
     if ( hvm_guest(v) )
     {
-        hvm_store_cpu_guest_regs(v, &c->user_regs);
-        hvm_store_cpu_guest_ctrl_regs(v, c->ctrlreg);
+        hvm_store_cpu_guest_regs(v, &c->user_regs, c->ctrlreg);
     }
     else
     {
diff -r 1577043d8e36 -r 8f722ac17efa xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Thu Mar 23 16:27:48 2006
+++ b/xen/arch/x86/hvm/platform.c       Thu Mar 23 16:37:37 2006
@@ -773,7 +773,7 @@
     mmio_opp = &v->arch.hvm_vcpu.mmio_op;
 
     regs = mmio_opp->inst_decoder_regs;
-    hvm_store_cpu_guest_regs(v, regs);
+    hvm_store_cpu_guest_regs(v, regs, NULL);
 
     if ((inst_len = hvm_instruction_length(v)) <= 0) {
         printf("handle_mmio: failed to get instruction length\n");
diff -r 1577043d8e36 -r 8f722ac17efa xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Thu Mar 23 16:27:48 2006
+++ b/xen/arch/x86/hvm/svm/svm.c        Thu Mar 23 16:37:37 2006
@@ -201,31 +201,41 @@
 }
 
 static void svm_store_cpu_guest_regs(
-    struct vcpu *v, struct cpu_user_regs *regs)
+    struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
+    if ( regs != NULL )
+    {
 #if defined (__x86_64__)
-    regs->rip    = vmcb->rip;
-    regs->rsp    = vmcb->rsp;
-    regs->rflags = vmcb->rflags;
-    regs->cs     = vmcb->cs.sel;
-    regs->ds     = vmcb->ds.sel;
-    regs->es     = vmcb->es.sel;
-    regs->ss     = vmcb->ss.sel;
-    regs->gs     = vmcb->gs.sel;
-    regs->fs     = vmcb->fs.sel;
+        regs->rip    = vmcb->rip;
+        regs->rsp    = vmcb->rsp;
+        regs->rflags = vmcb->rflags;
+        regs->cs     = vmcb->cs.sel;
+        regs->ds     = vmcb->ds.sel;
+        regs->es     = vmcb->es.sel;
+        regs->ss     = vmcb->ss.sel;
+        regs->gs     = vmcb->gs.sel;
+        regs->fs     = vmcb->fs.sel;
 #elif defined (__i386__)
-    regs->eip    = vmcb->rip;
-    regs->esp    = vmcb->rsp;
-    regs->eflags = vmcb->rflags;
-    regs->cs     = vmcb->cs.sel;
-    regs->ds     = vmcb->ds.sel;
-    regs->es     = vmcb->es.sel;
-    regs->ss     = vmcb->ss.sel;
-    regs->gs     = vmcb->gs.sel;
-    regs->fs     = vmcb->fs.sel;
+        regs->eip    = vmcb->rip;
+        regs->esp    = vmcb->rsp;
+        regs->eflags = vmcb->rflags;
+        regs->cs     = vmcb->cs.sel;
+        regs->ds     = vmcb->ds.sel;
+        regs->es     = vmcb->es.sel;
+        regs->ss     = vmcb->ss.sel;
+        regs->gs     = vmcb->gs.sel;
+        regs->fs     = vmcb->fs.sel;
 #endif
+    }
+
+    if ( crs != NULL )
+    {
+        crs[0] = vmcb->cr0;
+        crs[3] = vmcb->cr3;
+        crs[4] = vmcb->cr4;
+    }
 }
 
 static void svm_load_cpu_guest_regs(
@@ -372,15 +382,6 @@
     return 1;
 }
 
-void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    crs[0] = vmcb->cr0;
-    crs[3] = vmcb->cr3;
-    crs[4] = vmcb->cr4;
-}
-
 void svm_modify_guest_state(struct vcpu *v)
 {
     svm_modify_vmcb(v, &v->arch.guest_context.user_regs);
@@ -448,7 +449,6 @@
     hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
     hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
 
-    hvm_funcs.store_cpu_guest_ctrl_regs = svm_store_cpu_guest_ctrl_regs;
     hvm_funcs.modify_guest_state = svm_modify_guest_state;
 
     hvm_funcs.realmode = svm_realmode;
diff -r 1577043d8e36 -r 8f722ac17efa xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Mar 23 16:27:48 2006
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Mar 23 16:37:37 2006
@@ -398,31 +398,81 @@
         migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor);
 }
 
-void vmx_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
-{
+struct vmx_store_cpu_guest_regs_callback_info {
+    struct vcpu *v;
+    struct cpu_user_regs *regs;
+    unsigned long *crs;
+};
+
+static void vmx_store_cpu_guest_regs(
+    struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs);
+
+static void vmx_store_cpu_guest_regs_callback(void *data)
+{
+    struct vmx_store_cpu_guest_regs_callback_info *info = data;
+    vmx_store_cpu_guest_regs(info->v, info->regs, info->crs);
+}
+
+static void vmx_store_cpu_guest_regs(
+    struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
+{
+    if ( v != current )
+    {
+        /* Non-current VCPUs must be paused to get a register snapshot. */
+        ASSERT(atomic_read(&v->pausecnt) != 0);
+
+        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 = {
+                .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,
+                             &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 ( regs != NULL )
+    {
 #if defined (__x86_64__)
-    __vmread(GUEST_RFLAGS, &regs->rflags);
-    __vmread(GUEST_SS_SELECTOR, &regs->ss);
-    __vmread(GUEST_CS_SELECTOR, &regs->cs);
-    __vmread(GUEST_DS_SELECTOR, &regs->ds);
-    __vmread(GUEST_ES_SELECTOR, &regs->es);
-    __vmread(GUEST_GS_SELECTOR, &regs->gs);
-    __vmread(GUEST_FS_SELECTOR, &regs->fs);
-    __vmread(GUEST_RIP, &regs->rip);
-    __vmread(GUEST_RSP, &regs->rsp);
+        __vmread(GUEST_RFLAGS, &regs->rflags);
+        __vmread(GUEST_SS_SELECTOR, &regs->ss);
+        __vmread(GUEST_CS_SELECTOR, &regs->cs);
+        __vmread(GUEST_DS_SELECTOR, &regs->ds);
+        __vmread(GUEST_ES_SELECTOR, &regs->es);
+        __vmread(GUEST_GS_SELECTOR, &regs->gs);
+        __vmread(GUEST_FS_SELECTOR, &regs->fs);
+        __vmread(GUEST_RIP, &regs->rip);
+        __vmread(GUEST_RSP, &regs->rsp);
 #elif defined (__i386__)
-    __vmread(GUEST_RFLAGS, &regs->eflags);
-    __vmread(GUEST_SS_SELECTOR, &regs->ss);
-    __vmread(GUEST_CS_SELECTOR, &regs->cs);
-    __vmread(GUEST_DS_SELECTOR, &regs->ds);
-    __vmread(GUEST_ES_SELECTOR, &regs->es);
-    __vmread(GUEST_GS_SELECTOR, &regs->gs);
-    __vmread(GUEST_FS_SELECTOR, &regs->fs);
-    __vmread(GUEST_RIP, &regs->eip);
-    __vmread(GUEST_RSP, &regs->esp);
-#else
-#error Unsupported architecture
+        __vmread(GUEST_RFLAGS, &regs->eflags);
+        __vmread(GUEST_SS_SELECTOR, &regs->ss);
+        __vmread(GUEST_CS_SELECTOR, &regs->cs);
+        __vmread(GUEST_DS_SELECTOR, &regs->ds);
+        __vmread(GUEST_ES_SELECTOR, &regs->es);
+        __vmread(GUEST_GS_SELECTOR, &regs->gs);
+        __vmread(GUEST_FS_SELECTOR, &regs->fs);
+        __vmread(GUEST_RIP, &regs->eip);
+        __vmread(GUEST_RSP, &regs->esp);
 #endif
+    }
+
+    if ( crs != NULL )
+    {
+        __vmread(CR0_READ_SHADOW, &crs[0]);
+        __vmread(GUEST_CR3, &crs[3]);
+        __vmread(CR4_READ_SHADOW, &crs[4]);
+    }
+
+    /* 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));
 }
 
 void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
@@ -454,13 +504,6 @@
 #else
 #error Unsupported architecture
 #endif
-}
-
-void vmx_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
-{
-    __vmread(CR0_READ_SHADOW, &crs[0]);
-    __vmread(GUEST_CR3, &crs[3]);
-    __vmread(CR4_READ_SHADOW, &crs[4]);
 }
 
 void vmx_modify_guest_state(struct vcpu *v)
@@ -616,7 +659,6 @@
     hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs;
     hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs;
 
-    hvm_funcs.store_cpu_guest_ctrl_regs = vmx_store_cpu_guest_ctrl_regs;
     hvm_funcs.modify_guest_state = vmx_modify_guest_state;
 
     hvm_funcs.realmode = vmx_realmode;
diff -r 1577043d8e36 -r 8f722ac17efa xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Thu Mar 23 16:27:48 2006
+++ b/xen/arch/x86/x86_32/traps.c       Thu Mar 23 16:37:37 2006
@@ -27,8 +27,7 @@
     if ( hvm_guest(current) && guest_mode(regs) )
     {
         context = "hvm";
-        hvm_store_cpu_guest_regs(current, &fault_regs);
-        hvm_store_cpu_guest_ctrl_regs(current, fault_crs);
+        hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs);
     }
     else
     {
diff -r 1577043d8e36 -r 8f722ac17efa xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c       Thu Mar 23 16:27:48 2006
+++ b/xen/arch/x86/x86_64/traps.c       Thu Mar 23 16:37:37 2006
@@ -27,8 +27,7 @@
     if ( hvm_guest(current) && guest_mode(regs) )
     {
         context = "hvm";
-        hvm_store_cpu_guest_regs(current, &fault_regs);
-        hvm_store_cpu_guest_ctrl_regs(current, fault_crs);
+        hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs);
     }
     else
     {
diff -r 1577043d8e36 -r 8f722ac17efa xen/common/gdbstub.c
--- a/xen/common/gdbstub.c      Thu Mar 23 16:27:48 2006
+++ b/xen/common/gdbstub.c      Thu Mar 23 16:37:37 2006
@@ -562,6 +562,7 @@
     gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
     if ( gdb_ctx->serhnd != -1 )
         printk("GDB stub initialised.\n");
+    serial_start_sync(gdb_ctx->serhnd);
 }
 
 /*
diff -r 1577043d8e36 -r 8f722ac17efa xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Thu Mar 23 16:27:48 2006
+++ b/xen/drivers/char/ns16550.c        Thu Mar 23 16:37:37 2006
@@ -121,8 +121,11 @@
 
     while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) )
     {
-        serial_tx_interrupt(port, regs);
-        serial_rx_interrupt(port, regs);
+        char lsr = ns_read_reg(uart, LSR);
+        if ( lsr & LSR_THRE )
+            serial_tx_interrupt(port, regs);
+        if ( lsr & LSR_DR )
+            serial_rx_interrupt(port, regs);
     }
 }
 
diff -r 1577043d8e36 -r 8f722ac17efa xen/drivers/char/serial.c
--- a/xen/drivers/char/serial.c Thu Mar 23 16:27:48 2006
+++ b/xen/drivers/char/serial.c Thu Mar 23 16:37:37 2006
@@ -7,6 +7,7 @@
  */
 
 #include <xen/config.h>
+#include <xen/delay.h>
 #include <xen/init.h>
 #include <xen/irq.h>
 #include <xen/keyhandler.h> 
@@ -15,8 +16,8 @@
 #include <xen/serial.h>
 
 static struct serial_port com[2] = {
-    { .lock = SPIN_LOCK_UNLOCKED }, 
-    { .lock = SPIN_LOCK_UNLOCKED }
+    { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }, 
+    { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }
 };
 
 void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
@@ -25,7 +26,7 @@
     serial_rx_fn fn = NULL;
     unsigned long flags;
 
-    spin_lock_irqsave(&port->lock, flags);
+    spin_lock_irqsave(&port->rx_lock, flags);
 
     if ( port->driver->getc(port, &c) )
     {
@@ -39,7 +40,7 @@
             port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufp++)] = c;            
     }
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->rx_lock, flags);
 
     if ( fn != NULL )
         (*fn)(c & 0x7f, regs);
@@ -50,7 +51,19 @@
     int i;
     unsigned long flags;
 
-    spin_lock_irqsave(&port->lock, flags);
+    local_irq_save(flags);
+
+    /*
+     * Avoid spinning for a long time: if there is a long-term lock holder
+     * then we know that they'll be stuffing bytes into the transmitter which
+     * will therefore not be empty for long.
+     */
+    while ( !spin_trylock(&port->tx_lock) )
+    {
+        if ( !port->driver->tx_empty(port) )
+            return;
+        cpu_relax();
+    }
 
     if ( port->driver->tx_empty(port) )
     {
@@ -63,7 +76,7 @@
         }
     }
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 static void __serial_putc(struct serial_port *port, char c)
@@ -117,7 +130,7 @@
     if ( (handle == -1) || !port->driver || !port->driver->putc )
         return;
 
-    spin_lock_irqsave(&port->lock, flags);
+    spin_lock_irqsave(&port->tx_lock, flags);
 
     if ( (c == '\n') && (handle & SERHND_COOKED) )
         __serial_putc(port, '\r');
@@ -129,7 +142,7 @@
 
     __serial_putc(port, c);
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 void serial_puts(int handle, const char *s)
@@ -141,7 +154,7 @@
     if ( (handle == -1) || !port->driver || !port->driver->putc )
         return;
 
-    spin_lock_irqsave(&port->lock, flags);
+    spin_lock_irqsave(&port->tx_lock, flags);
 
     while ( (c = *s++) != '\0' )
     {
@@ -156,7 +169,7 @@
         __serial_putc(port, c);
     }
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 char serial_getc(int handle)
@@ -168,27 +181,28 @@
     if ( (handle == -1) || !port->driver || !port->driver->getc )
         return '\0';
 
-    do {        
+    do {
         for ( ; ; )
         {
-            spin_lock_irqsave(&port->lock, flags);
+            spin_lock_irqsave(&port->rx_lock, flags);
             
             if ( port->rxbufp != port->rxbufc )
             {
                 c = port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufc++)];
-                spin_unlock_irqrestore(&port->lock, flags);
+                spin_unlock_irqrestore(&port->rx_lock, flags);
                 break;
             }
             
             if ( port->driver->getc(port, &c) )
             {
-                spin_unlock_irqrestore(&port->lock, flags);
+                spin_unlock_irqrestore(&port->rx_lock, flags);
                 break;
             }
 
-            spin_unlock_irqrestore(&port->lock, flags);
+            spin_unlock_irqrestore(&port->rx_lock, flags);
 
             cpu_relax();
+            udelay(100);
         }
     } while ( ((handle & SERHND_LO) &&  (c & 0x80)) ||
               ((handle & SERHND_HI) && !(c & 0x80)) );
@@ -241,7 +255,7 @@
     if ( handle == -1 )
         return;
 
-    spin_lock_irqsave(&port->lock, flags);
+    spin_lock_irqsave(&port->rx_lock, flags);
 
     if ( port->rx != NULL )
         goto fail;
@@ -265,11 +279,11 @@
         port->rx = fn;
     }
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->rx_lock, flags);
     return;
 
  fail:
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->rx_lock, flags);
     printk("ERROR: Conflicting receive handlers for COM%d\n", 
            handle & SERHND_IDX);
 }
@@ -277,8 +291,13 @@
 void serial_force_unlock(int handle)
 {
     struct serial_port *port = &com[handle & SERHND_IDX];
-    if ( handle != -1 )
-        port->lock = SPIN_LOCK_UNLOCKED;
+
+    if ( handle == -1 )
+        return;
+
+    port->rx_lock = SPIN_LOCK_UNLOCKED;
+    port->tx_lock = SPIN_LOCK_UNLOCKED;
+
     serial_start_sync(handle);
 }
 
@@ -290,7 +309,7 @@
     if ( handle == -1 )
         return;
     
-    spin_lock_irqsave(&port->lock, flags);
+    spin_lock_irqsave(&port->tx_lock, flags);
 
     if ( port->sync++ == 0 )
     {
@@ -303,7 +322,7 @@
         }
     }
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 void serial_end_sync(int handle)
@@ -314,11 +333,11 @@
     if ( handle == -1 )
         return;
     
-    spin_lock_irqsave(&port->lock, flags);
+    spin_lock_irqsave(&port->tx_lock, flags);
 
     port->sync--;
 
-    spin_unlock_irqrestore(&port->lock, flags);
+    spin_unlock_irqrestore(&port->tx_lock, flags);
 }
 
 int serial_tx_space(int handle)
diff -r 1577043d8e36 -r 8f722ac17efa xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Thu Mar 23 16:27:48 2006
+++ b/xen/include/asm-x86/hvm/hvm.h     Thu Mar 23 16:37:37 2006
@@ -41,12 +41,12 @@
     /*
      * Store and load guest state:
      * 1) load/store guest register state,
-     * 2) store guest control register state (used for panic dumps),
-     * 3) modify guest state (e.g., set debug flags).
+     * 2) modify guest state (e.g., set debug flags).
      */
-    void (*store_cpu_guest_regs)(struct vcpu *v, struct cpu_user_regs *r);
-    void (*load_cpu_guest_regs)(struct vcpu *v, struct cpu_user_regs *r);
-    void (*store_cpu_guest_ctrl_regs)(struct vcpu *v, unsigned long crs[8]);
+    void (*store_cpu_guest_regs)(
+        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);
 
     /*
@@ -93,21 +93,16 @@
 }
 
 static inline void
-hvm_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *r)
+hvm_store_cpu_guest_regs(
+    struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs)
 {
-    hvm_funcs.store_cpu_guest_regs(v, r);
+    hvm_funcs.store_cpu_guest_regs(v, r, crs);
 }
 
 static inline void
 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_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
-{
-    hvm_funcs.store_cpu_guest_ctrl_regs(v, crs);
 }
 
 static inline void
diff -r 1577043d8e36 -r 8f722ac17efa xen/include/xen/serial.h
--- a/xen/include/xen/serial.h  Thu Mar 23 16:27:48 2006
+++ b/xen/include/xen/serial.h  Thu Mar 23 16:37:37 2006
@@ -42,7 +42,7 @@
     char                rxbuf[SERIAL_RXBUFSZ];
     unsigned int        rxbufp, rxbufc;
     /* Serial I/O is concurrency-safe. */
-    spinlock_t          lock;
+    spinlock_t          rx_lock, tx_lock;
 };
 
 struct uart_driver {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>