|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |