[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] x86: introduce CONFIG_GUEST and move code



commit ca363f186d6f2d43ba1b9e335284feb9d6d9fd79
Author:     Wei Liu <liuwe@xxxxxxxxxxxxx>
AuthorDate: Thu Sep 19 13:22:05 2019 +0100
Commit:     Wei Liu <wl@xxxxxxx>
CommitDate: Wed Dec 4 10:31:25 2019 +0000

    x86: introduce CONFIG_GUEST and move code
    
    Xen is able to run as a guest on Xen. We plan to make it able to run
    on Hyper-V as well.
    
    Introduce CONFIG_GUEST which is set to true if either running on Xen
    or Hyper-V is desired. Restructure code hierarchy for new code to
    come.
    
    No functional change intended.
    
    Signed-off-by: Wei Liu <liuwe@xxxxxxxxxxxxx>
    Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/Kconfig                    |   7 +-
 xen/arch/x86/Makefile                   |   2 +-
 xen/arch/x86/guest/Makefile             |   5 +-
 xen/arch/x86/guest/hypercall_page.S     |  78 --------
 xen/arch/x86/guest/pvh-boot.c           | 151 --------------
 xen/arch/x86/guest/xen.c                | 342 --------------------------------
 xen/arch/x86/guest/xen/Makefile         |   4 +
 xen/arch/x86/guest/xen/hypercall_page.S |  78 ++++++++
 xen/arch/x86/guest/xen/pvh-boot.c       | 151 ++++++++++++++
 xen/arch/x86/guest/xen/xen.c            | 342 ++++++++++++++++++++++++++++++++
 10 files changed, 582 insertions(+), 578 deletions(-)

diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 28b3b4692a..18c8f6fd26 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -161,9 +161,12 @@ config XEN_ALIGN_2M
 
 endchoice
 
+config GUEST
+       bool
+
 config XEN_GUEST
-       def_bool n
-       prompt "Xen Guest"
+       bool "Xen Guest"
+       select GUEST
        ---help---
          Support for Xen detecting when it is running under Xen.
 
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index a0b2f4ab15..7da5a2631e 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -1,7 +1,7 @@
 subdir-y += acpi
 subdir-y += cpu
 subdir-y += genapic
-subdir-$(CONFIG_XEN_GUEST) += guest
+subdir-$(CONFIG_GUEST) += guest
 subdir-$(CONFIG_HVM) += hvm
 subdir-y += mm
 subdir-$(CONFIG_XENOPROF) += oprofile
diff --git a/xen/arch/x86/guest/Makefile b/xen/arch/x86/guest/Makefile
index 26fb4b1007..6806f04947 100644
--- a/xen/arch/x86/guest/Makefile
+++ b/xen/arch/x86/guest/Makefile
@@ -1,4 +1 @@
-obj-y += hypercall_page.o
-obj-y += xen.o
-
-obj-bin-$(CONFIG_PVH_GUEST) += pvh-boot.init.o
+subdir-$(CONFIG_XEN_GUEST) += xen
diff --git a/xen/arch/x86/guest/hypercall_page.S 
b/xen/arch/x86/guest/hypercall_page.S
deleted file mode 100644
index 6485e9150e..0000000000
--- a/xen/arch/x86/guest/hypercall_page.S
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <asm/page.h>
-#include <asm/asm_defns.h>
-#include <public/xen.h>
-
-        .section ".text.page_aligned", "ax", @progbits
-        .p2align PAGE_SHIFT
-
-GLOBAL(hypercall_page)
-         /* Poisoned with `ret` for safety before hypercalls are set up. */
-        .fill PAGE_SIZE, 1, 0xc3
-        .type hypercall_page, STT_OBJECT
-        .size hypercall_page, PAGE_SIZE
-
-/*
- * Identify a specific hypercall in the hypercall page
- * @param name Hypercall name.
- */
-#define DECLARE_HYPERCALL(name)                                                
 \
-        .globl HYPERCALL_ ## name;                                             
 \
-        .set   HYPERCALL_ ## name, hypercall_page + __HYPERVISOR_ ## name * 
32; \
-        .type  HYPERCALL_ ## name, STT_FUNC;                                   
 \
