# 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, ®s->rflags);
- __vmread(GUEST_SS_SELECTOR, ®s->ss);
- __vmread(GUEST_CS_SELECTOR, ®s->cs);
- __vmread(GUEST_DS_SELECTOR, ®s->ds);
- __vmread(GUEST_ES_SELECTOR, ®s->es);
- __vmread(GUEST_GS_SELECTOR, ®s->gs);
- __vmread(GUEST_FS_SELECTOR, ®s->fs);
- __vmread(GUEST_RIP, ®s->rip);
- __vmread(GUEST_RSP, ®s->rsp);
+ __vmread(GUEST_RFLAGS, ®s->rflags);
+ __vmread(GUEST_SS_SELECTOR, ®s->ss);
+ __vmread(GUEST_CS_SELECTOR, ®s->cs);
+ __vmread(GUEST_DS_SELECTOR, ®s->ds);
+ __vmread(GUEST_ES_SELECTOR, ®s->es);
+ __vmread(GUEST_GS_SELECTOR, ®s->gs);
+ __vmread(GUEST_FS_SELECTOR, ®s->fs);
+ __vmread(GUEST_RIP, ®s->rip);
+ __vmread(GUEST_RSP, ®s->rsp);
#elif defined (__i386__)
- __vmread(GUEST_RFLAGS, ®s->eflags);
- __vmread(GUEST_SS_SELECTOR, ®s->ss);
- __vmread(GUEST_CS_SELECTOR, ®s->cs);
- __vmread(GUEST_DS_SELECTOR, ®s->ds);
- __vmread(GUEST_ES_SELECTOR, ®s->es);
- __vmread(GUEST_GS_SELECTOR, ®s->gs);
- __vmread(GUEST_FS_SELECTOR, ®s->fs);
- __vmread(GUEST_RIP, ®s->eip);
- __vmread(GUEST_RSP, ®s->esp);
-#else
-#error Unsupported architecture
+ __vmread(GUEST_RFLAGS, ®s->eflags);
+ __vmread(GUEST_SS_SELECTOR, ®s->ss);
+ __vmread(GUEST_CS_SELECTOR, ®s->cs);
+ __vmread(GUEST_DS_SELECTOR, ®s->ds);
+ __vmread(GUEST_ES_SELECTOR, ®s->es);
+ __vmread(GUEST_GS_SELECTOR, ®s->gs);
+ __vmread(GUEST_FS_SELECTOR, ®s->fs);
+ __vmread(GUEST_RIP, ®s->eip);
+ __vmread(GUEST_RSP, ®s->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
|