*/
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;
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
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
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);
}
/*
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"
*
* 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);
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;
if ( np == dt_host )
{
- res = make_hypervisor_node(kinfo->fdt, np);
+ res = make_hypervisor_node(d, kinfo->fdt, np);
if ( res )
return res;
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())
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;
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 */
} arm_psci_t;
#define PSCI(_name, _nr_args) \
- [ __PSCI_ ## _name ] = { \
+ [ PSCI_ ## _name ] = { \
.fn = (arm_psci_fn_t) &do_psci_ ## _name, \
.nr_args = _nr_args, \
}
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;
spinlock_t lock;
} vuart;
+ unsigned int evtchn_irq;
} __cacheline_aligned;
struct arch_vcpu
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
#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 <xen/device_tree.h>
#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 */
#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);
#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
#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
#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__ */