Skip to content

Commit

Permalink
Merge branch 'upstream/pvhvm' into upstream/xen
Browse files Browse the repository at this point in the history
* upstream/pvhvm:
  Introduce CONFIG_XEN_PVHVM compile option
  blkfront: do not create a PV cdrom device if xen_hvm_guest
  support multiple .discard.* sections to avoid section type conflicts
  xen/pvhvm: fix build problem when !CONFIG_XEN
  xenfs: enable for HVM domains too
  x86: Call HVMOP_pagetable_dying on exit_mmap.
  x86: Unplug emulated disks and nics.
  x86: Use xen_vcpuop_clockevent, xen_clocksource and xen wallclock.
  xen: Fix find_unbound_irq in presence of ioapic irqs.
  xen: Add suspend/resume support for PV on HVM guests.
  xen: Xen PCI platform device driver.
  x86/xen: event channels delivery on HVM.
  x86: early PV on HVM features initialization.
  xen: Add support for HVM hypercalls.

Conflicts:
	arch/x86/xen/enlighten.c
	arch/x86/xen/time.c
  • Loading branch information
Jeremy Fitzhardinge committed Aug 4, 2010
2 parents a70ce4b + ca65f9f commit ca50a5f
Show file tree
Hide file tree
Showing 39 changed files with 1,156 additions and 61 deletions.
11 changes: 11 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ parameter is applicable:
More X86-64 boot options can be found in
Documentation/x86/x86_64/boot-options.txt .
X86 Either 32bit or 64bit x86 (same as X86-32+X86-64)
XEN Xen support is enabled

In addition, the following text indicates that the option:

Expand Down Expand Up @@ -2879,6 +2880,16 @@ and is between 256 and 4096 characters. It is defined in the file
xd= [HW,XT] Original XT pre-IDE (RLL encoded) disks.
xd_geo= See header of drivers/block/xd.c.

xen_emul_unplug= [HW,X86,XEN]
Unplug Xen emulated devices
Format: [unplug0,][unplug1]
ide-disks -- unplug primary master IDE devices
aux-ide-disks -- unplug non-primary-master IDE devices
nics -- unplug network devices
all -- unplug all emulated devices (NICs and IDE disks)
ignore -- continue loading the Xen platform PCI driver even
if the version check failed

xirc2ps_cs= [NET,PCMCIA]
Format:
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/hypervisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ extern const struct hypervisor_x86 *x86_hyper;
/* Recognized hypervisors */
extern const struct hypervisor_x86 x86_hyper_vmware;
extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
extern const struct hypervisor_x86 x86_hyper_xen_hvm;

#endif
3 changes: 3 additions & 0 deletions arch/x86/include/asm/irq_vectors.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@
*/
#define MCE_SELF_VECTOR 0xeb

/* Xen vector callback to receive events in a HVM domain */
#define XEN_HVM_EVTCHN_CALLBACK 0xe9

#define NR_VECTORS 256

#define FPU_IRQ 13
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void *extend_brk(size_t size, size_t align);
* executable.)
*/
#define RESERVE_BRK(name,sz) \
static void __section(.discard) __used \
static void __section(.discard.text) __used \
__brk_reservation_fn_##name##__(void) { \
asm volatile ( \
".pushsection .brk_reservation,\"aw\",@nobits;" \
Expand Down
6 changes: 6 additions & 0 deletions arch/x86/include/asm/xen/hypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,12 @@ HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
return _hypercall2(int, nmi_op, op, arg);
}

static inline unsigned long __must_check
HYPERVISOR_hvm_op(int op, void *arg)
{
return _hypercall2(unsigned long, hvm_op, op, arg);
}

