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 <stefano.stabellini@eu.citrix.com> Signed-off-by: Julien Grall <julien.grall@linaro.org> Acked-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
81e863c3a2
commit
5882bfef63
|
@ -1,6 +1,8 @@
|
||||||
#ifndef _ASM_ARM_XEN_HYPERVISOR_H
|
#ifndef _ASM_ARM_XEN_HYPERVISOR_H
|
||||||
#define _ASM_ARM_XEN_HYPERVISOR_H
|
#define _ASM_ARM_XEN_HYPERVISOR_H
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
extern struct shared_info *HYPERVISOR_shared_info;
|
extern struct shared_info *HYPERVISOR_shared_info;
|
||||||
extern struct start_info *xen_start_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;
|
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 */
|
#endif /* _ASM_ARM_XEN_HYPERVISOR_H */
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cachetype.h>
|
#include <asm/cachetype.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
|
#include <asm/xen/hypervisor.h>
|
||||||
|
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
|
@ -951,6 +952,7 @@ void __init setup_arch(char **cmdline_p)
|
||||||
|
|
||||||
arm_dt_init_cpu_maps();
|
arm_dt_init_cpu_maps();
|
||||||
psci_init();
|
psci_init();
|
||||||
|
xen_early_init();
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
if (is_smp()) {
|
if (is_smp()) {
|
||||||
if (!mdesc->smp_init || !mdesc->smp_init()) {
|
if (!mdesc->smp_init || !mdesc->smp_init()) {
|
||||||
|
|
|
@ -53,6 +53,8 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
|
||||||
|
|
||||||
static __read_mostly unsigned int xen_events_irq;
|
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,
|
int xen_remap_domain_mfn_array(struct vm_area_struct *vma,
|
||||||
unsigned long addr,
|
unsigned long addr,
|
||||||
xen_pfn_t *mfn, int nr,
|
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.
|
* documentation of the Xen Device Tree format.
|
||||||
*/
|
*/
|
||||||
#define GRANT_TABLE_PHYSADDR 0
|
#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;
|
int len;
|
||||||
const char *s = NULL;
|
const char *s = NULL;
|
||||||
const char *version = NULL;
|
const char *version = NULL;
|
||||||
const char *xen_prefix = "xen,xen-";
|
const char *xen_prefix = "xen,xen-";
|
||||||
struct resource res;
|
|
||||||
phys_addr_t grant_frames;
|
|
||||||
|
|
||||||
node = of_find_compatible_node(NULL, NULL, "xen,xen");
|
xen_node = of_find_compatible_node(NULL, NULL, "xen,xen");
|
||||||
if (!node) {
|
if (!xen_node) {
|
||||||
pr_debug("No Xen support\n");
|
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 &&
|
if (strlen(xen_prefix) + 3 < len &&
|
||||||
!strncmp(xen_prefix, s, strlen(xen_prefix)))
|
!strncmp(xen_prefix, s, strlen(xen_prefix)))
|
||||||
version = s + strlen(xen_prefix);
|
version = s + strlen(xen_prefix);
|
||||||
if (version == NULL) {
|
if (version == NULL) {
|
||||||
pr_debug("Xen version not found\n");
|
pr_debug("Xen version not found\n");
|
||||||
return 0;
|
return;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_info("Xen %s support found, events_irq=%d gnttab_frame=%pa\n",
|
pr_info("Xen %s support found\n", version);
|
||||||
version, xen_events_irq, &grant_frames);
|
|
||||||
|
|
||||||
xen_domain_type = XEN_HVM_DOMAIN;
|
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;
|
xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED;
|
||||||
else
|
else
|
||||||
xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED);
|
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) {
|
if (!shared_info_page) {
|
||||||
pr_err("not enough memory\n");
|
pr_err("not enough memory\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include <asm/psci.h>
|
#include <asm/psci.h>
|
||||||
#include <asm/efi.h>
|
#include <asm/efi.h>
|
||||||
#include <asm/virt.h>
|
#include <asm/virt.h>
|
||||||
|
#include <asm/xen/hypervisor.h>
|
||||||
|
|
||||||
unsigned long elf_hwcap __read_mostly;
|
unsigned long elf_hwcap __read_mostly;
|
||||||
EXPORT_SYMBOL_GPL(elf_hwcap);
|
EXPORT_SYMBOL_GPL(elf_hwcap);
|
||||||
|
@ -416,6 +417,7 @@ void __init setup_arch(char **cmdline_p)
|
||||||
psci_acpi_init();
|
psci_acpi_init();
|
||||||
acpi_init_cpus();
|
acpi_init_cpus();
|
||||||
}
|
}
|
||||||
|
xen_early_init();
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
smp_build_mpidr_hash();
|
smp_build_mpidr_hash();
|
||||||
|
|
Loading…
Reference in New Issue