-        .size  HYPERCALL_ ## name, 32
-
-DECLARE_HYPERCALL(set_trap_table)
-DECLARE_HYPERCALL(mmu_update)
-DECLARE_HYPERCALL(set_gdt)
-DECLARE_HYPERCALL(stack_switch)
-DECLARE_HYPERCALL(set_callbacks)
-DECLARE_HYPERCALL(fpu_taskswitch)
-DECLARE_HYPERCALL(sched_op_compat)
-DECLARE_HYPERCALL(platform_op)
-DECLARE_HYPERCALL(set_debugreg)
-DECLARE_HYPERCALL(get_debugreg)
-DECLARE_HYPERCALL(update_descriptor)
-DECLARE_HYPERCALL(memory_op)
-DECLARE_HYPERCALL(multicall)
-DECLARE_HYPERCALL(update_va_mapping)
-DECLARE_HYPERCALL(set_timer_op)
-DECLARE_HYPERCALL(event_channel_op_compat)
-DECLARE_HYPERCALL(xen_version)
-DECLARE_HYPERCALL(console_io)
-DECLARE_HYPERCALL(physdev_op_compat)
-DECLARE_HYPERCALL(grant_table_op)
-DECLARE_HYPERCALL(vm_assist)
-DECLARE_HYPERCALL(update_va_mapping_otherdomain)
-DECLARE_HYPERCALL(iret)
-DECLARE_HYPERCALL(vcpu_op)
-DECLARE_HYPERCALL(set_segment_base)
-DECLARE_HYPERCALL(mmuext_op)
-DECLARE_HYPERCALL(xsm_op)
-DECLARE_HYPERCALL(nmi_op)
-DECLARE_HYPERCALL(sched_op)
-DECLARE_HYPERCALL(callback_op)
-DECLARE_HYPERCALL(xenoprof_op)
-DECLARE_HYPERCALL(event_channel_op)
-DECLARE_HYPERCALL(physdev_op)
-DECLARE_HYPERCALL(hvm_op)
-DECLARE_HYPERCALL(sysctl)
-DECLARE_HYPERCALL(domctl)
-DECLARE_HYPERCALL(kexec_op)
-DECLARE_HYPERCALL(argo_op)
-DECLARE_HYPERCALL(xenpmu_op)
-
-DECLARE_HYPERCALL(arch_0)
-DECLARE_HYPERCALL(arch_1)
-DECLARE_HYPERCALL(arch_2)
-DECLARE_HYPERCALL(arch_3)
-DECLARE_HYPERCALL(arch_4)
-DECLARE_HYPERCALL(arch_5)
-DECLARE_HYPERCALL(arch_6)
-DECLARE_HYPERCALL(arch_7)
-
-/*
- * Local variables:
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/x86/guest/pvh-boot.c b/xen/arch/x86/guest/pvh-boot.c
deleted file mode 100644
index ca8e156f7d..0000000000
--- a/xen/arch/x86/guest/pvh-boot.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/******************************************************************************
- * arch/x86/guest/pvh-boot.c
- *
- * PVH boot time support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (c) 2017 Citrix Systems Ltd.
- */
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-
-#include <asm/e820.h>
-#include <asm/guest.h>
-
-#include <public/arch-x86/hvm/start_info.h>
-
-/* Initialised in head.S, before .bss is zeroed. */
-bool __initdata pvh_boot;
-uint32_t __initdata pvh_start_info_pa;
-
-static multiboot_info_t __initdata pvh_mbi;
-static module_t __initdata pvh_mbi_mods[8];
-static const char *__initdata pvh_loader = "PVH Directboot";
-
-static void __init convert_pvh_info(multiboot_info_t **mbi,
-                                    module_t **mod)
-{
-    const struct hvm_start_info *pvh_info = __va(pvh_start_info_pa);
-    const struct hvm_modlist_entry *entry;
-    unsigned int i;
-
-    if ( pvh_info->magic != XEN_HVM_START_MAGIC_VALUE )
-        panic("Magic value is wrong: %x\n", pvh_info->magic);
-
-    /*
-     * Temporary module array needs to be at least one element bigger than
-     * required. The extra element is used to aid relocation. See
-     * arch/x86/setup.c:__start_xen().
-     */
-    if ( ARRAY_SIZE(pvh_mbi_mods) <= pvh_info->nr_modules )
-        panic("The module array is too small, size %zu, requested %u\n",
-              ARRAY_SIZE(pvh_mbi_mods), pvh_info->nr_modules);
-
-    /*
-     * Turn hvm_start_info into mbi. Luckily all modules are placed under 4GB
-     * boundary on x86.
-     */
-    pvh_mbi.flags = MBI_CMDLINE | MBI_MODULES | MBI_LOADERNAME;
-
-    BUG_ON(pvh_info->cmdline_paddr >> 32);
-    pvh_mbi.cmdline = pvh_info->cmdline_paddr;
-    pvh_mbi.boot_loader_name = __pa(pvh_loader);
-
-    BUG_ON(pvh_info->nr_modules >= ARRAY_SIZE(pvh_mbi_mods));
-    pvh_mbi.mods_count = pvh_info->nr_modules;
-    pvh_mbi.mods_addr = __pa(pvh_mbi_mods);
-
-    entry = __va(pvh_info->modlist_paddr);
-    for ( i = 0; i < pvh_info->nr_modules; i++ )
-    {
-        BUG_ON(entry[i].paddr >> 32);
-        BUG_ON(entry[i].cmdline_paddr >> 32);
-
-        pvh_mbi_mods[i].mod_start = entry[i].paddr;
-        pvh_mbi_mods[i].mod_end   = entry[i].paddr + entry[i].size;
-        pvh_mbi_mods[i].string    = entry[i].cmdline_paddr;
-    }
-
-    rsdp_hint = pvh_info->rsdp_paddr;
-
-    *mbi = &pvh_mbi;
-    *mod = pvh_mbi_mods;
-}
-
-static void __init get_memory_map(void)
-{
-    struct xen_memory_map memmap = {
-        .nr_entries = E820MAX,
-    };
-
-    set_xen_guest_handle(memmap.buffer, e820_raw.map);
-    BUG_ON(xen_hypercall_memory_op(XENMEM_memory_map, &memmap));
-    e820_raw.nr_map = memmap.nr_entries;
-
-    /* :( Various toolstacks don't sort the memory map. */
-    sanitize_e820_map(e820_raw.map, &e820_raw.nr_map);
-}
-
-void __init pvh_init(multiboot_info_t **mbi, module_t **mod)
-{
-    convert_pvh_info(mbi, mod);
-
-    probe_hypervisor();
-    ASSERT(xen_guest);
-
-    get_memory_map();
-}
-
-void __init pvh_print_info(void)
-{
-    const struct hvm_start_info *pvh_info = __va(pvh_start_info_pa);
-    const struct hvm_modlist_entry *entry;
-    unsigned int i;
-
-    ASSERT(pvh_info->magic == XEN_HVM_START_MAGIC_VALUE);
-
-    printk("PVH start info: (pa %08x)\n", pvh_start_info_pa);
-    printk("  version:    %u\n", pvh_info->version);
-    printk("  flags:      %#"PRIx32"\n", pvh_info->flags);
-    printk("  nr_modules: %u\n", pvh_info->nr_modules);
-    printk("  modlist_pa: %016"PRIx64"\n", pvh_info->modlist_paddr);
-    printk("  cmdline_pa: %016"PRIx64"\n", pvh_info->cmdline_paddr);
-    if ( pvh_info->cmdline_paddr )
-        printk("  cmdline:    '%s'\n", (char *)__va(pvh_info->cmdline_paddr));
-    printk("  rsdp_pa:    %016"PRIx64"\n", pvh_info->rsdp_paddr);
-
-    entry = __va(pvh_info->modlist_paddr);
-    for ( i = 0; i < pvh_info->nr_modules; i++ )
-    {
-        printk("    mod[%u].pa:         %016"PRIx64"\n", i, entry[i].paddr);
-        printk("    mod[%u].size:       %016"PRIu64"\n", i, entry[i].size);
-        printk("    mod[%u].cmdline_pa: %016"PRIx64"\n",
-               i, entry[i].cmdline_paddr);
-        if ( entry[i].cmdline_paddr )
-            printk("    mod[%1u].cmdline:    '%s'\n", i,
-                   (char *)__va(entry[i].cmdline_paddr));
-    }
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/x86/guest/xen.c b/xen/arch/x86/guest/xen.c
deleted file mode 100644
index a329e7c886..0000000000
--- a/xen/arch/x86/guest/xen.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/******************************************************************************
- * arch/x86/guest/xen.c
- *
- * Support for detecting and running under Xen.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (c) 2017 Citrix Systems Ltd.
- */
-#include <xen/event.h>
-#include <xen/init.h>
-#include <xen/mm.h>
-#include <xen/pfn.h>
-#include <xen/rangeset.h>
-#include <xen/types.h>
-#include <xen/pv_console.h>
-
-#include <asm/apic.h>
-#include <asm/e820.h>
-#include <asm/guest.h>
-#include <asm/msr.h>
-#include <asm/processor.h>
-
-#include <public/arch-x86/cpuid.h>
-#include <public/hvm/params.h>
-
-bool __read_mostly xen_guest;
-
-static __read_mostly uint32_t xen_cpuid_base;
-extern char hypercall_page[];
-static struct rangeset *mem;
-
-DEFINE_PER_CPU(unsigned int, vcpu_id);
-
-static struct vcpu_info *vcpu_info;
-static unsigned long vcpu_info_mapped[BITS_TO_LONGS(NR_CPUS)];
-DEFINE_PER_CPU(struct vcpu_info *, vcpu_info);
-
-static void __init find_xen_leaves(void)
-{
-    uint32_t eax, ebx, ecx, edx, base;
-
-    for ( base = XEN_CPUID_FIRST_LEAF;
-          base < XEN_CPUID_FIRST_LEAF + 0x10000; base += 0x100 )
-    {
-        cpuid(base, &eax, &ebx, &ecx, &edx);
-
-        if ( (ebx == XEN_CPUID_SIGNATURE_EBX) &&
-             (ecx == XEN_CPUID_SIGNATURE_ECX) &&
-             (edx == XEN_CPUID_SIGNATURE_EDX) &&
-             ((eax - base) >= 2) )
-        {
-            xen_cpuid_base = base;
-            break;
-        }
-    }
-}
-
-void __init probe_hypervisor(void)
-{
-    if ( xen_guest || !cpu_has_hypervisor )
-        return;
-
-    find_xen_leaves();
-
-    if ( !xen_cpuid_base )
-        return;
-
-    /* Fill the hypercall page. */
-    wrmsrl(cpuid_ebx(xen_cpuid_base + 2), __pa(hypercall_page));
-
-    xen_guest = true;
-}
-
-static void map_shared_info(void)
-{
-    mfn_t mfn;
-    struct xen_add_to_physmap xatp = {
-        .domid = DOMID_SELF,
-        .space = XENMAPSPACE_shared_info,
-    };
-    unsigned int i;
-    unsigned long rc;
-
-    if ( hypervisor_alloc_unused_page(&mfn) )
-        panic("unable to reserve shared info memory page\n");
-
-    xatp.gpfn = mfn_x(mfn);
-    rc = xen_hypercall_memory_op(XENMEM_add_to_physmap, &xatp);
-    if ( rc )
-        panic("failed to map shared_info page: %ld\n", rc);
-
-    set_fixmap(FIX_XEN_SHARED_INFO, mfn_x(mfn) << PAGE_SHIFT);
-
-    /* Mask all upcalls */
-    for ( i = 0; i < ARRAY_SIZE(XEN_shared_info->evtchn_mask); i++ )
-        write_atomic(&XEN_shared_info->evtchn_mask[i], ~0ul);
-}
-
-static int map_vcpuinfo(void)
-{
-    unsigned int vcpu = this_cpu(vcpu_id);
-    struct vcpu_register_vcpu_info info;
-    int rc;
-
-    if ( !vcpu_info )
-    {
-        this_cpu(vcpu_info) = &XEN_shared_info->vcpu_info[vcpu];
-        return 0;
-    }
-
-    if ( test_bit(vcpu, vcpu_info_mapped) )
-    {
-        this_cpu(vcpu_info) = &vcpu_info[vcpu];
-        return 0;
-    }
-
-    info.mfn = virt_to_mfn(&vcpu_info[vcpu]);
-    info.offset = (unsigned long)&vcpu_info[vcpu] & ~PAGE_MASK;
-    rc = xen_hypercall_vcpu_op(VCPUOP_register_vcpu_info, vcpu, &info);
-    if ( rc )
-    {
-        BUG_ON(vcpu >= XEN_LEGACY_MAX_VCPUS);
-        this_cpu(vcpu_info) = &XEN_shared_info->vcpu_info[vcpu];
-    }
-    else
-    {
-        this_cpu(vcpu_info) = &vcpu_info[vcpu];
-        set_bit(vcpu, vcpu_info_mapped);
-    }
-
-    return rc;
-}
-
-static void set_vcpu_id(void)
-{
-    uint32_t eax, ebx, ecx, edx;
-
-    ASSERT(xen_cpuid_base);
-
-    /* Fetch vcpu id from cpuid. */
-    cpuid(xen_cpuid_base + 4, &eax, &ebx, &ecx, &edx);
-    if ( eax & XEN_HVM_CPUID_VCPU_ID_PRESENT )
-        this_cpu(vcpu_id) = ebx;
-    else
-        this_cpu(vcpu_id) = smp_processor_id();
-}
-
-static void __init init_memmap(void)
-{
-    unsigned int i;
-
-    mem = rangeset_new(NULL, "host memory map", 0);
-    if ( !mem )
-        panic("failed to allocate PFN usage rangeset\n");
-
-    /*
-     * Mark up to the last memory page (or 4GiB) as RAM. This is done because
-     * Xen doesn't know the position of possible MMIO holes, so at least try to
-     * avoid the know MMIO hole below 4GiB. Note that this is subject to future
-     * discussion and improvements.
-     */
-    if ( rangeset_add_range(mem, 0, max_t(unsigned long, max_page - 1,
-                                          PFN_DOWN(GB(4) - 1))) )
-        panic("unable to add RAM to in-use PFN rangeset\n");
-
-    for ( i = 0; i < e820.nr_map; i++ )
-    {
-        struct e820entry *e = &e820.map[i];
-
-        if ( rangeset_add_range(mem, PFN_DOWN(e->addr),
-                                PFN_UP(e->addr + e->size - 1)) )
-            panic("unable to add range [%#lx, %#lx] to in-use PFN rangeset\n",
-                  PFN_DOWN(e->addr), PFN_UP(e->addr + e->size - 1));
-    }
-}
-
-static void xen_evtchn_upcall(struct cpu_user_regs *regs)
-{
-    struct vcpu_info *vcpu_info = this_cpu(vcpu_info);
-    unsigned long pending;
-
-    vcpu_info->evtchn_upcall_pending = 0;
-    pending = xchg(&vcpu_info->evtchn_pending_sel, 0);
-
-    while ( pending )
-    {
-        unsigned int l1 = find_first_set_bit(pending);
-        unsigned long evtchn = xchg(&XEN_shared_info->evtchn_pending[l1], 0);
-
-        __clear_bit(l1, &pending);
-        evtchn &= ~XEN_shared_info->evtchn_mask[l1];
-        while ( evtchn )
-        {
-            unsigned int port = find_first_set_bit(evtchn);
-
-            __clear_bit(port, &evtchn);
-            port += l1 * BITS_PER_LONG;
-
-            if ( pv_console && port == pv_console_evtchn() )
-                pv_console_rx(regs);
-            else if ( pv_shim )
-                pv_shim_inject_evtchn(port);
-        }
-    }
-
-    ack_APIC_irq();
-}
-
-static void init_evtchn(void)
-{
-    static uint8_t evtchn_upcall_vector;
-    int rc;
-
-    if ( !evtchn_upcall_vector )
-        alloc_direct_apic_vector(&evtchn_upcall_vector, xen_evtchn_upcall);
-
-    ASSERT(evtchn_upcall_vector);
-
-    rc = xen_hypercall_set_evtchn_upcall_vector(this_cpu(vcpu_id),
-                                                evtchn_upcall_vector);
-    if ( rc )
-        panic("Unable to set evtchn upcall vector: %d\n", rc);
-
-    /* Trick toolstack to think we are enlightened */
-    {
-        struct xen_hvm_param a = {
-            .domid = DOMID_SELF,
-            .index = HVM_PARAM_CALLBACK_IRQ,
-            .value = 1,
-        };
-
-        BUG_ON(xen_hypercall_hvm_op(HVMOP_set_param, &a));
-    }
-}
-
-void __init hypervisor_setup(void)
-{
-    init_memmap();
-
-    map_shared_info();
-
-    set_vcpu_id();
-    vcpu_info = xzalloc_array(struct vcpu_info, nr_cpu_ids);
-    if ( map_vcpuinfo() )
-    {
-        xfree(vcpu_info);
-        vcpu_info = NULL;
-    }
-    if ( !vcpu_info && nr_cpu_ids > XEN_LEGACY_MAX_VCPUS )
-    {
-        unsigned int i;
-
-        for ( i = XEN_LEGACY_MAX_VCPUS; i < nr_cpu_ids; i++ )
-            __cpumask_clear_cpu(i, &cpu_present_map);
-        nr_cpu_ids = XEN_LEGACY_MAX_VCPUS;
-        printk(XENLOG_WARNING
-               "unable to map vCPU info, limiting vCPUs to: %u\n",
-               XEN_LEGACY_MAX_VCPUS);
-    }
-
-    init_evtchn();
-}
-
-void hypervisor_ap_setup(void)
-{
-    set_vcpu_id();
-    map_vcpuinfo();
-    init_evtchn();
-}
-
-int hypervisor_alloc_unused_page(mfn_t *mfn)
-{
-    unsigned long m;
-    int rc;
-
-    rc = rangeset_claim_range(mem, 1, &m);
-    if ( !rc )
-        *mfn = _mfn(m);
-
-    return rc;
-}
-
-int hypervisor_free_unused_page(mfn_t mfn)
-{
-    return rangeset_remove_range(mem, mfn_x(mfn), mfn_x(mfn));
-}
-
-uint32_t hypervisor_cpuid_base(void)
-{
-    return xen_cpuid_base;
-}
-
-static void ap_resume(void *unused)
-{
-    map_vcpuinfo();
-    init_evtchn();
-}
-
-void hypervisor_resume(void)
-{
-    /* Reset shared info page. */
-    map_shared_info();
-
-    /*
-     * Reset vcpu_info. Just clean the mapped bitmap and try to map the vcpu
-     * area again. On failure to map (when it was previously mapped) panic
-     * since it's impossible to safely shut down running guest vCPUs in order
-     * to meet the new XEN_LEGACY_MAX_VCPUS requirement.
-     */
-    bitmap_zero(vcpu_info_mapped, NR_CPUS);
-    if ( map_vcpuinfo() && nr_cpu_ids > XEN_LEGACY_MAX_VCPUS )
-        panic("unable to remap vCPU info and vCPUs > legacy limit\n");
-
-    /* Setup event channel upcall vector. */
-    init_evtchn();
-    smp_call_function(ap_resume, NULL, 1);
-
-    if ( pv_console )
-        pv_console_init();
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/x86/guest/xen/Makefile b/xen/arch/x86/guest/xen/Makefile
new file mode 100644
index 0000000000..26fb4b1007
--- /dev/null
+++ b/xen/arch/x86/guest/xen/Makefile
@@ -0,0 +1,4 @@
+obj-y += hypercall_page.o
+obj-y += xen.o
+
+obj-bin-$(CONFIG_PVH_GUEST) += pvh-boot.init.o
diff --git a/xen/arch/x86/guest/xen/hypercall_page.S 
b/xen/arch/x86/guest/xen/hypercall_page.S
new file mode 100644
index 0000000000..6485e9150e
--- /dev/null
+++ b/xen/arch/x86/guest/xen/hypercall_page.S
@@ -0,0 +1,78 @@
+#include <asm/page.h>
+#include <asm/asm_defns.h>
+#include <public/xen.h>
+
+        .section ".text.page_aligned", "ax", @progbits
+        .p2align PAGE_SHIFT
+
+GLOBAL(hypercall_page)
+         /* Poisoned with `ret` for safety before hypercalls are set up. */
+        .fill PAGE_SIZE, 1, 0xc3
+        .type hypercall_page, STT_OBJECT
+        .size hypercall_page, PAGE_SIZE
+
+/*
+ * Identify a specific hypercall in the hypercall page
+ * @param name Hypercall name.
+ */
+#define DECLARE_HYPERCALL(name)                                                
 \
+        .globl HYPERCALL_ ## name;                                             
 \
+        .set   HYPERCALL_ ## name, hypercall_page + __HYPERVISOR_ ## name * 
32; \
+        .type  HYPERCALL_ ## name, STT_FUNC;                                   
 \
+        .size  HYPERCALL_ ## name, 32
+
+DECLARE_HYPERCALL(set_trap_table)
+DECLARE_HYPERCALL(mmu_update)
+DECLARE_HYPERCALL(set_gdt)
+DECLARE_HYPERCALL(stack_switch)
+DECLARE_HYPERCALL(set_callbacks)
+DECLARE_HYPERCALL(fpu_taskswitch)
+DECLARE_HYPERCALL(sched_op_compat)
+DECLARE_HYPERCALL(platform_op)
+DECLARE_HYPERCALL(set_debugreg)
+DECLARE_HYPERCALL(get_debugreg)
+DECLARE_HYPERCALL(update_descriptor)
+DECLARE_HYPERCALL(memory_op)
+DECLARE_HYPERCALL(multicall)
+DECLARE_HYPERCALL(update_va_mapping)
+DECLARE_HYPERCALL(set_timer_op)
+DECLARE_HYPERCALL(event_channel_op_compat)
+DECLARE_HYPERCALL(xen_version)
+DECLARE_HYPERCALL(console_io)
+DECLARE_HYPERCALL(physdev_op_compat)
+DECLARE_HYPERCALL(grant_table_op)
+DECLARE_HYPERCALL(vm_assist)
+DECLARE_HYPERCALL(update_va_mapping_otherdomain)
+DECLARE_HYPERCALL(iret)
+DECLARE_HYPERCALL(vcpu_op)
+DECLARE_HYPERCALL(set_segment_base)
+DECLARE_HYPERCALL(mmuext_op)
+DECLARE_HYPERCALL(xsm_op)
+DECLARE_HYPERCALL(nmi_op)
+DECLARE_HYPERCALL(sched_op)
+DECLARE_HYPERCALL(callback_op)
+DECLARE_HYPERCALL(xenoprof_op)
+DECLARE_HYPERCALL(event_channel_op)
+DECLARE_HYPERCALL(physdev_op)
+DECLARE_HYPERCALL(hvm_op)
+DECLARE_HYPERCALL(sysctl)
+DECLARE_HYPERCALL(domctl)
+DECLARE_HYPERCALL(kexec_op)
+DECLARE_HYPERCALL(argo_op)
+DECLARE_HYPERCALL(xenpmu_op)
+
+DECLARE_HYPERCALL(arch_0)
+DECLARE_HYPERCALL(arch_1)
+DECLARE_HYPERCALL(arch_2)
+DECLARE_HYPERCALL(arch_3)
+DECLARE_HYPERCALL(arch_4)
+DECLARE_HYPERCALL(arch_5)
+DECLARE_HYPERCALL(arch_6)
+DECLARE_HYPERCALL(arch_7)
+
+/*
+ * Local variables:
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/guest/xen/pvh-boot.c 
b/xen/arch/x86/guest/xen/pvh-boot.c
new file mode 100644
index 0000000000..ca8e156f7d
--- /dev/null
+++ b/xen/arch/x86/guest/xen/pvh-boot.c
@@ -0,0 +1,151 @@
+/******************************************************************************
+ * arch/x86/guest/pvh-boot.c
+ *
+ * PVH boot time support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2017 Citrix Systems Ltd.
+ */
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+
+#include <asm/e820.h>
+#include <asm/guest.h>
+
+#include <public/arch-x86/hvm/start_info.h>
+
+/* Initialised in head.S, before .bss is zeroed. */
+bool __initdata pvh_boot;
+uint32_t __initdata pvh_start_info_pa;
+
+static multiboot_info_t __initdata pvh_mbi;
+static module_t __initdata pvh_mbi_mods[8];
+static const char *__initdata pvh_loader = "PVH Directboot";
+
+static void __init convert_pvh_info(multiboot_info_t **mbi,
+                                    module_t **mod)
+{
+    const struct hvm_start_info *pvh_info = __va(pvh_start_info_pa);
+    const struct hvm_modlist_entry *entry;
+    unsigned int i;
+
+    if ( pvh_info->magic != XEN_HVM_START_MAGIC_VALUE )
+        panic("Magic value is wrong: %x\n", pvh_info->magic);
+
+    /*
+     * Temporary module array needs to be at least one element bigger than
+     * required. The extra element is used to aid relocation. See
+     * arch/x86/setup.c:__start_xen().
+     */
+    if ( ARRAY_SIZE(pvh_mbi_mods) <= pvh_info->nr_modules )
+        panic("The module array is too small, size %zu, requested %u\n",
+              ARRAY_SIZE(pvh_mbi_mods), pvh_info->nr_modules);
+
+    /*
+     * Turn hvm_start_info into mbi. Luckily all modules are placed under 4GB
+     * boundary on x86.
+     */
+    pvh_mbi.flags = MBI_CMDLINE | MBI_MODULES | MBI_LOADERNAME;
+
+    BUG_ON(pvh_info->cmdline_paddr >> 32);
+    pvh_mbi.cmdline = pvh_info->cmdline_paddr;
+    pvh_mbi.boot_loader_name = __pa(pvh_loader);
+
+    BUG_ON(pvh_info->nr_modules >= ARRAY_SIZE(pvh_mbi_mods));
+    pvh_mbi.mods_count = pvh_info->nr_modules;
+    pvh_mbi.mods_addr = __pa(pvh_mbi_mods);
+
+    entry = __va(pvh_info->modlist_paddr);
+    for ( i = 0; i < pvh_info->nr_modules; i++ )
+    {
+        BUG_ON(entry[i].paddr >> 32);
+        BUG_ON(entry[i].cmdline_paddr >> 32);
+
+        pvh_mbi_mods[i].mod_start = entry[i].paddr;
+        pvh_mbi_mods[i].mod_end   = entry[i].paddr + entry[i].size;
+        pvh_mbi_mods[i].string    = entry[i].cmdline_paddr;
+    }
+
+    rsdp_hint = pvh_info->rsdp_paddr;
+
+    *mbi = &pvh_mbi;
+    *mod = pvh_mbi_mods;
+}
+
+static void __init get_memory_map(void)
+{
+    struct xen_memory_map memmap = {
+        .nr_entries = E820MAX,
+    };
+
+    set_xen_guest_handle(memmap.buffer, e820_raw.map);
+    BUG_ON(xen_hypercall_memory_op(XENMEM_memory_map, &memmap));
+    e820_raw.nr_map = memmap.nr_entries;
+
+    /* :( Various toolstacks don't sort the memory map. */
+    sanitize_e820_map(e820_raw.map, &e820_raw.nr_map);
+}
+
+void __init pvh_init(multiboot_info_t **mbi, module_t **mod)
+{
+    convert_pvh_info(mbi, mod);
+
+    probe_hypervisor();
+    ASSERT(xen_guest);
+
+    get_memory_map();
+}
+
+void __init pvh_print_info(void)
+{
+    const struct hvm_start_info *pvh_info = __va(pvh_start_info_pa);
+    const struct hvm_modlist_entry *entry;
+    unsigned int i;
+
+    ASSERT(pvh_info->magic == XEN_HVM_START_MAGIC_VALUE);
+
+    printk("PVH start info: (pa %08x)\n", pvh_start_info_pa);
+    printk("  version:    %u\n", pvh_info->version);
+    printk("  flags:      %#"PRIx32"\n", pvh_info->flags);
+    printk("  nr_modules: %u\n", pvh_info->nr_modules);
+    printk("  modlist_pa: %016"PRIx64"\n", pvh_info->modlist_paddr);
+    printk("  cmdline_pa: %016"PRIx64"\n", pvh_info->cmdline_paddr);
+    if ( pvh_info->cmdline_paddr )
+        printk("  cmdline:    '%s'\n", (char *)__va(pvh_info->cmdline_paddr));
+    printk("  rsdp_pa:    %016"PRIx64"\n", pvh_info->rsdp_paddr);
+
+    entry = __va(pvh_info->modlist_paddr);
+    for ( i = 0; i < pvh_info->nr_modules; i++ )
+    {
+        printk("    mod[%u].pa:         %016"PRIx64"\n", i, entry[i].paddr);
+        printk("    mod[%u].size:       %016"PRIu64"\n", i, entry[i].size);
+        printk("    mod[%u].cmdline_pa: %016"PRIx64"\n",
+               i, entry[i].cmdline_paddr);
+        if ( entry[i].cmdline_paddr )
+            printk("    mod[%1u].cmdline:    '%s'\n", i,
+                   (char *)__va(entry[i].cmdline_paddr));
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/guest/xen/xen.c b/xen/arch/x86/guest/xen/xen.c
new file mode 100644
index 0000000000..a329e7c886
--- /dev/null
+++ b/xen/arch/x86/guest/xen/xen.c
@@ -0,0 +1,342 @@
+/******************************************************************************
+ * arch/x86/guest/xen.c
+ *
+ * Support for detecting and running under Xen.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (c) 2017 Citrix Systems Ltd.
+ */
+#include <xen/event.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/rangeset.h>
+#include <xen/types.h>
+#include <xen/pv_console.h>
+
+#include <asm/apic.h>
+#include <asm/e820.h>
+#include <asm/guest.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+#include <public/arch-x86/cpuid.h>
+#include <public/hvm/params.h>
+
+bool __read_mostly xen_guest;
+
+static __read_mostly uint32_t xen_cpuid_base;
+extern char hypercall_page[];
+static struct rangeset *mem;
+
+DEFINE_PER_CPU(unsigned int, vcpu_id);
+
+static struct vcpu_info *vcpu_info;
+static unsigned long vcpu_info_mapped[BITS_TO_LONGS(NR_CPUS)];
+DEFINE_PER_CPU(struct vcpu_info *, vcpu_info);
+
+static void __init find_xen_leaves(void)
+{
+    uint32_t eax, ebx, ecx, edx, base;
+
+    for ( base = XEN_CPUID_FIRST_LEAF;
+          base < XEN_CPUID_FIRST_LEAF + 0x10000; base += 0x100 )
+    {
+        cpuid(base, &eax, &ebx, &ecx, &edx);
+
+        if ( (ebx == XEN_CPUID_SIGNATURE_EBX) &&
+             (ecx == XEN_CPUID_SIGNATURE_ECX) &&
+             (edx == XEN_CPUID_SIGNATURE_EDX) &&
+             ((eax - base) >= 2) )
+        {
+            xen_cpuid_base = base;
+            break;
+        }
+    }
+}
+
+void __init probe_hypervisor(void)
+{
+    if ( xen_guest || !cpu_has_hypervisor )
+        return;
+
+    find_xen_leaves();
+
+    if ( !xen_cpuid_base )
+        return;
+
+    /* Fill the hypercall page. */
+    wrmsrl(cpuid_ebx(xen_cpuid_base + 2), __pa(hypercall_page));
+
+    xen_guest = true;
+}
+
+static void map_shared_info(void)
+{
+    mfn_t mfn;
+    struct xen_add_to_physmap xatp = {
+        .domid = DOMID_SELF,
+        .space = XENMAPSPACE_shared_info,
+    };
+    unsigned int i;
+    unsigned long rc;
+
+    if ( hypervisor_alloc_unused_page(&mfn) )
+        panic("unable to reserve shared info memory page\n");
+
+    xatp.gpfn = mfn_x(mfn);
+    rc = xen_hypercall_memory_op(XENMEM_add_to_physmap, &xatp);
+    if ( rc )
+        panic("failed to map shared_info page: %ld\n", rc);
+
+    set_fixmap(FIX_XEN_SHARED_INFO, mfn_x(mfn) << PAGE_SHIFT);
+
+    /* Mask all upcalls */
+    for ( i = 0; i < ARRAY_SIZE(XEN_shared_info->evtchn_mask); i++ )
+        write_atomic(&XEN_shared_info->evtchn_mask[i], ~0ul);
+}
+
+static int map_vcpuinfo(void)
+{
+    unsigned int vcpu = this_cpu(vcpu_id);
+    struct vcpu_register_vcpu_info info;
+    int rc;
+
+    if ( !vcpu_info )
+    {
+        this_cpu(vcpu_info) = &XEN_shared_info->vcpu_info[vcpu];
+        return 0;
+    }
+
+    if ( test_bit(vcpu, vcpu_info_mapped) )
+    {
+        this_cpu(vcpu_info) = &vcpu_info[vcpu];
+        return 0;
+    }
+
+    info.mfn = virt_to_mfn(&vcpu_info[vcpu]);
+    info.offset = (unsigned long)&vcpu_info[vcpu] & ~PAGE_MASK;
+    rc = xen_hypercall_vcpu_op(VCPUOP_register_vcpu_info, vcpu, &info);
+    if ( rc )
+    {
+        BUG_ON(vcpu >= XEN_LEGACY_MAX_VCPUS);
+        this_cpu(vcpu_info) = &XEN_shared_info->vcpu_info[vcpu];
+    }
+    else
+    {
+        this_cpu(vcpu_info) = &vcpu_info[vcpu];
+        set_bit(vcpu, vcpu_info_mapped);
+    }
+
+    return rc;
+}
+
+static void set_vcpu_id(void)
+{
+    uint32_t eax, ebx, ecx, edx;
+
+    ASSERT(xen_cpuid_base);
+
+    /* Fetch vcpu id from cpuid. */
+    cpuid(xen_cpuid_base + 4, &eax, &ebx, &ecx, &edx);
+    if ( eax & XEN_HVM_CPUID_VCPU_ID_PRESENT )
+        this_cpu(vcpu_id) = ebx;
+    else
+        this_cpu(vcpu_id) = smp_processor_id();
+}
+
+static void __init init_memmap(void)
+{
+    unsigned int i;
+
+    mem = rangeset_new(NULL, "host memory map", 0);
+    if ( !mem )
+        panic("failed to allocate PFN usage rangeset\n");
+
+    /*
+     * Mark up to the last memory page (or 4GiB) as RAM. This is done because
+     * Xen doesn't know the position of possible MMIO holes, so at least try to
+     * avoid the know MMIO hole below 4GiB. Note that this is subject to future
+     * discussion and improvements.
+     */
+    if ( rangeset_add_range(mem, 0, max_t(unsigned long, max_page - 1,
+                                          PFN_DOWN(GB(4) - 1))) )
+        panic("unable to add RAM to in-use PFN rangeset\n");
+
+    for ( i = 0; i < e820.nr_map; i++ )
+    {
+        struct e820entry *e = &e820.map[i];
+
+        if ( rangeset_add_range(mem, PFN_DOWN(e->addr),
+                                PFN_UP(e->addr + e->size - 1)) )
+            panic("unable to add range [%#lx, %#lx] to in-use PFN rangeset\n",
+                  PFN_DOWN(e->addr), PFN_UP(e->addr + e->size - 1));
+    }
+}
+
+static void xen_evtchn_upcall(struct cpu_user_regs *regs)
+{
+    struct vcpu_info *vcpu_info = this_cpu(vcpu_info);
+    unsigned long pending;
+
+    vcpu_info->evtchn_upcall_pending = 0;
+    pending = xchg(&vcpu_info->evtchn_pending_sel, 0);
+
+    while ( pending )
+    {
+        unsigned int l1 = find_first_set_bit(pending);
+        unsigned long evtchn = xchg(&XEN_shared_info->evtchn_pending[l1], 0);
+
+        __clear_bit(l1, &pending);
+        evtchn &= ~XEN_shared_info->evtchn_mask[l1];
+        while ( evtchn )
+        {
+            unsigned int port = find_first_set_bit(evtchn);
+
+            __clear_bit(port, &evtchn);
+            port += l1 * BITS_PER_LONG;
+
+            if ( pv_console && port == pv_console_evtchn() )
+                pv_console_rx(regs);
+            else if ( pv_shim )
+                pv_shim_inject_evtchn(port);
+        }
+    }
+
+    ack_APIC_irq();
+}
+
+static void init_evtchn(void)
+{
+    static uint8_t evtchn_upcall_vector;
+    int rc;
+
+    if ( !evtchn_upcall_vector )
+        alloc_direct_apic_vector(&evtchn_upcall_vector, xen_evtchn_upcall);
+
+    ASSERT(evtchn_upcall_vector);
+
+    rc = xen_hypercall_set_evtchn_upcall_vector(this_cpu(vcpu_id),
+                                                evtchn_upcall_vector);
+    if ( rc )
+        panic("Unable to set evtchn upcall vector: %d\n", rc);
+
+    /* Trick toolstack to think we are enlightened */
+    {
+        struct xen_hvm_param a = {
+            .domid = DOMID_SELF,
+            .index = HVM_PARAM_CALLBACK_IRQ,
+            .value = 1,
+        };
+
+        BUG_ON(xen_hypercall_hvm_op(HVMOP_set_param, &a));
+    }
+}
+
+void __init hypervisor_setup(void)
+{
+    init_memmap();
+
+    map_shared_info();
+
+    set_vcpu_id();
+    vcpu_info = xzalloc_array(struct vcpu_info, nr_cpu_ids);
+    if ( map_vcpuinfo() )
+    {
+        xfree(vcpu_info);
+        vcpu_info = NULL;
+    }
+    if ( !vcpu_info && nr_cpu_ids > XEN_LEGACY_MAX_VCPUS )
+    {
+        unsigned int i;
+
+        for ( i = XEN_LEGACY_MAX_VCPUS; i < nr_cpu_ids; i++ )
+            __cpumask_clear_cpu(i, &cpu_present_map);
+        nr_cpu_ids = XEN_LEGACY_MAX_VCPUS;
+        printk(XENLOG_WARNING
+               "unable to map vCPU info, limiting vCPUs to: %u\n",
+               XEN_LEGACY_MAX_VCPUS);
+    }
+
+    init_evtchn();
+}
+
+void hypervisor_ap_setup(void)
+{
+    set_vcpu_id();
+    map_vcpuinfo();
+    init_evtchn();
+}
+
+int hypervisor_alloc_unused_page(mfn_t *mfn)
+{
+    unsigned long m;
+    int rc;
+
+    rc = rangeset_claim_range(mem, 1, &m);
+    if ( !rc )
+        *mfn = _mfn(m);
+
+    return rc;
+}
+
+int hypervisor_free_unused_page(mfn_t mfn)
+{
+    return rangeset_remove_range(mem, mfn_x(mfn), mfn_x(mfn));
+}
+
+uint32_t hypervisor_cpuid_base(void)
+{
+    return xen_cpuid_base;
+}
+
+static void ap_resume(void *unused)
+{
+    map_vcpuinfo();
+    init_evtchn();
+}
+
+void hypervisor_resume(void)
+{
+    /* Reset shared info page. */
+    map_shared_info();
+
+    /*
+     * Reset vcpu_info. Just clean the mapped bitmap and try to map the vcpu
+     * area again. On failure to map (when it was previously mapped) panic
+     * since it's impossible to safely shut down running guest vCPUs in order
+     * to meet the new XEN_LEGACY_MAX_VCPUS requirement.
+     */
+    bitmap_zero(vcpu_info_mapped, NR_CPUS);
+    if ( map_vcpuinfo() && nr_cpu_ids > XEN_LEGACY_MAX_VCPUS )
+        panic("unable to remap vCPU info and vCPUs > legacy limit\n");
+
+    /* Setup event channel upcall vector. */
+    init_evtchn();
+    smp_call_function(ap_resume, NULL, 1);
+
+    if ( pv_console )
+        pv_console_init();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.