aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Grall <julien.grall@linaro.org>2013-04-26 19:53:17 +0100
committerIan Campbell <ian.campbell@citrix.com>2013-05-13 11:59:59 +0100
commit699f48cd134f6cf92375f0b00fcb67cffc8f40b4 (patch)
tree260a846362104c913ed0305ecd5a5a6f30d8a56d
parentf5bde3da40ea79cbd4a1ab4de28e46e338bf7486 (diff)
downloadxen-699f48cd134f6cf92375f0b00fcb67cffc8f40b4.tar.gz
xen-699f48cd134f6cf92375f0b00fcb67cffc8f40b4.tar.bz2
xen-699f48cd134f6cf92375f0b00fcb67cffc8f40b4.zip
xen/arm: Don't hardcode VGIC informations
- Define VGIC base address per domain. For the moment the base addresses to dom0 base addresses. - The number of interrupt lines (ie number of SPIs) is equal to: * 0 for guests * number of host SPIs for dom0 Signed-off-by: Julien Grall <julien.grall@linaro.org> Acked-by: Ian Campbell <ian.campbell@citrix.com>
-rw-r--r--xen/arch/arm/gic.c21
-rw-r--r--xen/arch/arm/vgic.c20
-rw-r--r--xen/include/asm-arm/domain.h5
-rw-r--r--xen/include/asm-arm/gic.h3
4 files changed, 39 insertions, 10 deletions
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index f69f86a69b..821f6836bf 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -56,6 +56,11 @@ static DEFINE_PER_CPU(uint64_t, lr_mask);
static unsigned nr_lrs;
+unsigned int gic_number_lines(void)
+{
+ return gic.lines;
+}
+
irq_desc_t *__irq_to_desc(int irq)
{
if (irq < NR_LOCAL_IRQS) return &this_cpu(local_irq_desc)[irq];
@@ -775,11 +780,21 @@ 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
+ */
+ d->arch.vgic.dbase = gic.dbase;
+ d->arch.vgic.cbase = gic.cbase;
+
+
+ d->arch.vgic.nr_lines = 0;
+
/* map the gic virtual cpu interface in the gic cpu interface region of
* the guest */
- return map_mmio_regions(d, gic.cbase,
- gic.cbase + (2 * PAGE_SIZE) - 1,
- gic.vbase);
+ return map_mmio_regions(d, d->arch.vgic.cbase,
+ d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
+ gic.vbase);
}
static void gic_irq_eoi(void *info)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index f9c1a6b26e..7eaccb7eee 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -30,8 +30,6 @@
#include "io.h"
#include <asm/gic.h>
-#define VGIC_DISTR_BASE_ADDRESS 0x000000002c001000
-
#define REG(n) (n/4)
/* Number of ranks of interrupt registers for a domain */
@@ -80,7 +78,15 @@ int domain_vgic_init(struct domain *d)
int i;
d->arch.vgic.ctlr = 0;
- d->arch.vgic.nr_lines = 32;
+
+ /* Currently nr_lines in vgic and gic doesn't have the same meanings
+ * Here nr_lines = number of SPIs
+ */
+ if ( d->domain_id == 0 )
+ d->arch.vgic.nr_lines = gic_number_lines() - 32;
+ else
+ d->arch.vgic.nr_lines = 0; /* We don't need SPIs for the guest */
+
d->arch.vgic.shared_irqs =
xmalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d));
d->arch.vgic.pending_irqs =
@@ -163,7 +169,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
struct cpu_user_regs *regs = guest_cpu_user_regs();
register_t *r = select_user_reg(regs, dabt.reg);
struct vgic_irq_rank *rank;
- int offset = (int)(info->gpa - VGIC_DISTR_BASE_ADDRESS);
+ int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
int gicd_reg = REG(offset);
switch ( gicd_reg )
@@ -440,7 +446,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
struct cpu_user_regs *regs = guest_cpu_user_regs();
register_t *r = select_user_reg(regs, dabt.reg);
struct vgic_irq_rank *rank;
- int offset = (int)(info->gpa - VGIC_DISTR_BASE_ADDRESS);
+ int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
int gicd_reg = REG(offset);
uint32_t tr;
@@ -620,7 +626,9 @@ write_ignore:
static int vgic_distr_mmio_check(struct vcpu *v, paddr_t addr)
{
- return addr >= VGIC_DISTR_BASE_ADDRESS && addr < (VGIC_DISTR_BASE_ADDRESS+PAGE_SIZE);
+ struct domain *d = v->domain;
+
+ return (addr >= (d->arch.vgic.dbase)) && (addr < (d->arch.vgic.dbase + PAGE_SIZE));
}
const struct mmio_handler vgic_distr_mmio_handler = {
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index cca7416f31..cb251cc250 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -88,13 +88,16 @@ struct arch_domain
*/
spinlock_t lock;
int ctlr;
- int nr_lines;
+ int nr_lines; /* Number of SPIs */
struct vgic_irq_rank *shared_irqs;
/*
* SPIs are domain global, SGIs and PPIs are per-VCPU and stored in
* struct arch_vcpu.
*/
struct pending_irq *pending_irqs;
+ /* Base address for guest GIC */
+ paddr_t dbase; /* Distributor base address */
+ paddr_t cbase; /* CPU base address */
} vgic;
struct vpl011 {
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 6ff217c231..e7608dc00b 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -189,6 +189,9 @@ extern void send_SGI_allbutself(enum gic_sgi sgi);
/* print useful debug info */
extern void gic_dump_info(struct vcpu *v);
+/* Number of interrupt lines */
+extern unsigned int gic_number_lines(void);
+
/* IRQ translation function for the device tree */
int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
unsigned int *out_hwirq, unsigned int *out_type);