aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-11-16 14:16:36 +0000
committerKeir Fraser <keir@xen.org>2010-11-16 14:16:36 +0000
commit106f2288c2a71e4f6438d5e2571a78720e659d34 (patch)
tree085fb5fd0943b5fd21d2bbdfbebf622eb0ee8362
parent561e9179370c6927160eb797e1dccc5351d13eb3 (diff)
downloadxen-106f2288c2a71e4f6438d5e2571a78720e659d34.tar.gz
xen-106f2288c2a71e4f6438d5e2571a78720e659d34.tar.bz2
xen-106f2288c2a71e4f6438d5e2571a78720e659d34.zip
x86_64: Make 32-bit-hypercall translate area per-vcpu.
This is a prerequisite for allowing guest descheduling within a hypercall. Signed-off-by: Keir Fraser <keir@xen.org>
-rw-r--r--xen/arch/x86/domain.c9
-rw-r--r--xen/arch/x86/hvm/hvm.c15
-rw-r--r--xen/arch/x86/smpboot.c9
-rw-r--r--xen/arch/x86/x86_64/mm.c31
-rw-r--r--xen/include/asm-x86/domain.h4
-rw-r--r--xen/include/asm-x86/x86_64/uaccess.h9
6 files changed, 47 insertions, 30 deletions
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 6cdb6d85c6..13ff475555 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -214,11 +214,19 @@ static int setup_compat_l4(struct vcpu *v)
{
struct page_info *pg;
l4_pgentry_t *l4tab;
+ int rc;
pg = alloc_domheap_page(NULL, MEMF_node(vcpu_to_node(v)));
if ( pg == NULL )
return -ENOMEM;
+ rc = setup_compat_arg_xlat(v);
+ if ( rc )
+ {
+ free_domheap_page(pg);
+ return rc;
+ }
+
/* This page needs to look like a pagetable so that it can be shadowed */
pg->u.inuse.type_info = PGT_l4_page_table|PGT_validated|1;
@@ -239,6 +247,7 @@ static int setup_compat_l4(struct vcpu *v)
static void release_compat_l4(struct vcpu *v)
{
+ free_compat_arg_xlat(v);
free_domheap_page(pagetable_get_page(v->arch.guest_table));
v->arch.guest_table = pagetable_null();
v->arch.guest_table_user = pagetable_null();
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ba0481a133..6bd92ce61c 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -944,9 +944,15 @@ int hvm_vcpu_initialise(struct vcpu *v)
spin_lock_init(&v->arch.hvm_vcpu.tm_lock);
INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
- rc = hvm_vcpu_cacheattr_init(v);
+#ifdef CONFIG_COMPAT
+ rc = setup_compat_arg_xlat(v);
if ( rc != 0 )
goto fail3;
+#endif
+
+ rc = hvm_vcpu_cacheattr_init(v);
+ if ( rc != 0 )
+ goto fail4;
tasklet_init(&v->arch.hvm_vcpu.assert_evtchn_irq_tasklet,
(void(*)(unsigned long))hvm_assert_evtchn_irq,
@@ -971,6 +977,10 @@ int hvm_vcpu_initialise(struct vcpu *v)
return 0;
+ fail4:
+#ifdef CONFIG_COMPAT
+ free_compat_arg_xlat(v);
+#endif
fail3:
hvm_funcs.vcpu_destroy(v);
fail2:
@@ -981,6 +991,9 @@ int hvm_vcpu_initialise(struct vcpu *v)
void hvm_vcpu_destroy(struct vcpu *v)
{
+#ifdef CONFIG_COMPAT
+ free_compat_arg_xlat(v);
+#endif
tasklet_kill(&v->arch.hvm_vcpu.assert_evtchn_irq_tasklet);
hvm_vcpu_cacheattr_destroy(v);
vlapic_destroy(v);
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 365d70a4c4..90b4bfb56c 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -627,10 +627,6 @@ static void cpu_smpboot_free(unsigned int cpu)
xfree(idt_tables[cpu]);
idt_tables[cpu] = NULL;
-#ifdef __x86_64__
- free_compat_arg_xlat(cpu);
-#endif
-
order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
#ifdef __x86_64__
if ( per_cpu(compat_gdt_table, cpu) )
@@ -690,11 +686,6 @@ static int cpu_smpboot_alloc(unsigned int cpu)
BUILD_BUG_ON(NR_CPUS > 0x10000);
gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
-#ifdef __x86_64__
- if ( setup_compat_arg_xlat(cpu, cpu_to_node[cpu]) )
- goto oom;
-#endif
-
idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES);
if ( idt_tables[cpu] == NULL )
goto oom;
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index 883d23fa84..1de4e8b03d 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -47,8 +47,6 @@ unsigned int __read_mostly pfn_pdx_hole_shift = 0;
unsigned int __read_mostly m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START;
-DEFINE_PER_CPU_READ_MOSTLY(void *, compat_arg_xlat);
-
/* Top-level master (and idle-domain) page directory. */
l4_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
idle_pg_table[L4_PAGETABLE_ENTRIES];
@@ -819,25 +817,30 @@ void __init zap_low_mappings(void)
0x10, __PAGE_HYPERVISOR);
}
-int __cpuinit setup_compat_arg_xlat(unsigned int cpu, int node)
+void *compat_arg_xlat_virt_base(void)
+{
+ return current->arch.compat_arg_xlat;
+}
+
+int setup_compat_arg_xlat(struct vcpu *v)
{
unsigned int order = get_order_from_bytes(COMPAT_ARG_XLAT_SIZE);
- unsigned int memflags = node != NUMA_NO_NODE ? MEMF_node(node) : 0;
struct page_info *pg;
- BUG_ON((PAGE_SIZE << order) != COMPAT_ARG_XLAT_SIZE);
+ pg = alloc_domheap_pages(NULL, order, 0);
+ if ( pg == NULL )
+ return -ENOMEM;
- pg = alloc_domheap_pages(NULL, order, memflags);
- per_cpu(compat_arg_xlat, cpu) = pg ? page_to_virt(pg) : NULL;
- return pg ? 0 : -ENOMEM;
+ v->arch.compat_arg_xlat = page_to_virt(pg);
+ return 0;
}
-void __cpuinit free_compat_arg_xlat(unsigned int cpu)
+void free_compat_arg_xlat(struct vcpu *v)
{
unsigned int order = get_order_from_bytes(COMPAT_ARG_XLAT_SIZE);
- if ( per_cpu(compat_arg_xlat, cpu) != NULL )
- free_domheap_pages(virt_to_page(per_cpu(compat_arg_xlat, cpu)), order);
- per_cpu(compat_arg_xlat, cpu) = NULL;
+ if ( v->arch.compat_arg_xlat != NULL )
+ free_domheap_pages(virt_to_page(v->arch.compat_arg_xlat), order);
+ v->arch.compat_arg_xlat = NULL;
}
void cleanup_frame_table(struct mem_hotadd_info *info)
@@ -1009,10 +1012,6 @@ void __init subarch_init_memory(void)
share_xen_page_with_privileged_guests(page, XENSHARE_readonly);
}
}
-
- if ( setup_compat_arg_xlat(smp_processor_id(),
- cpu_to_node[0]) )
- panic("Could not setup argument translation area");
}
long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 6b4222abed..5ff0a06e98 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -436,6 +436,10 @@ struct arch_vcpu
/* A secondary copy of the vcpu time info. */
XEN_GUEST_HANDLE(vcpu_time_info_t) time_info_guest;
+#ifdef CONFIG_COMPAT
+ void *compat_arg_xlat;
+#endif
+
} __cacheline_aligned;
/* Shorthands to improve code legibility. */
diff --git a/xen/include/asm-x86/x86_64/uaccess.h b/xen/include/asm-x86/x86_64/uaccess.h
index c5cb386d2b..e35ce28e03 100644
--- a/xen/include/asm-x86/x86_64/uaccess.h
+++ b/xen/include/asm-x86/x86_64/uaccess.h
@@ -1,11 +1,12 @@
#ifndef __X86_64_UACCESS_H
#define __X86_64_UACCESS_H
-#define COMPAT_ARG_XLAT_VIRT_BASE this_cpu(compat_arg_xlat)
+#define COMPAT_ARG_XLAT_VIRT_BASE compat_arg_xlat_virt_base()
#define COMPAT_ARG_XLAT_SIZE (2*PAGE_SIZE)
-DECLARE_PER_CPU(void *, compat_arg_xlat);
-int setup_compat_arg_xlat(unsigned int cpu, int node);
-void free_compat_arg_xlat(unsigned int cpu);
+struct vcpu;
+void *compat_arg_xlat_virt_base(void);
+int setup_compat_arg_xlat(struct vcpu *v);
+void free_compat_arg_xlat(struct vcpu *v);
#define is_compat_arg_xlat_range(addr, size) ({ \
unsigned long __off; \
__off = (unsigned long)(addr) - (unsigned long)COMPAT_ARG_XLAT_VIRT_BASE; \