mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Merged.
This commit is contained in:
commit
22f9491cad
18 files changed
+222
-159
No files matched your search
@@ -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 @@ static int __direct_remap_pfn_range(struct mm_struct *mm,
|
||||
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 @@ static int __direct_remap_pfn_range(struct mm_struct *mm,
|
||||
|
||||
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 @@ int direct_kernel_remap_pfn_range(unsigned long address,
|
||||
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 @@ int create_lookup_pte_addr(struct mm_struct *mm,
|
||||
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 @@ int touch_pte_range(struct mm_struct *mm,
|
||||
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);
|
||||
|
||||
@@ -114,8 +114,6 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
int __initdata unsync_tsc_on_multicluster;
|
||||
|
||||
/*
|
||||
* This interrupt should _never_ happen with our APIC/SMP architecture
|
||||
*/
|
||||
|
||||
@@ -517,7 +517,7 @@ void balloon_update_driver_allowance(long delta)
|
||||
}
|
||||
|
||||
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 @@ struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
|
||||
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;
|
||||
|
||||
@@ -360,7 +360,7 @@ gnttab_request_free_callback(struct gnttab_free_callback *callback,
|
||||
}
|
||||
|
||||
#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 @@ static int map_pte_fn(pte_t *pte, struct page *pte_page,
|
||||
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_resume(void)
|
||||
{
|
||||
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 @@ gnttab_resume(void)
|
||||
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 @@ gnttab_resume(void)
|
||||
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 @@ gnttab_suspend(void)
|
||||
{
|
||||
|
||||
#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;
|
||||
|
||||
@@ -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 @@ struct vm_struct *alloc_vm_area(unsigned long size)
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1020,10 +1020,10 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
|
||||
#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
|
||||
|
||||
@@ -1378,36 +1378,39 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
|
||||
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 @@ static inline int generic_pmd_range(struct mm_struct *mm, pud_t *pud,
|
||||
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 @@ static inline int generic_pud_range(struct mm_struct *mm, pgd_t *pgd,
|
||||
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 @@ static inline int generic_pud_range(struct mm_struct *mm, pgd_t *pgd,
|
||||
* 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 @@ int generic_page_range(struct mm_struct *mm, unsigned long addr,
|
||||
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
|
||||
|
||||
/*
|
||||
|
||||
@@ -460,8 +460,7 @@ void arch_getdomaininfo_ctxt(
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
@@ -773,7 +773,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
|
||||
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");
|
||||
|
||||
+29
-29
@@ -201,31 +201,41 @@ int svm_initialize_guest_resources(struct vcpu *v)
|
||||
}
|
||||
|
||||
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 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
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 @@ 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.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;
|
||||
|
||||
+71
-29
@@ -398,31 +398,81 @@ void vmx_migrate_timers(struct vcpu *v)
|
||||
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)
|
||||
@@ -456,13 +506,6 @@ void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
|
||||
#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)
|
||||
{
|
||||
modify_vmcs(&v->arch.hvm_vmx, &v->arch.guest_context.user_regs);
|
||||
@@ -616,7 +659,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.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;
|
||||
|
||||
@@ -27,8 +27,7 @@ void show_registers(struct cpu_user_regs *regs)
|
||||
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
|
||||
{
|
||||
|
||||
@@ -27,8 +27,7 @@ void show_registers(struct cpu_user_regs *regs)
|
||||
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
|
||||
{
|
||||
|
||||
@@ -562,6 +562,7 @@ initialise_gdb(void)
|
||||
gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
|
||||
if ( gdb_ctx->serhnd != -1 )
|
||||
printk("GDB stub initialised.\n");
|
||||
serial_start_sync(gdb_ctx->serhnd);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -121,8 +121,11 @@ static void ns16550_interrupt(
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-24
@@ -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 @@ void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
|
||||
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 @@ void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
|
||||
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 @@ void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
|
||||
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 @@ void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ void serial_putc(int handle, char c)
|
||||
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 @@ void serial_putc(int handle, char c)
|
||||
|
||||
__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 @@ void serial_puts(int handle, const char *s)
|
||||
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 @@ void serial_puts(int handle, const char *s)
|
||||
__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 @@ char serial_getc(int handle)
|
||||
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 @@ void serial_set_rx_handler(int handle, serial_rx_fn fn)
|
||||
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 @@ void serial_set_rx_handler(int handle, serial_rx_fn fn)
|
||||
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_set_rx_handler(int handle, serial_rx_fn fn)
|
||||
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 @@ void serial_start_sync(int handle)
|
||||
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 @@ void serial_start_sync(int handle)
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
spin_unlock_irqrestore(&port->tx_lock, flags);
|
||||
}
|
||||
|
||||
void serial_end_sync(int handle)
|
||||
@@ -314,11 +333,11 @@ void serial_end_sync(int handle)
|
||||
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)
|
||||
|
||||
@@ -41,12 +41,12 @@ struct hvm_function_table {
|
||||
/*
|
||||
* 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,9 +93,10 @@ hvm_relinquish_guest_resources(struct domain *d)
|
||||
}
|
||||
|
||||
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
|
||||
@@ -104,12 +105,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_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
|
||||
{
|
||||
hvm_funcs.store_cpu_guest_ctrl_regs(v, crs);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hvm_modify_guest_state(struct vcpu *v)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ struct serial_port {
|
||||
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 {
|
||||
|
||||