x86: early PV on HVM features initialization.
Initialize basic pv on hvm features adding a new Xen HVM specific hypervisor_x86 structure. Don't try to initialize xen-kbdfront and xen-fbfront when running on HVM because the backends are not available. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
This commit is contained in:
Родитель
18f19aa62a
Коммит
bee6ab53e6
|
@ -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
|
||||
|
|
|
@ -34,6 +34,7 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
|
|||
{
|
||||
&x86_hyper_vmware,
|
||||
&x86_hyper_ms_hyperv,
|
||||
&x86_hyper_xen_hvm,
|
||||
};
|
||||
|
||||
const struct hypervisor_x86 *x86_hyper;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#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/hvc-console.h>
|
||||
|
@ -55,7 +56,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"
|
||||
|
@ -76,6 +79,8 @@ struct shared_info xen_dummy_shared_info;
|
|||
|
||||
void *xen_initial_gdt;
|
||||
|
||||
RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Point at some empty memory to start with. We map the real shared_info
|
||||
* page as soon as fixmap is up and running.
|
||||
|
@ -1206,3 +1211,98 @@ 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;
|
||||
}
|
||||
|
||||
static void __init init_shared_info(void)
|
||||
{
|
||||
struct xen_add_to_physmap xatp;
|
||||
struct shared_info *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;
|
||||
|
||||
per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
|
||||
}
|
||||
|
||||
static void __init xen_hvm_guest_init(void)
|
||||
{
|
||||
int r;
|
||||
int major, minor;
|
||||
|
||||
r = init_hvm_pv_info(&major, &minor);
|
||||
if (r < 0)
|
||||
return;
|
||||
|
||||
init_shared_info();
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -339,7 +339,7 @@ static struct xenbus_driver xenkbd_driver = {
|
|||
|
||||
static int __init xenkbd_init(void)
|
||||
{
|
||||
if (!xen_domain())
|
||||
if (!xen_pv_domain())
|
||||
return -ENODEV;
|
||||
|
||||
/* Nothing to do if running in dom0. */
|
||||
|
|
|
@ -684,7 +684,7 @@ static struct xenbus_driver xenfb_driver = {
|
|||
|
||||
static int __init xenfb_init(void)
|
||||
{
|
||||
if (!xen_domain())
|
||||
if (!xen_pv_domain())
|
||||
return -ENODEV;
|
||||
|
||||
/* Nothing to do if running in dom0. */
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include <xen/events.h>
|
||||
#include <xen/page.h>
|
||||
|
||||
#include <xen/hvm.h>
|
||||
|
||||
#include "xenbus_comms.h"
|
||||
#include "xenbus_probe.h"
|
||||
|
||||
|
@ -805,11 +807,24 @@ static int __init xenbus_probe_init(void)
|
|||
if (xen_initial_domain()) {
|
||||
/* dom0 not yet supported */
|
||||
} else {
|
||||
if (xen_hvm_domain()) {
|
||||
uint64_t v = 0;
|
||||
err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
|
||||
if (err)
|
||||
goto out_error;
|
||||
xen_store_evtchn = (int)v;
|
||||
err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
|
||||
if (err)
|
||||
goto out_error;
|
||||
xen_store_mfn = (unsigned long)v;
|
||||
xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
|
||||
} else {
|
||||
xen_store_evtchn = xen_start_info->store_evtchn;
|
||||
xen_store_mfn = xen_start_info->store_mfn;
|
||||
xen_store_interface = mfn_to_virt(xen_store_mfn);
|
||||
}
|
||||
xenstored_ready = 1;
|
||||
xen_store_evtchn = xen_start_info->store_evtchn;
|
||||
xen_store_mfn = xen_start_info->store_mfn;
|
||||
}
|
||||
xen_store_interface = mfn_to_virt(xen_store_mfn);
|
||||
|
||||
/* Initialize the interface to xenstore. */
|
||||
err = xs_init();
|
||||
|
|
Загрузка…
Ссылка в новой задаче