static inline void
MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
{
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/cpu/hypervisor.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
{
&x86_hyper_vmware,
&x86_hyper_ms_hyperv,
#ifdef CONFIG_XEN_PVHVM
&x86_hyper_xen_hvm,
#endif
};

const struct hypervisor_x86 *x86_hyper;
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,9 @@ ENTRY(xen_failsafe_callback)
.previous
ENDPROC(xen_failsafe_callback)

BUILD_INTERRUPT3(xen_hvm_callback_vector, XEN_HVM_EVTCHN_CALLBACK,
xen_evtchn_do_upcall)

#endif /* CONFIG_XEN */

#ifdef CONFIG_FUNCTION_TRACER
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,9 @@ ENTRY(xen_failsafe_callback)
CFI_ENDPROC
END(xen_failsafe_callback)

apicinterrupt XEN_HVM_EVTCHN_CALLBACK \
xen_hvm_callback_vector xen_evtchn_do_upcall

#endif /* CONFIG_XEN */

/*
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/xen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ config XEN
kernel to boot in a paravirtualized environment under the
Xen hypervisor.

config XEN_PVHVM
def_bool y
depends on XEN
depends on X86_LOCAL_APIC

config XEN_MAX_DOMAIN_MEMORY
int "Maximum allowed size of a domain in gigabytes"
default 8 if X86_32
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/xen/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CFLAGS_mmu.o := $(nostackp)

obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
time.o xen-asm.o xen-asm_$(BITS).o \
grant-table.o suspend.o
grant-table.o suspend.o platform-pci-unplug.o

obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
Expand Down
158 changes: 146 additions & 12 deletions arch/x86/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
*/

#include <linux/cpu.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp.h>
Expand All @@ -35,8 +36,10 @@
#include <xen/interface/version.h>
#include <xen/interface/physdev.h>
#include <xen/interface/vcpu.h>
#include <xen/interface/memory.h>
#include <xen/features.h>
#include <xen/page.h>
#include <xen/hvm.h>
#include <xen/hvc-console.h>

#include <asm/paravirt.h>
Expand All @@ -55,7 +58,9 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/reboot.h>
#include <asm/setup.h>
#include <asm/stackprotector.h>
#include <asm/hypervisor.h>

#include "xen-ops.h"
#include "mmu.h"
Expand All @@ -76,6 +81,10 @@ struct shared_info xen_dummy_shared_info;

void *xen_initial_gdt;

RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
__read_mostly int xen_have_vector_callback;
EXPORT_SYMBOL_GPL(xen_have_vector_callback);

/*
* Point at some empty memory to start with. We map the real shared_info
* page as soon as fixmap is up and running.
Expand Down Expand Up @@ -938,10 +947,6 @@ static const struct pv_init_ops xen_init_ops __initdata = {
.patch = xen_patch,
};

static const struct pv_time_ops xen_time_ops __initdata = {
.sched_clock = xen_clocksource_read,
};

static const struct pv_cpu_ops xen_cpu_ops __initdata = {
.cpuid = xen_cpuid,

Expand Down Expand Up @@ -1096,21 +1101,14 @@ asmlinkage void __init xen_start_kernel(void)
/* Install Xen paravirt ops */
pv_info = xen_info;
pv_init_ops = xen_init_ops;
pv_time_ops = xen_time_ops;
pv_cpu_ops = xen_cpu_ops;
pv_apic_ops = xen_apic_ops;

x86_init.resources.memory_setup = xen_memory_setup;
x86_init.oem.arch_setup = xen_arch_setup;
x86_init.oem.banner = xen_banner;

x86_init.timers.timer_init = xen_time_init;
x86_init.timers.setup_percpu_clockev = x86_init_noop;
x86_cpuinit.setup_percpu_clockev = x86_init_noop;

x86_platform.calibrate_tsc = xen_tsc_khz;
x86_platform.get_wallclock = xen_get_wallclock;
x86_platform.set_wallclock = xen_set_wallclock;
xen_init_time_ops();

/*
* Set up some pagetable state before starting to set any ptes.
Expand Down Expand Up @@ -1235,3 +1233,139 @@ asmlinkage void __init xen_start_kernel(void)
x86_64_start_reservations((char *)__pa_symbol(&boot_params));
#endif
}

static uint32_t xen_cpuid_base(void)
{
uint32_t base, eax, ebx, ecx, edx;
char signature[13];

for (base = 0x40000000; base < 0x40010000; base += 0x100) {
cpuid(base, &eax, &ebx, &ecx, &edx);
*(uint32_t *)(signature + 0) = ebx;
*(uint32_t *)(signature + 4) = ecx;
*(uint32_t *)(signature + 8) = edx;
signature[12] = 0;

if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
return base;
}

return 0;
}

static int init_hvm_pv_info(int *major, int *minor)
{
uint32_t eax, ebx, ecx, edx, pages, msr, base;
u64 pfn;

base = xen_cpuid_base();
cpuid(base + 1, &eax, &ebx, &ecx, &edx);

*major = eax >> 16;
*minor = eax & 0xffff;
printk(KERN_INFO "Xen version %d.%d.\n", *major, *minor);

cpuid(base + 2, &pages, &msr, &ecx, &edx);

pfn = __pa(hypercall_page);
wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));

xen_setup_features();

pv_info = xen_info;
pv_info.kernel_rpl = 0;

xen_domain_type = XEN_HVM_DOMAIN;

return 0;
}

void xen_hvm_init_shared_info(void)
{
int cpu;
struct xen_add_to_physmap xatp;
static struct shared_info *shared_info_page = 0;

if (!shared_info_page)
shared_info_page = (struct shared_info *)
extend_brk(PAGE_SIZE, PAGE_SIZE);
xatp.domid = DOMID_SELF;
xatp.idx = 0;
xatp.space = XENMAPSPACE_shared_info;
xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
BUG();

HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;

/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
* page, we use it in the event channel upcall and in some pvclock
* related functions. We don't need the vcpu_info placement
* optimizations because we don't use any pv_mmu or pv_irq op on
* HVM.
* When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
* online but xen_hvm_init_shared_info is run at resume time too and
* in that case multiple vcpus might be online. */
for_each_online_cpu(cpu) {
per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
}
}

