diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c index df59ffb84c..9f3fdd39ec 100644 --- a/tools/libxc/xc_dom_arm.c +++ b/tools/libxc/xc_dom_arm.c @@ -126,13 +126,13 @@ static int vcpu_arm(struct xc_dom_image *dom, void *ptr) */ ctxt->user_regs.r2_usr = 0xffffffff; - ctxt->sctlr = /* #define SCTLR_BASE */0x00c50078; + ctxt->sctlr = SCTLR_GUEST_INIT; ctxt->ttbr0 = 0; ctxt->ttbr1 = 0; ctxt->ttbcr = 0; /* Defined Reset Value */ - ctxt->user_regs.cpsr = PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC; + ctxt->user_regs.cpsr = PSR_GUEST32_INIT; ctxt->flags = VGCF_online; diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 5ff7adfd9b..2f57d019e2 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -461,7 +461,8 @@ int vcpu_initialise(struct vcpu *v) if ( is_idle_vcpu(v) ) return rc; - v->arch.sctlr = SCTLR_BASE; + v->arch.sctlr = SCTLR_GUEST_INIT; + /* * By default exposes an SMP system with AFF0 set to the VCPU ID * TODO: Handle multi-threading processor and cluster @@ -525,6 +526,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) if ( (rc = vcpu_domain_init(d)) != 0 ) goto fail; + /* XXX dom0 needs more intelligent selection of PPI */ + d->arch.evtchn_irq = GUEST_EVTCHN_PPI; + /* * Virtual UART is only used by linux early printk and decompress code. * Only use it for dom0 because the linux kernel may not support @@ -740,7 +744,7 @@ void vcpu_mark_events_pending(struct vcpu *v) if ( already_pending ) return; - vgic_vcpu_inject_irq(v, VGIC_IRQ_EVTCHN_CALLBACK, 1); + vgic_vcpu_inject_irq(v, v->domain->arch.evtchn_irq, 1); } /* diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 4014b0ae9f..aa7e3d2937 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -333,7 +333,8 @@ static int make_memory_node(const struct domain *d, return res; } -static int make_hypervisor_node(void *fdt, const struct dt_device_node *parent) +static int make_hypervisor_node(struct domain *d, + void *fdt, const struct dt_device_node *parent) { const char compat[] = "xen,xen-"__stringify(XEN_VERSION)"."__stringify(XEN_SUBVERSION)"\0" @@ -381,8 +382,8 @@ static int make_hypervisor_node(void *fdt, const struct dt_device_node *parent) * * TODO: Handle correctly the cpumask */ - DPRINT(" Event channel interrupt to %u\n", VGIC_IRQ_EVTCHN_CALLBACK); - set_interrupt_ppi(intr, VGIC_IRQ_EVTCHN_CALLBACK, 0xf, + DPRINT(" Event channel interrupt to %u\n", d->arch.evtchn_irq); + set_interrupt_ppi(intr, d->arch.evtchn_irq, 0xf, DT_IRQ_TYPE_LEVEL_LOW); res = fdt_property_interrupts(fdt, &intr, 1); @@ -413,11 +414,11 @@ static int make_psci_node(void *fdt, const struct dt_device_node *parent) if ( res ) return res; - res = fdt_property_cell(fdt, "cpu_off", __PSCI_cpu_off); + res = fdt_property_cell(fdt, "cpu_off", PSCI_cpu_off); if ( res ) return res; - res = fdt_property_cell(fdt, "cpu_on", __PSCI_cpu_on); + res = fdt_property_cell(fdt, "cpu_on", PSCI_cpu_on); if ( res ) return res; @@ -855,7 +856,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo, if ( np == dt_host ) { - res = make_hypervisor_node(kinfo->fdt, np); + res = make_hypervisor_node(d, kinfo->fdt, np); if ( res ) return res; diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 74575cda7a..33c6b8d1ac 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -717,7 +717,7 @@ int gic_events_need_delivery(void) void gic_inject(void) { if ( vcpu_info(current, evtchn_upcall_pending) ) - vgic_vcpu_inject_irq(current, VGIC_IRQ_EVTCHN_CALLBACK, 1); + vgic_vcpu_inject_irq(current, current->domain->arch.evtchn_irq, 1); gic_restore_pending_irqs(current); if (!gic_events_need_delivery()) @@ -823,13 +823,20 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq) int gicv_setup(struct domain *d) { - /* TODO: Retrieve distributor and CPU guest base address from the - * guest DTS - * For the moment we use dom0 DTS + /* + * Domain 0 gets the hardware address. + * Guests get the virtual platform layout. */ - d->arch.vgic.dbase = gic.dbase; - d->arch.vgic.cbase = gic.cbase; - + if ( d == dom0 ) + { + d->arch.vgic.dbase = gic.dbase; + d->arch.vgic.cbase = gic.cbase; + } + else + { + d->arch.vgic.dbase = GUEST_GICD_BASE; + d->arch.vgic.cbase = GUEST_GICC_BASE; + } d->arch.vgic.nr_lines = 0; diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c index 6c3be47c69..c82884f805 100644 --- a/xen/arch/arm/psci.c +++ b/xen/arch/arm/psci.c @@ -43,7 +43,7 @@ int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point) memset(ctxt, 0, sizeof(*ctxt)); ctxt->user_regs.pc64 = (u64) entry_point; - ctxt->sctlr = SCTLR_BASE; + ctxt->sctlr = SCTLR_GUEST_INIT; ctxt->ttbr0 = 0; ctxt->ttbr1 = 0; ctxt->ttbcr = 0; /* Defined Reset Value */ diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 10ee498527..d39e2d4489 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -867,7 +867,7 @@ typedef struct { } arm_psci_t; #define PSCI(_name, _nr_args) \ - [ __PSCI_ ## _name ] = { \ + [ PSCI_ ## _name ] = { \ .fn = (arm_psci_fn_t) &do_psci_ ## _name, \ .nr_args = _nr_args, \ } diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c index d58a630ad8..f323453071 100644 --- a/xen/arch/arm/vtimer.c +++ b/xen/arch/arm/vtimer.c @@ -54,21 +54,26 @@ int vcpu_domain_init(struct domain *d) int vcpu_vtimer_init(struct vcpu *v) { struct vtimer *t = &v->arch.phys_timer; + bool_t d0 = (v->domain == dom0); - /* TODO: Retrieve physical and virtual timer IRQ from the guest - * DT. For the moment we use dom0 DT + /* + * Domain 0 uses the hardware interrupts, guests get the virtual platform. */ init_timer(&t->timer, phys_timer_expired, t, v->processor); t->ctl = 0; t->cval = NOW(); - t->irq = timer_dt_irq(TIMER_PHYS_NONSECURE_PPI)->irq; + t->irq = d0 + ? timer_dt_irq(TIMER_PHYS_NONSECURE_PPI)->irq + : GUEST_TIMER_PHYS_NS_PPI; t->v = v; t = &v->arch.virt_timer; init_timer(&t->timer, virt_timer_expired, t, v->processor); t->ctl = 0; - t->irq = timer_dt_irq(TIMER_VIRT_PPI)->irq; + t->irq = d0 + ? timer_dt_irq(TIMER_VIRT_PPI)->irq + : GUEST_TIMER_VIRT_PPI; t->v = v; return 0; diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 67bfbbc29e..d5cae2eb94 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -112,6 +112,7 @@ struct arch_domain spinlock_t lock; } vuart; + unsigned int evtchn_irq; } __cacheline_aligned; struct arch_vcpu diff --git a/xen/include/asm-arm/event.h b/xen/include/asm-arm/event.h index 04d854fa62..dd3ad13da4 100644 --- a/xen/include/asm-arm/event.h +++ b/xen/include/asm-arm/event.h @@ -15,7 +15,8 @@ static inline int vcpu_event_delivery_is_enabled(struct vcpu *v) static inline int local_events_need_delivery_nomask(void) { - struct pending_irq *p = irq_to_pending(current, VGIC_IRQ_EVTCHN_CALLBACK); + struct pending_irq *p = irq_to_pending(current, + current->domain->arch.evtchn_irq); /* XXX: if the first interrupt has already been delivered, we should * check whether any other interrupts with priority higher than the diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index 0a890bea0b..41f0b3be87 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -129,9 +129,6 @@ #define GICH_LR_CPUID_SHIFT 9 #define GICH_VTR_NRLRGS 0x3f -/* XXX: write this into the DT */ -#define VGIC_IRQ_EVTCHN_CALLBACK 31 - #ifndef __ASSEMBLY__ #include diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index 529442152e..3da3a3dc90 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -48,15 +48,8 @@ #define SCTLR_A (1<<1) #define SCTLR_M (1<<0) -#define SCTLR_BASE 0x00c50078 #define HSCTLR_BASE 0x30c51878 -#define PSR_GUEST32_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC) - -#ifdef CONFIG_ARM_64 -#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h) -#endif - /* HCR Hyp Configuration Register */ #define HCR_RW (1<<31) /* Register Width, ARM64 only */ #define HCR_TGE (1<<27) /* Trap General Exceptions */ diff --git a/xen/include/asm-arm/psci.h b/xen/include/asm-arm/psci.h index fdba636752..67d4c35f71 100644 --- a/xen/include/asm-arm/psci.h +++ b/xen/include/asm-arm/psci.h @@ -6,11 +6,6 @@ #define PSCI_EINVAL -2 #define PSCI_DENIED -3 -#define __PSCI_cpu_suspend 0 -#define __PSCI_cpu_off 1 -#define __PSCI_cpu_on 2 -#define __PSCI_migrate 3 - int do_psci_cpu_on(uint32_t vcpuid, register_t entry_point); int do_psci_cpu_off(uint32_t power_state); int do_psci_cpu_suspend(uint32_t power_state, register_t entry_point); diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 1e8aeda19d..cb41ddc460 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -302,8 +302,19 @@ typedef uint64_t xen_callback_t; #endif +#if defined(__XEN__) || defined(__XEN_TOOLS__) + /* PSR bits (CPSR, SPSR)*/ +#define PSR_THUMB (1<<5) /* Thumb Mode enable */ +#define PSR_FIQ_MASK (1<<6) /* Fast Interrupt mask */ +#define PSR_IRQ_MASK (1<<7) /* Interrupt mask */ +#define PSR_ABT_MASK (1<<8) /* Asynchronous Abort mask */ +#define PSR_BIG_ENDIAN (1<<9) /* arm32: Big Endian Mode */ +#define PSR_DBG_MASK (1<<9) /* arm64: Debug Exception mask */ +#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */ +#define PSR_JAZELLE (1<<24) /* Jazelle Mode */ + /* 32 bit modes */ #define PSR_MODE_USR 0x10 #define PSR_MODE_FIQ 0x11 @@ -316,7 +327,6 @@ typedef uint64_t xen_callback_t; #define PSR_MODE_SYS 0x1f /* 64 bit modes */ -#ifdef __aarch64__ #define PSR_MODE_BIT 0x10 /* Set iff AArch32 */ #define PSR_MODE_EL3h 0x0d #define PSR_MODE_EL3t 0x0c @@ -325,18 +335,44 @@ typedef uint64_t xen_callback_t; #define PSR_MODE_EL1h 0x05 #define PSR_MODE_EL1t 0x04 #define PSR_MODE_EL0t 0x00 -#endif -#define PSR_THUMB (1<<5) /* Thumb Mode enable */ -#define PSR_FIQ_MASK (1<<6) /* Fast Interrupt mask */ -#define PSR_IRQ_MASK (1<<7) /* Interrupt mask */ -#define PSR_ABT_MASK (1<<8) /* Asynchronous Abort mask */ -#define PSR_BIG_ENDIAN (1<<9) /* Big Endian Mode */ -#ifdef __aarch64__ /* For Aarch64 bit 9 is repurposed. */ -#define PSR_DBG_MASK (1<<9) +#define PSR_GUEST32_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC) +#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h) + +#define SCTLR_GUEST_INIT 0x00c50078 + +/* + * Virtual machine platform (memory layout, interrupts) + * + * These are defined for consistency between the tools and the + * hypervisor. Guests must not rely on these hardcoded values but + * should instead use the FDT. + */ + +/* Physical Address Space */ +#define GUEST_GICD_BASE 0x2c001000ULL +#define GUEST_GICD_SIZE 0x1000ULL +#define GUEST_GICC_BASE 0x2c002000ULL +#define GUEST_GICC_SIZE 0x100ULL + +#define GUEST_RAM_BASE 0x80000000ULL + +#define GUEST_GNTTAB_BASE 0xb0000000ULL +#define GUEST_GNTTAB_SIZE 0x00020000ULL + +/* Interrupts */ +#define GUEST_TIMER_VIRT_PPI 27 +#define GUEST_TIMER_PHYS_S_PPI 29 +#define GUEST_TIMER_PHYS_NS_PPI 30 +#define GUEST_EVTCHN_PPI 31 + +/* PSCI functions */ +#define PSCI_cpu_suspend 0 +#define PSCI_cpu_off 1 +#define PSCI_cpu_on 2 +#define PSCI_migrate 3 + #endif -#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */ -#define PSR_JAZELLE (1<<24) /* Jazelle Mode */ #endif /* __XEN_PUBLIC_ARCH_ARM_H__ */