From 5882bfef6327093bff63569be19795170ff71e5f Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Wed, 6 May 2015 14:13:31 +0000 Subject: [PATCH] arm,arm64/xen: move Xen initialization earlier Currently, Xen is initialized/discovered in an initcall. This doesn't allow us to support earlyprintk or choosing the preferred console when running on Xen. The current function xen_guest_init is now split in 2 parts: - xen_early_init: Check if there is a Xen node in the device tree and setup domain type - xen_guest_init: Retrieve the information from the device node and initialize Xen (grant table, shared page...) The former is called in setup_arch, while the latter is an initcall. Signed-off-by: Stefano Stabellini Signed-off-by: Julien Grall Acked-by: Ian Campbell Acked-by: Will Deacon --- arch/arm/include/asm/xen/hypervisor.h | 8 ++++ arch/arm/kernel/setup.c | 2 + arch/arm/xen/enlighten.c | 58 ++++++++++++++++----------- arch/arm64/kernel/setup.c | 2 + 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/arch/arm/include/asm/xen/hypervisor.h b/arch/arm/include/asm/xen/hypervisor.h index 1317ee40f4df..04ff8e7b37df 100644 --- a/arch/arm/include/asm/xen/hypervisor.h +++ b/arch/arm/include/asm/xen/hypervisor.h @@ -1,6 +1,8 @@ #ifndef _ASM_ARM_XEN_HYPERVISOR_H #define _ASM_ARM_XEN_HYPERVISOR_H +#include + extern struct shared_info *HYPERVISOR_shared_info; extern struct start_info *xen_start_info; @@ -18,4 +20,10 @@ static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void) extern struct dma_map_ops *xen_dma_ops; +#ifdef CONFIG_XEN +void __init xen_early_init(void); +#else +static inline void xen_early_init(void) { return; } +#endif + #endif /* _ASM_ARM_XEN_HYPERVISOR_H */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6c777e908a24..aa9bfebe113f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -951,6 +952,7 @@ void __init setup_arch(char **cmdline_p) arm_dt_init_cpu_maps(); psci_init(); + xen_early_init(); #ifdef CONFIG_SMP if (is_smp()) { if (!mdesc->smp_init || !mdesc->smp_init()) { diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 6fbdc8fa4a19..3463a9e1ff65 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -53,6 +53,8 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); static __read_mostly unsigned int xen_events_irq; +static __initdata struct device_node *xen_node; + int xen_remap_domain_mfn_array(struct vm_area_struct *vma, unsigned long addr, xen_pfn_t *mfn, int nr, @@ -150,42 +152,28 @@ static irqreturn_t xen_arm_callback(int irq, void *arg) * documentation of the Xen Device Tree format. */ #define GRANT_TABLE_PHYSADDR 0 -static int __init xen_guest_init(void) +void __init xen_early_init(void) { - struct xen_add_to_physmap xatp; - static struct shared_info *shared_info_page = 0; - struct device_node *node; int len; const char *s = NULL; const char *version = NULL; const char *xen_prefix = "xen,xen-"; - struct resource res; - phys_addr_t grant_frames; - node = of_find_compatible_node(NULL, NULL, "xen,xen"); - if (!node) { + xen_node = of_find_compatible_node(NULL, NULL, "xen,xen"); + if (!xen_node) { pr_debug("No Xen support\n"); - return 0; + return; } - s = of_get_property(node, "compatible", &len); + s = of_get_property(xen_node, "compatible", &len); if (strlen(xen_prefix) + 3 < len && !strncmp(xen_prefix, s, strlen(xen_prefix))) version = s + strlen(xen_prefix); if (version == NULL) { pr_debug("Xen version not found\n"); - return 0; - } - if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res)) - return 0; - grant_frames = res.start; - xen_events_irq = irq_of_parse_and_map(node, 0); - if (!xen_events_irq) { - pr_debug("Xen event channel interrupt not found\n"); - return -ENODEV; + return; } - pr_info("Xen %s support found, events_irq=%d gnttab_frame=%pa\n", - version, xen_events_irq, &grant_frames); + pr_info("Xen %s support found\n", version); xen_domain_type = XEN_HVM_DOMAIN; @@ -195,10 +183,32 @@ static int __init xen_guest_init(void) xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; else xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED); +} + +static int __init xen_guest_init(void) +{ + struct xen_add_to_physmap xatp; + struct shared_info *shared_info_page = NULL; + struct resource res; + phys_addr_t grant_frames; + + if (!xen_domain()) + return 0; + + if (of_address_to_resource(xen_node, GRANT_TABLE_PHYSADDR, &res)) { + pr_err("Xen grant table base address not found\n"); + return -ENODEV; + } + grant_frames = res.start; + + xen_events_irq = irq_of_parse_and_map(xen_node, 0); + if (!xen_events_irq) { + pr_err("Xen event channel interrupt not found\n"); + return -ENODEV; + } + + shared_info_page = (struct shared_info *)get_zeroed_page(GFP_KERNEL); - if (!shared_info_page) - shared_info_page = (struct shared_info *) - get_zeroed_page(GFP_KERNEL); if (!shared_info_page) { pr_err("not enough memory\n"); return -ENOMEM; diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 74753132c3ac..1b36ba9b73ac 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -64,6 +64,7 @@ #include #include #include +#include unsigned long elf_hwcap __read_mostly; EXPORT_SYMBOL_GPL(elf_hwcap); @@ -416,6 +417,7 @@ void __init setup_arch(char **cmdline_p) psci_acpi_init(); acpi_init_cpus(); } + xen_early_init(); #ifdef CONFIG_SMP smp_build_mpidr_hash();