#ifdef CONFIG_XEN_PVHVM
static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
int cpu = (long)hcpu;
switch (action) {
case CPU_UP_PREPARE:
per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
break;
default:
break;
}
return NOTIFY_OK;
}

static struct notifier_block __cpuinitdata xen_hvm_cpu_notifier = {
.notifier_call = xen_hvm_cpu_notify,
};

static void __init xen_hvm_guest_init(void)
{
int r;
int major, minor;

r = init_hvm_pv_info(&major, &minor);
if (r < 0)
return;

xen_hvm_init_shared_info();

if (xen_feature(XENFEAT_hvm_callback_vector))
xen_have_vector_callback = 1;
register_cpu_notifier(&xen_hvm_cpu_notifier);
xen_unplug_emulated_devices();
have_vcpu_info_placement = 0;
x86_init.irqs.intr_init = xen_init_IRQ;
xen_hvm_init_time_ops();
xen_hvm_init_mmu_ops();
}

static bool __init xen_hvm_platform(void)
{
if (xen_pv_domain())
return false;

if (!xen_cpuid_base())
return false;

return true;
}

const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
.name = "Xen HVM",
.detect = xen_hvm_platform,
.init_platform = xen_hvm_guest_init,
};
EXPORT_SYMBOL(x86_hyper_xen_hvm);
#endif
35 changes: 35 additions & 0 deletions arch/x86/xen/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@

#include <xen/page.h>
#include <xen/interface/xen.h>
#include <xen/interface/hvm/hvm_op.h>
#include <xen/interface/version.h>
#include <xen/hvc-console.h>

Expand Down Expand Up @@ -1941,6 +1942,40 @@ void __init xen_init_mmu_ops(void)
pv_mmu_ops = xen_mmu_ops;
}

#ifdef CONFIG_XEN_PVHVM
static void xen_hvm_exit_mmap(struct mm_struct *mm)
{
struct xen_hvm_pagetable_dying a;
int rc;

a.domid = DOMID_SELF;
a.gpa = __pa(mm->pgd);
rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
WARN_ON_ONCE(rc < 0);
}

static int is_pagetable_dying_supported(void)
{
struct xen_hvm_pagetable_dying a;
int rc = 0;

a.domid = DOMID_SELF;
a.gpa = 0x00;
rc = HYPERVISOR_hvm_op(HVMOP_pagetable_dying, &a);
if (rc < 0) {
printk(KERN_DEBUG "HVMOP_pagetable_dying not supported\n");
return 0;
}
return 1;
}

void __init xen_hvm_init_mmu_ops(void)
{
if (is_pagetable_dying_supported())
pv_mmu_ops.exit_mmap = xen_hvm_exit_mmap;
}
#endif

#ifdef CONFIG_XEN_DEBUG_FS

static struct dentry *d_mmu_debug;
Expand Down
1 change: 1 addition & 0 deletions arch/x86/xen/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
unsigned long xen_read_cr2_direct(void);

extern void xen_init_mmu_ops(void);
extern void xen_hvm_init_mmu_ops(void);
#endif /* _XEN_MMU_H */
Loading

0 comments on commit ca50a5f

Please sign in to comment.