Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 0/11] xen/arm: event channels and shared_info page
Hi all, this patch series implements support for injecting event channels into the guest and enables a wider range of hypercalls for ARM guests. In order to allow more flexibility I modified the hypercall protocol, in particular the hypercall number is not passed as imm to hvc anymore, because we might not always know it at compile time. The hypercall number is now passed on the r12 register. With this patch series and using the following Linux tree: git://xenbits.xen.org/people/sstabellini/linux-pvhvm.git vexpress-dt-privcmd-2 I am able to boot dom0, start xenstored and run basic xl commands, like "xl list" and "xl uptime". I have added at the beginning of this series few patches that were previously sent separately (in particular "arm: support fewer LR registers than virtual irqs"). Changes in v3: - several fixes to "support fewer LR registers than virtual irqs"; - many more comments to the gic and vgic IRQ queues; - merge Ian''s patch into "shared_info page allocation and mapping"; - do not alloc the shared_info page for the idle domain; - added "handle dom0_max_vcpus=0 case properly" by Ian, removed the corresponding patch in my series; - move XEN_HYPERCALL_TAG to a public header; - clobber register in the debug build; - document calling convention; - check if arm_hypercall_table[regs->r12] != NULL; - use a PPI for events injection (IRQ 31) and do not request maintenance interrupts for it whenever possible. Changes in v2: - fixed tabs/spaces problem. Ian Campbell (1): arm: handle dom0_max_vcpus=0 case properly Stefano Stabellini (10): arm: rename link to inflight arm: fix inflight_irqs list priority ordering arm: support fewer LR registers than virtual irqs arm: replace list_del and INIT_LIST_HEAD with list_del_init arm: shared_info page allocation and mapping arm: use r12 to pass the hypercall number arm: introduce more hypercalls arm: implement flush_tlb_all_local and flush_tlb_local arm: remove VGIC_SOFTIRQ arm: implement event injection xen/arch/arm/Makefile | 1 + xen/arch/arm/domain.c | 22 ++++++ xen/arch/arm/domain_build.c | 11 ++-- xen/arch/arm/dummy.S | 1 - xen/arch/arm/gic.c | 151 ++++++++++++++++++++++++++++++++------- xen/arch/arm/gic.h | 7 ++- xen/arch/arm/mm.c | 98 ++++++++++++++++++++++++- xen/arch/arm/p2m.c | 26 +++++++- xen/arch/arm/physdev.c | 27 +++++++ xen/arch/arm/traps.c | 40 +++++++--- xen/arch/arm/vgic.c | 27 ++------ xen/include/asm-arm/config.h | 2 + xen/include/asm-arm/domain.h | 14 ++++- xen/include/asm-arm/flushtlb.h | 23 ++++++- xen/include/asm-arm/hypercall.h | 1 + xen/include/asm-arm/mm.h | 4 + xen/include/asm-arm/p2m.h | 9 +++ xen/include/asm-arm/paging.h | 3 + xen/include/asm-arm/softirq.h | 3 +- xen/include/public/arch-arm.h | 21 ++++++ 20 files changed, 415 insertions(+), 76 deletions(-) A git branch based on my previous gic and tools patches is available here: git://xenbits.xen.org/people/sstabellini/xen-unstable.git events-3 Cheers, Stefano
The link field in pending_irq has a confusing name so rename it to inflight and comment its behaviour. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/gic.c | 4 ++-- xen/arch/arm/vgic.c | 10 +++++----- xen/include/asm-arm/domain.h | 4 +++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index adc10bb..120ec82 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -450,8 +450,8 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r GICC[GICC_DIR] = virq; } gic_inject_irq_stop(); - list_del(&p->link); - INIT_LIST_HEAD(&p->link); + list_del(&p->inflight); + INIT_LIST_HEAD(&p->inflight); cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); spin_unlock(¤t->arch.vgic.lock); } diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 584e682..dd99629 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -85,7 +85,7 @@ int domain_vgic_init(struct domain *d) xmalloc_array(struct pending_irq, d->arch.vgic.nr_lines + (32 * d->max_vcpus)); for (i=0; i<d->arch.vgic.nr_lines + (32 * d->max_vcpus); i++) - INIT_LIST_HEAD(&d->arch.vgic.pending_irqs[i].link); + INIT_LIST_HEAD(&d->arch.vgic.pending_irqs[i].inflight); for (i=0; i<DOMAIN_NR_RANKS(d); i++) spin_lock_init(&d->arch.vgic.shared_irqs[i].lock); return 0; @@ -550,7 +550,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual) struct pending_irq *iter, *n = irq_to_pending(v, irq); /* irq still pending */ - if (!list_empty(&n->link)) + if (!list_empty(&n->inflight)) return; priority = byte_read(rank->ipriority[REG_RANK_INDEX(8, idx)], 0, byte); @@ -565,16 +565,16 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual) gic_set_guest_irq(irq, GICH_LR_PENDING, priority); spin_lock(&v->arch.vgic.lock); - list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, link ) + list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight ) { if ( iter->priority < priority ) { - list_add_tail(&n->link, &iter->link); + list_add_tail(&n->inflight, &iter->inflight); spin_unlock(&v->arch.vgic.lock); return; } } - list_add(&n->link, &v->arch.vgic.inflight_irqs); + list_add(&n->inflight, &v->arch.vgic.inflight_irqs); spin_unlock(&v->arch.vgic.lock); /* we have a new higher priority irq, inject it into the guest */ cpu_raise_softirq(v->processor, VGIC_SOFTIRQ); diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 3372d14..9851220 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -20,7 +20,9 @@ struct pending_irq int irq; struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */ uint8_t priority; - struct list_head link; + /* inflight is used to append instances of pending_irq to + * vgic.inflight_irqs */ + struct list_head inflight; }; struct arch_domain -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 02/11] arm: fix inflight_irqs list priority ordering
Lower priority integers mean higher priority. Also when we are about to insert the lowest priority IRQ so far, add it at the end. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/vgic.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index dd99629..4d2a0e0 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -567,14 +567,14 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual) spin_lock(&v->arch.vgic.lock); list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight ) { - if ( iter->priority < priority ) + if ( iter->priority > priority ) { list_add_tail(&n->inflight, &iter->inflight); spin_unlock(&v->arch.vgic.lock); return; } } - list_add(&n->inflight, &v->arch.vgic.inflight_irqs); + list_add_tail(&n->inflight, &v->arch.vgic.inflight_irqs); spin_unlock(&v->arch.vgic.lock); /* we have a new higher priority irq, inject it into the guest */ cpu_raise_softirq(v->processor, VGIC_SOFTIRQ); -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 03/11] arm: support fewer LR registers than virtual irqs
If the vgic needs to inject a virtual irq into the guest, but no free LR registers are available, add the irq to a list and return. Whenever an LR register becomes available we add the queued irq to it and remove it from the list. We use the gic lock to protect the list and the bitmask. Changes in this version: - added some comments; - rename lr_link to lr_queue; - fix list handling in gic_set_guest_irq; - use nr_lrs instead of sizeof(uint64_t) as argument to find_first_zero_bit. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/gic.c | 101 ++++++++++++++++++++++++++++++++--------- xen/include/asm-arm/domain.h | 10 ++++ 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 120ec82..72b122e 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -25,6 +25,7 @@ #include <xen/sched.h> #include <xen/errno.h> #include <xen/softirq.h> +#include <xen/list.h> #include <asm/p2m.h> #include <asm/domain.h> @@ -45,6 +46,14 @@ static struct { unsigned int lines; unsigned int cpus; spinlock_t lock; + uint64_t lr_mask; + /* lr_pending is used to queue IRQs (struct pending_irq) that the + * vgic tried to inject in the guest (calling gic_set_guest_irq) but + * no LRs were available at the time. + * As soon as an LR is freed we remove the first IRQ from this + * list and write it to the LR register. + * lr_pending is a subset of vgic.inflight_irqs. */ + struct list_head lr_pending; } gic; irq_desc_t irq_desc[NR_IRQS]; @@ -247,6 +256,8 @@ static void __cpuinit gic_hyp_init(void) GICH[GICH_HCR] = GICH_HCR_EN; GICH[GICH_MISR] = GICH_MISR_EOI; + gic.lr_mask = 0ULL; + INIT_LIST_HEAD(&gic.lr_pending); } /* Set up the GIC */ @@ -345,16 +356,50 @@ int __init setup_irq(unsigned int irq, struct irqaction *new) return rc; } -void gic_set_guest_irq(unsigned int virtual_irq, +static inline void gic_set_lr(int lr, unsigned int virtual_irq, unsigned int state, unsigned int priority) { - BUG_ON(virtual_irq > nr_lrs); - GICH[GICH_LR + virtual_irq] = state | + BUG_ON(lr > nr_lrs); + GICH[GICH_LR + lr] = state | GICH_LR_MAINTENANCE_IRQ | ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) | ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT); } +void gic_set_guest_irq(unsigned int virtual_irq, + unsigned int state, unsigned int priority) +{ + int i; + struct pending_irq *iter, *n; + + spin_lock(&gic.lock); + + if ( list_empty(&gic.lr_pending) ) + { + i = find_first_zero_bit(&gic.lr_mask, nr_lrs); + if (i < nr_lrs) { + set_bit(i, &gic.lr_mask); + gic_set_lr(i, virtual_irq, state, priority); + goto out; + } + } + + n = irq_to_pending(current, virtual_irq); + list_for_each_entry ( iter, &gic.lr_pending, lr_queue ) + { + if ( iter->priority > priority ) + { + list_add_tail(&n->lr_queue, &iter->lr_queue); + goto out; + } + } + list_add_tail(&n->lr_queue, &gic.lr_pending); + +out: + spin_unlock(&gic.lock); + return; +} + void gic_inject_irq_start(void) { uint32_t hcr; @@ -431,30 +476,42 @@ void gicv_setup(struct domain *d) static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) { - int i, virq; + int i = 0, virq; uint32_t lr; uint64_t eisr = GICH[GICH_EISR0] | (((uint64_t) GICH[GICH_EISR1]) << 32); - for ( i = 0; i < 64; i++ ) { - if ( eisr & ((uint64_t)1 << i) ) { - struct pending_irq *p; - - lr = GICH[GICH_LR + i]; - virq = lr & GICH_LR_VIRTUAL_MASK; - GICH[GICH_LR + i] = 0; - - spin_lock(¤t->arch.vgic.lock); - p = irq_to_pending(current, virq); - if ( p->desc != NULL ) { - p->desc->status &= ~IRQ_INPROGRESS; - GICC[GICC_DIR] = virq; - } + while ((i = find_next_bit((const long unsigned int *) &eisr, + sizeof(eisr), i)) < sizeof(eisr)) { + struct pending_irq *p; + + spin_lock(&gic.lock); + lr = GICH[GICH_LR + i]; + virq = lr & GICH_LR_VIRTUAL_MASK; + GICH[GICH_LR + i] = 0; + clear_bit(i, &gic.lr_mask); + + if ( !list_empty(&gic.lr_pending) ) { + p = list_entry(gic.lr_pending.next, typeof(*p), lr_queue); + gic_set_lr(i, p->irq, GICH_LR_PENDING, p->priority); + list_del_init(&p->lr_queue); + set_bit(i, &gic.lr_mask); + } else { gic_inject_irq_stop(); - list_del(&p->inflight); - INIT_LIST_HEAD(&p->inflight); - cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); - spin_unlock(¤t->arch.vgic.lock); } + spin_unlock(&gic.lock); + + spin_lock(¤t->arch.vgic.lock); + p = irq_to_pending(current, virq); + if ( p->desc != NULL ) { + p->desc->status &= ~IRQ_INPROGRESS; + GICC[GICC_DIR] = virq; + } + list_del(&p->inflight); + INIT_LIST_HEAD(&p->inflight); + cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); + spin_unlock(¤t->arch.vgic.lock); + + i++; } } diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 9851220..3aa7a8a 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -23,6 +23,9 @@ struct pending_irq /* inflight is used to append instances of pending_irq to * vgic.inflight_irqs */ struct list_head inflight; + /* lr_queue is used to append instances of pending_irq to + * gic.lr_pending */ + struct list_head lr_queue; }; struct arch_domain @@ -56,6 +59,13 @@ struct arch_vcpu struct { struct vgic_irq_rank private_irqs; + /* This list is ordered by IRQ priority and it is used to keep + * track of the IRQs that the VGIC injected into the guest. + * Depending on the availability of LR registers, the IRQs might + * actually be in an LR, and therefore injected into the guest, + * or queued in gic.lr_pending. + * As soon as an IRQ is EOI''d by the guest and removed from the + * corresponding LR it is also removed from this list. */ struct list_head inflight_irqs; spinlock_t lock; } vgic; -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 04/11] arm: replace list_del and INIT_LIST_HEAD with list_del_init
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/gic.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 72b122e..4842161 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -506,8 +506,7 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r p->desc->status &= ~IRQ_INPROGRESS; GICC[GICC_DIR] = virq; } - list_del(&p->inflight); - INIT_LIST_HEAD(&p->inflight); + list_del_init(&p->inflight); cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); spin_unlock(¤t->arch.vgic.lock); -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 05/11] arm: shared_info page allocation and mapping
Allocate the shared_info page at domain creation. Implement arch_memory_op, only for XENMEM_add_to_physmap with space =XENMAPSPACE_shared_info, so that the guest can map the shared_info page. Changes in v3: - /MEMF_bits(32)/MEMF_bits(64); - do not alloc the shared_info page for the idle domain; - define CONFIG_PAGING_ASSISTANCE; - adjust the API to match what the common code expects; - implement a dummy guest_physmap_remove_page. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/domain.c | 11 +++++ xen/arch/arm/mm.c | 98 ++++++++++++++++++++++++++++++++++++++++-- xen/arch/arm/p2m.c | 24 ++++++++++- xen/include/asm-arm/config.h | 2 + xen/include/asm-arm/mm.h | 4 ++ xen/include/asm-arm/p2m.h | 9 ++++ xen/include/asm-arm/paging.h | 3 + 7 files changed, 146 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 0b55934..fca3d60 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -235,6 +235,17 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) if ( (rc = p2m_init(d)) != 0 ) goto fail; + if ( !is_idle_domain(d) ) + { + rc = -ENOMEM; + if ( (d->shared_info = alloc_xenheap_pages(0, MEMF_bits(64))) == NULL ) + goto fail; + + clear_page(d->shared_info); + share_xen_page_with_guest( + virt_to_page(d->shared_info), d, XENSHARE_writable); + } + d->max_vcpus = 8; if ( (rc = domain_vgic_init(d)) != 0 ) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index a0f39eb..cf3de8a 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -25,8 +25,11 @@ #include <xen/mm.h> #include <xen/preempt.h> #include <xen/errno.h> +#include <xen/guest_access.h> #include <asm/page.h> #include <asm/current.h> +#include <public/memory.h> +#include <xen/sched.h> struct domain *dom_xen, *dom_io; @@ -323,17 +326,104 @@ void arch_dump_shared_mem_info(void) { } -long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) +int donate_page(struct domain *d, struct page_info *page, unsigned int memflags) { + ASSERT(0); return -ENOSYS; } -int donate_page(struct domain *d, struct page_info *page, unsigned int memflags) +void share_xen_page_with_guest(struct page_info *page, + struct domain *d, int readonly) { - ASSERT(0); - return -ENOSYS; + if ( page_get_owner(page) == d ) + return; + + spin_lock(&d->page_alloc_lock); + + /* The incremented type count pins as writable or read-only. */ + page->u.inuse.type_info = (readonly ? PGT_none : PGT_writable_page); + page->u.inuse.type_info |= PGT_validated | 1; + + page_set_owner(page, d); + wmb(); /* install valid domain ptr before updating refcnt. */ + ASSERT((page->count_info & ~PGC_xen_heap) == 0); + + /* Only add to the allocation list if the domain isn''t dying. */ + if ( !d->is_dying ) + { + page->count_info |= PGC_allocated | 1; + if ( unlikely(d->xenheap_pages++ == 0) ) + get_knownalive_domain(d); + page_list_add_tail(page, &d->xenpage_list); + } + + spin_unlock(&d->page_alloc_lock); +} + +static int xenmem_add_to_physmap_once( + struct domain *d, + const struct xen_add_to_physmap *xatp) +{ + unsigned long mfn = 0; + int rc; + + switch ( xatp->space ) + { + case XENMAPSPACE_shared_info: + if ( xatp->idx == 0 ) + mfn = virt_to_mfn(d->shared_info); + break; + default: + return -ENOSYS; + } + + domain_lock(d); + + /* Map at new location. */ + rc = guest_physmap_add_page(d, xatp->gpfn, mfn, 0); + + domain_unlock(d); + + return rc; +} + +static int xenmem_add_to_physmap(struct domain *d, + struct xen_add_to_physmap *xatp) +{ + return xenmem_add_to_physmap_once(d, xatp); } +long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) +{ + int rc; + + switch ( op ) + { + case XENMEM_add_to_physmap: + { + struct xen_add_to_physmap xatp; + struct domain *d; + + if ( copy_from_guest(&xatp, arg, 1) ) + return -EFAULT; + + rc = rcu_lock_target_domain_by_id(xatp.domid, &d); + if ( rc != 0 ) + return rc; + + rc = xenmem_add_to_physmap(d, &xatp); + + rcu_unlock_domain(d); + + return rc; + } + + default: + return -ENOSYS; + } + + return 0; +} /* * Local variables: * mode: C diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 14614fd..4c94ef0 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -118,7 +118,12 @@ static int create_p2m_entries(struct domain *d, } /* else: third already valid */ - BUG_ON(third[third_table_offset(addr)].p2m.valid); + if ( third[third_table_offset(addr)].p2m.valid ) + { + /* p2m entry already present */ + free_domheap_page( + mfn_to_page(third[third_table_offset(addr)].p2m.base)); + } /* Allocate a new RAM page and attach */ if (alloc) @@ -172,6 +177,23 @@ int map_mmio_regions(struct domain *d, return create_p2m_entries(d, 0, start_gaddr, end_gaddr, maddr); } +int guest_physmap_add_page(struct domain *d, + unsigned long gpfn, + unsigned long mfn, + unsigned int page_order) +{ + return create_p2m_entries(d, 0, gpfn << PAGE_SHIFT, + (gpfn + (1<<page_order)) << PAGE_SHIFT, + mfn << PAGE_SHIFT); +} + +void guest_physmap_remove_page(struct domain *d, + unsigned long gpfn, + unsigned long mfn, unsigned int page_order) +{ + ASSERT(0); +} + int p2m_alloc_table(struct domain *d) { struct p2m_domain *p2m = &d->arch.p2m; diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h index c2ab0a2..63fb48e 100644 --- a/xen/include/asm-arm/config.h +++ b/xen/include/asm-arm/config.h @@ -7,6 +7,8 @@ #ifndef __ARM_CONFIG_H__ #define __ARM_CONFIG_H__ +#define CONFIG_PAGING_ASSISTANCE 1 + #define CONFIG_PAGING_LEVELS 3 #define CONFIG_ARM 1 diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h index bfc0f76..56ab9415 100644 --- a/xen/include/asm-arm/mm.h +++ b/xen/include/asm-arm/mm.h @@ -78,6 +78,10 @@ struct page_info #define _PGT_pinned PG_shift(5) #define PGT_pinned PG_mask(1, 5) + /* Has this page been validated for use as its current type? */ +#define _PGT_validated PG_shift(6) +#define PGT_validated PG_mask(1, 6) + /* Count of uses of this frame as its current type. */ #define PGT_count_width PG_shift(9) #define PGT_count_mask ((1UL<<PGT_count_width)-1) diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index aec52f7..d8e8dc8 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -40,6 +40,15 @@ int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end); int map_mmio_regions(struct domain *d, paddr_t start_gaddr, paddr_t end_gaddr, paddr_t maddr); +/* Untyped version for RAM only, for compatibility */ +int guest_physmap_add_page(struct domain *d, + unsigned long gfn, + unsigned long mfn, + unsigned int page_order); +void guest_physmap_remove_page(struct domain *d, + unsigned long gpfn, + unsigned long mfn, unsigned int page_order); + unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn); /* diff --git a/xen/include/asm-arm/paging.h b/xen/include/asm-arm/paging.h index 4dc340f..3d7dd95 100644 --- a/xen/include/asm-arm/paging.h +++ b/xen/include/asm-arm/paging.h @@ -1,6 +1,9 @@ #ifndef _XEN_PAGING_H #define _XEN_PAGING_H +#define paging_mode_translate(d) (0) +#define paging_mode_external(d) (0) + #endif /* XEN_PAGING_H */ /* -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 06/11] arm: handle dom0_max_vcpus=0 case properly
From: Ian Campbell <ian.campbell@citrix.com> Also use xzalloc_array. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain_build.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index cbbc0b9..ef52d1d 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -14,13 +14,14 @@ integer_param("dom0_max_vcpus", opt_dom0_max_vcpus); struct vcpu *__init alloc_dom0_vcpu0(void) { - dom0->vcpu = xmalloc_array(struct vcpu *, opt_dom0_max_vcpus); + if ( opt_dom0_max_vcpus == 0 ) + opt_dom0_max_vcpus = num_online_cpus(); + if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS ) + opt_dom0_max_vcpus = MAX_VIRT_CPUS; + + dom0->vcpu = xzalloc_array(struct vcpu *, opt_dom0_max_vcpus); if ( !dom0->vcpu ) - { - printk("failed to alloc dom0->vccpu\n"); return NULL; - } - memset(dom0->vcpu, 0, opt_dom0_max_vcpus * sizeof(*dom0->vcpu)); dom0->max_vcpus = opt_dom0_max_vcpus; return alloc_vcpu(dom0, 0, 0); -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 07/11] arm: use r12 to pass the hypercall number
Use r12 to pass the hypercall number and r0-r4 for the hypercall arguments. Use the ISS to pass an hypervisor specific tag. Remove passing unused registers to arm_hypercall_table: we don''t have 6 arguments hypercalls and we never use 64 bit values as hypercall arguments, 64 bit values are only contained within structs passed as arguments. Changes in v3: - move XEN_HYPERCALL_TAG to a public header; - clobber register in the debug build; - document calling convention; - check if arm_hypercall_table[regs->r12] != NULL. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/traps.c | 31 ++++++++++++++++++++----------- xen/include/public/arch-arm.h | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 395d0af..750f85a 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -367,7 +367,6 @@ unsigned long do_arch_0(unsigned int cmd, unsigned long long value) } typedef unsigned long arm_hypercall_t( - unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); #define HYPERCALL(x) \ @@ -407,18 +406,28 @@ static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code) static void do_trap_hypercall(struct cpu_user_regs *regs, unsigned long iss) { + arm_hypercall_t *call = NULL; local_irq_enable(); - regs->r0 = arm_hypercall_table[iss](regs->r0, - regs->r1, - regs->r2, - regs->r3, - regs->r4, - regs->r5, - regs->r6, - regs->r7, - regs->r8, - regs->r9); + if ( iss != XEN_HYPERCALL_TAG ) { + printk("%s %d: received an alien hypercall iss=%lx\n", __func__ , + __LINE__ , iss); + regs->r0 = -EINVAL; + return; + } + + call = arm_hypercall_table[regs->r12]; + if ( call == NULL ) { + regs->r0 = -ENOSYS; + return; + } + + regs->r0 = call(regs->r0, regs->r1, regs->r2, regs->r3, regs->r4); + +#ifdef DEBUG + /* clobber registers */ + regs->r1 = regs->r2 = regs->r3 = regs->r4 = regs->r12 = 0xDEADBEEF; +#endif } static void do_cp15_32(struct cpu_user_regs *regs, diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index e3d5c08..4f16bde 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -27,6 +27,27 @@ #ifndef __XEN_PUBLIC_ARCH_ARM_H__ #define __XEN_PUBLIC_ARCH_ARM_H__ +/* hypercall calling convention + * ---------------------------- + * + * An hypercall is issued using the ARM HVC instruction. + * + * The hypercall arguments go on the registers, the first argument on + * r0, the second argument on r1, the third on r2, and so on. + * + * The hypercall number is passed on r12. + * + * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG. + * + * The return value is passed on r0. + * + * The hypercall will clobber r0, r1, r2, r3, r4 and r12. + * + */ + +#define XEN_HYPERCALL_TAG 0XEA1 + + #ifndef __ASSEMBLY__ #define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ typedef struct { type *p; } __guest_handle_ ## name -- 1.7.2.5
Implement xen_version, event_channel_op, memory_op sysctl and physdev_op hypercalls. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/physdev.c | 27 +++++++++++++++++++++++++++ xen/arch/arm/traps.c | 5 +++++ xen/include/asm-arm/hypercall.h | 1 + 4 files changed, 34 insertions(+), 0 deletions(-) create mode 100644 xen/arch/arm/physdev.c diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 49b64fe..619430c 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -14,6 +14,7 @@ obj-y += kernel.o obj-y += mm.o obj-y += p2m.o obj-y += guestcopy.o +obj-y += physdev.o obj-y += setup.o obj-y += time.o obj-y += smpboot.o diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c new file mode 100644 index 0000000..bcf4337 --- /dev/null +++ b/xen/arch/arm/physdev.c @@ -0,0 +1,27 @@ +/****************************************************************************** + * Arch-specific physdev.c + * + * Copyright (c) 2012, Citrix Systems + */ + +#include <xen/config.h> +#include <xen/types.h> +#include <xen/lib.h> +#include <xen/errno.h> +#include <asm/hypercall.h> + + +int do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) +{ + printk("%s %d cmd=%d: not implemented yet\n", __func__, __LINE__, cmd); + return -ENOSYS; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 750f85a..98bfcd5 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -376,6 +376,11 @@ static arm_hypercall_t *arm_hypercall_table[] = { HYPERCALL(arch_0), HYPERCALL(sched_op), HYPERCALL(console_io), + HYPERCALL(xen_version), + HYPERCALL(event_channel_op), + HYPERCALL(memory_op), + HYPERCALL(physdev_op), + HYPERCALL(sysctl), }; static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code) diff --git a/xen/include/asm-arm/hypercall.h b/xen/include/asm-arm/hypercall.h index e840507..454f02e 100644 --- a/xen/include/asm-arm/hypercall.h +++ b/xen/include/asm-arm/hypercall.h @@ -2,6 +2,7 @@ #define __ASM_ARM_HYPERCALL_H__ #include <public/domctl.h> /* for arch_do_domctl */ +int do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); #endif /* __ASM_ARM_HYPERCALL_H__ */ /* -- 1.7.2.5
Stefano Stabellini
2012-Mar-02 14:27 UTC
[PATCH v3 09/11] arm: implement flush_tlb_all_local and flush_tlb_local
Call flush_tlb_all_local from create_p2m_entries after removing a page from the p2m. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/p2m.c | 2 ++ xen/include/asm-arm/flushtlb.h | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 4c94ef0..051a0e8 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -3,6 +3,7 @@ #include <xen/lib.h> #include <xen/errno.h> #include <xen/domain_page.h> +#include <asm/flushtlb.h> void p2m_load_VTTBR(struct domain *d) { @@ -123,6 +124,7 @@ static int create_p2m_entries(struct domain *d, /* p2m entry already present */ free_domheap_page( mfn_to_page(third[third_table_offset(addr)].p2m.base)); + flush_tlb_all_local(); } /* Allocate a new RAM page and attach */ diff --git a/xen/include/asm-arm/flushtlb.h b/xen/include/asm-arm/flushtlb.h index c8486fc..210abfa 100644 --- a/xen/include/asm-arm/flushtlb.h +++ b/xen/include/asm-arm/flushtlb.h @@ -14,8 +14,27 @@ do { \ #define tlbflush_current_time() (0) -/* Flush local TLBs */ -void flush_tlb_local(void); +/* Flush local TLBs, current VMID only */ +static inline void flush_tlb_local(void) +{ + dsb(); + + WRITE_CP32((uint32_t) 0, TLBIALLIS); + + dsb(); + isb(); +} + +/* Flush local TLBs, all VMIDs, non-hypervisor mode */ +static inline void flush_tlb_all_local(void) +{ + dsb(); + + WRITE_CP32((uint32_t) 0, TLBIALLNSNHIS); + + dsb(); + isb(); +} /* Flush specified CPUs'' TLBs */ void flush_tlb_mask(const cpumask_t *mask); -- 1.7.2.5
Instead of using a softirq to check whether we need to set the VI bit in the HCR (IRQ injection in the guest), always check the lr_mask on leave_hypervisor_tail. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/gic.c | 13 ++++++++++--- xen/arch/arm/gic.h | 4 ++-- xen/arch/arm/traps.c | 4 +++- xen/arch/arm/vgic.c | 15 --------------- xen/include/asm-arm/softirq.h | 3 +-- 5 files changed, 16 insertions(+), 23 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 4842161..e216160 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -400,7 +400,7 @@ out: return; } -void gic_inject_irq_start(void) +static void gic_inject_irq_start(void) { uint32_t hcr; hcr = READ_CP32(HCR); @@ -408,7 +408,7 @@ void gic_inject_irq_start(void) isb(); } -void gic_inject_irq_stop(void) +static void gic_inject_irq_stop(void) { uint32_t hcr; hcr = READ_CP32(HCR); @@ -418,6 +418,14 @@ void gic_inject_irq_stop(void) } } +void gic_inject(void) +{ + if (!gic.lr_mask) + gic_inject_irq_stop(); + else + gic_inject_irq_start(); +} + int gic_route_irq_to_guest(struct domain *d, unsigned int irq, const char * devname) { @@ -507,7 +515,6 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r GICC[GICC_DIR] = virq; } list_del_init(&p->inflight); - cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); spin_unlock(¤t->arch.vgic.lock); i++; diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h index 81c388d..2d38e18 100644 --- a/xen/arch/arm/gic.h +++ b/xen/arch/arm/gic.h @@ -128,11 +128,11 @@ extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq); extern void gic_route_irqs(void); +extern void gic_inject(void); + extern void __cpuinit init_maintenance_interrupt(void); extern void gic_set_guest_irq(unsigned int irq, unsigned int state, unsigned int priority); -extern void gic_inject_irq_start(void); -extern void gic_inject_irq_stop(void); extern int gic_route_irq_to_guest(struct domain *d, unsigned int irq, const char * devname); diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 98bfcd5..33396a3 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -606,8 +606,10 @@ asmlinkage void leave_hypervisor_tail(void) while (1) { local_irq_disable(); - if (!softirq_pending(smp_processor_id())) + if (!softirq_pending(smp_processor_id())) { + gic_inject(); return; + } local_irq_enable(); do_softirq(); } diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 4d2a0e0..629a0da 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -577,23 +577,8 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual) list_add_tail(&n->inflight, &v->arch.vgic.inflight_irqs); spin_unlock(&v->arch.vgic.lock); /* we have a new higher priority irq, inject it into the guest */ - cpu_raise_softirq(v->processor, VGIC_SOFTIRQ); } -static void vgic_softirq(void) -{ - if (list_empty(¤t->arch.vgic.inflight_irqs)) - return; - - gic_inject_irq_start(); -} - -static int __init init_vgic_softirq(void) -{ - open_softirq(VGIC_SOFTIRQ, vgic_softirq); - return 0; -} -__initcall(init_vgic_softirq); /* * Local variables: * mode: C diff --git a/xen/include/asm-arm/softirq.h b/xen/include/asm-arm/softirq.h index 536af38..27818ae 100644 --- a/xen/include/asm-arm/softirq.h +++ b/xen/include/asm-arm/softirq.h @@ -1,8 +1,7 @@ #ifndef __ASM_SOFTIRQ_H__ #define __ASM_SOFTIRQ_H__ -#define VGIC_SOFTIRQ (NR_COMMON_SOFTIRQS + 0) -#define NR_ARCH_SOFTIRQS 1 +#define NR_ARCH_SOFTIRQS 0 #endif /* __ASM_SOFTIRQ_H__ */ /* -- 1.7.2.5
Implement vcpu_mark_events_pending using the vgic to inject PPI 31, that we reserve for Xen usage. In the future the interrupt used for event injection might be dynamic and could be written into the device tree. Otherwise it could be an SGI choosen by the guest and passed to Xen through an hypecall. Considering that: - it is easy to determine if an event notification interrupt has already been EOI''d by the guest just looking at the evtchn_upcall_pending bit in the shared_info page; - we can safely assume that there is at most one event notification interrupt pending at any time in any set of LR registers because we never inject more than a single event notification interrupt in one vcpu (see vcpu_mark_events_pending); we can avoid requesting maintenance interrupts for VGIC_IRQ_EVTCHN_CALLBACK, provided that we check for event notification interrupts that need to be cleared in the following places: - maintenance interrupt entry; - gic_set_guest_irq; that is every time we are about to write to an LR. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 11 +++++++++++ xen/arch/arm/dummy.S | 1 - xen/arch/arm/gic.c | 40 +++++++++++++++++++++++++++++++++++++++- xen/arch/arm/gic.h | 3 +++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index fca3d60..b0f6ed9 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -275,6 +275,17 @@ void arch_dump_vcpu_info(struct vcpu *v) { } +void vcpu_mark_events_pending(struct vcpu *v) +{ + int already_pending = test_and_set_bit( + 0, (unsigned long *)&vcpu_info(v, evtchn_upcall_pending)); + + if ( already_pending ) + return; + + vgic_vcpu_inject_irq(v, VGIC_IRQ_EVTCHN_CALLBACK, 1); +} + /* * Local variables: * mode: C diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S index 3f2cc4b..93f6f53 100644 --- a/xen/arch/arm/dummy.S +++ b/xen/arch/arm/dummy.S @@ -31,7 +31,6 @@ DUMMY(arch_vcpu_reset); DUMMY(free_vcpu_guest_context); DUMMY(sync_vcpu_execstate); NOP(update_vcpu_system_time); -DUMMY(vcpu_mark_events_pending); DUMMY(vcpu_show_execution_state); /* Page Reference & Type Maintenance */ diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index e216160..e2371c7 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -37,6 +37,7 @@ + (GIC_CR_OFFSET & 0xfff))) #define GICH ((volatile uint32_t *) (FIXMAP_ADDR(FIXMAP_GICH) \ + (GIC_HR_OFFSET & 0xfff))) +static void events_maintenance(struct vcpu *v); /* Global state */ static struct { @@ -46,6 +47,7 @@ static struct { unsigned int lines; unsigned int cpus; spinlock_t lock; + uint64_t event_mask; uint64_t lr_mask; /* lr_pending is used to queue IRQs (struct pending_irq) that the * vgic tried to inject in the guest (calling gic_set_guest_irq) but @@ -257,6 +259,7 @@ static void __cpuinit gic_hyp_init(void) GICH[GICH_HCR] = GICH_HCR_EN; GICH[GICH_MISR] = GICH_MISR_EOI; gic.lr_mask = 0ULL; + gic.event_mask = 0ULL; INIT_LIST_HEAD(&gic.lr_pending); } @@ -359,9 +362,15 @@ int __init setup_irq(unsigned int irq, struct irqaction *new) static inline void gic_set_lr(int lr, unsigned int virtual_irq, unsigned int state, unsigned int priority) { + int maintenance_int = GICH_LR_MAINTENANCE_IRQ; + BUG_ON(lr > nr_lrs); + + if (virtual_irq == VGIC_IRQ_EVTCHN_CALLBACK && nr_lrs > 1) + maintenance_int = 0; + GICH[GICH_LR + lr] = state | - GICH_LR_MAINTENANCE_IRQ | + maintenance_int | ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) | ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT); } @@ -372,6 +381,8 @@ void gic_set_guest_irq(unsigned int virtual_irq, int i; struct pending_irq *iter, *n; + events_maintenance(current); + spin_lock(&gic.lock); if ( list_empty(&gic.lr_pending) ) @@ -379,6 +390,8 @@ void gic_set_guest_irq(unsigned int virtual_irq, i = find_first_zero_bit(&gic.lr_mask, nr_lrs); if (i < nr_lrs) { set_bit(i, &gic.lr_mask); + if ( virtual_irq == VGIC_IRQ_EVTCHN_CALLBACK ) + set_bit(i, &gic.event_mask); gic_set_lr(i, virtual_irq, state, priority); goto out; } @@ -482,12 +495,35 @@ void gicv_setup(struct domain *d) GIC_BASE_ADDRESS + GIC_VR_OFFSET); } +static void events_maintenance(struct vcpu *v) +{ + int i = 0; + int already_pending = test_bit(0, + (unsigned long *)&vcpu_info(v, evtchn_upcall_pending)); + + if (!already_pending && gic.event_mask != 0) { + spin_lock(&gic.lock); + while ((i = find_next_bit((const long unsigned int *) &gic.event_mask, + sizeof(uint64_t), i)) < sizeof(uint64_t)) { + + GICH[GICH_LR + i] = 0; + clear_bit(i, &gic.lr_mask); + clear_bit(i, &gic.event_mask); + + i++; + } + spin_unlock(&gic.lock); + } +} + static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) { int i = 0, virq; uint32_t lr; uint64_t eisr = GICH[GICH_EISR0] | (((uint64_t) GICH[GICH_EISR1]) << 32); + events_maintenance(current); + while ((i = find_next_bit((const long unsigned int *) &eisr, sizeof(eisr), i)) < sizeof(eisr)) { struct pending_irq *p; @@ -503,6 +539,8 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r gic_set_lr(i, p->irq, GICH_LR_PENDING, p->priority); list_del_init(&p->lr_queue); set_bit(i, &gic.lr_mask); + if ( p->irq == VGIC_IRQ_EVTCHN_CALLBACK ) + set_bit(i, &gic.event_mask); } else { gic_inject_irq_stop(); } diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h index 2d38e18..cb98fb7 100644 --- a/xen/arch/arm/gic.h +++ b/xen/arch/arm/gic.h @@ -121,6 +121,9 @@ #define GICH_LR_CPUID_SHIFT 9 #define GICH_VTR_NRLRGS 0x3f +/* XXX: write this into the DT */ +#define VGIC_IRQ_EVTCHN_CALLBACK 31 + extern int domain_vgic_init(struct domain *d); extern int vcpu_vgic_init(struct vcpu *v); extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq,int virtual); -- 1.7.2.5
Ian Campbell
2012-Mar-13 14:30 UTC
Re: [PATCH v3 03/11] arm: support fewer LR registers than virtual irqs
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> ...Is this the final version of this patch? There is a v4 in my queue[0] but it seems to predate this one. Ian. [0] <1330016454-19752-1-git-send-email-stefano.stabellini@eu.citrix.com>> If the vgic needs to inject a virtual irq into the guest, but no free > LR registers are available, add the irq to a list and return. > Whenever an LR register becomes available we add the queued irq to it > and remove it from the list. > We use the gic lock to protect the list and the bitmask. > > > Changes in this version: > > - added some comments; > > - rename lr_link to lr_queue; > > - fix list handling in gic_set_guest_irq; > > - use nr_lrs instead of sizeof(uint64_t) as argument to > find_first_zero_bit. > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/gic.c | 101 ++++++++++++++++++++++++++++++++--------- > xen/include/asm-arm/domain.h | 10 ++++ > 2 files changed, 89 insertions(+), 22 deletions(-) > > diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c > index 120ec82..72b122e 100644 > --- a/xen/arch/arm/gic.c > +++ b/xen/arch/arm/gic.c > @@ -25,6 +25,7 @@ > #include <xen/sched.h> > #include <xen/errno.h> > #include <xen/softirq.h> > +#include <xen/list.h> > #include <asm/p2m.h> > #include <asm/domain.h> > > @@ -45,6 +46,14 @@ static struct { > unsigned int lines; > unsigned int cpus; > spinlock_t lock; > + uint64_t lr_mask; > + /* lr_pending is used to queue IRQs (struct pending_irq) that the > + * vgic tried to inject in the guest (calling gic_set_guest_irq) but > + * no LRs were available at the time. > + * As soon as an LR is freed we remove the first IRQ from this > + * list and write it to the LR register. > + * lr_pending is a subset of vgic.inflight_irqs. */ > + struct list_head lr_pending; > } gic; > > irq_desc_t irq_desc[NR_IRQS]; > @@ -247,6 +256,8 @@ static void __cpuinit gic_hyp_init(void) > > GICH[GICH_HCR] = GICH_HCR_EN; > GICH[GICH_MISR] = GICH_MISR_EOI; > + gic.lr_mask = 0ULL; > + INIT_LIST_HEAD(&gic.lr_pending); > } > > /* Set up the GIC */ > @@ -345,16 +356,50 @@ int __init setup_irq(unsigned int irq, struct irqaction *new) > return rc; > } > > -void gic_set_guest_irq(unsigned int virtual_irq, > +static inline void gic_set_lr(int lr, unsigned int virtual_irq, > unsigned int state, unsigned int priority) > { > - BUG_ON(virtual_irq > nr_lrs); > - GICH[GICH_LR + virtual_irq] = state | > + BUG_ON(lr > nr_lrs); > + GICH[GICH_LR + lr] = state | > GICH_LR_MAINTENANCE_IRQ | > ((priority >> 3) << GICH_LR_PRIORITY_SHIFT) | > ((virtual_irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT); > } > > +void gic_set_guest_irq(unsigned int virtual_irq, > + unsigned int state, unsigned int priority) > +{ > + int i; > + struct pending_irq *iter, *n; > + > + spin_lock(&gic.lock); > + > + if ( list_empty(&gic.lr_pending) ) > + { > + i = find_first_zero_bit(&gic.lr_mask, nr_lrs); > + if (i < nr_lrs) { > + set_bit(i, &gic.lr_mask); > + gic_set_lr(i, virtual_irq, state, priority); > + goto out; > + } > + } > + > + n = irq_to_pending(current, virtual_irq); > + list_for_each_entry ( iter, &gic.lr_pending, lr_queue ) > + { > + if ( iter->priority > priority ) > + { > + list_add_tail(&n->lr_queue, &iter->lr_queue); > + goto out; > + } > + } > + list_add_tail(&n->lr_queue, &gic.lr_pending); > + > +out: > + spin_unlock(&gic.lock); > + return; > +} > + > void gic_inject_irq_start(void) > { > uint32_t hcr; > @@ -431,30 +476,42 @@ void gicv_setup(struct domain *d) > > static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) > { > - int i, virq; > + int i = 0, virq; > uint32_t lr; > uint64_t eisr = GICH[GICH_EISR0] | (((uint64_t) GICH[GICH_EISR1]) << 32); > > - for ( i = 0; i < 64; i++ ) { > - if ( eisr & ((uint64_t)1 << i) ) { > - struct pending_irq *p; > - > - lr = GICH[GICH_LR + i]; > - virq = lr & GICH_LR_VIRTUAL_MASK; > - GICH[GICH_LR + i] = 0; > - > - spin_lock(¤t->arch.vgic.lock); > - p = irq_to_pending(current, virq); > - if ( p->desc != NULL ) { > - p->desc->status &= ~IRQ_INPROGRESS; > - GICC[GICC_DIR] = virq; > - } > + while ((i = find_next_bit((const long unsigned int *) &eisr, > + sizeof(eisr), i)) < sizeof(eisr)) { > + struct pending_irq *p; > + > + spin_lock(&gic.lock); > + lr = GICH[GICH_LR + i]; > + virq = lr & GICH_LR_VIRTUAL_MASK; > + GICH[GICH_LR + i] = 0; > + clear_bit(i, &gic.lr_mask); > + > + if ( !list_empty(&gic.lr_pending) ) { > + p = list_entry(gic.lr_pending.next, typeof(*p), lr_queue); > + gic_set_lr(i, p->irq, GICH_LR_PENDING, p->priority); > + list_del_init(&p->lr_queue); > + set_bit(i, &gic.lr_mask); > + } else { > gic_inject_irq_stop(); > - list_del(&p->inflight); > - INIT_LIST_HEAD(&p->inflight); > - cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); > - spin_unlock(¤t->arch.vgic.lock); > } > + spin_unlock(&gic.lock); > + > + spin_lock(¤t->arch.vgic.lock); > + p = irq_to_pending(current, virq); > + if ( p->desc != NULL ) { > + p->desc->status &= ~IRQ_INPROGRESS; > + GICC[GICC_DIR] = virq; > + } > + list_del(&p->inflight); > + INIT_LIST_HEAD(&p->inflight); > + cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); > + spin_unlock(¤t->arch.vgic.lock); > + > + i++; > } > } > > diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h > index 9851220..3aa7a8a 100644 > --- a/xen/include/asm-arm/domain.h > +++ b/xen/include/asm-arm/domain.h > @@ -23,6 +23,9 @@ struct pending_irq > /* inflight is used to append instances of pending_irq to > * vgic.inflight_irqs */ > struct list_head inflight; > + /* lr_queue is used to append instances of pending_irq to > + * gic.lr_pending */ > + struct list_head lr_queue; > }; > > struct arch_domain > @@ -56,6 +59,13 @@ struct arch_vcpu > > struct { > struct vgic_irq_rank private_irqs; > + /* This list is ordered by IRQ priority and it is used to keep > + * track of the IRQs that the VGIC injected into the guest. > + * Depending on the availability of LR registers, the IRQs might > + * actually be in an LR, and therefore injected into the guest, > + * or queued in gic.lr_pending. > + * As soon as an IRQ is EOI''d by the guest and removed from the > + * corresponding LR it is also removed from this list. */ > struct list_head inflight_irqs; > spinlock_t lock; > } vgic;
Ian Campbell
2012-Mar-13 15:28 UTC
Re: [PATCH v3 07/11] arm: use r12 to pass the hypercall number
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> Use r12 to pass the hypercall number and r0-r4 for the hypercall > arguments. > > Use the ISS to pass an hypervisor specific tag. > > Remove passing unused registers to arm_hypercall_table: we don''t have 6 > arguments hypercalls and we never use 64 bit values as hypercall > arguments, 64 bit values are only contained within structs passed as > arguments. > > > Changes in v3: > > - move XEN_HYPERCALL_TAG to a public header; > > - clobber register in the debug build; > > - document calling convention; > > - check if arm_hypercall_table[regs->r12] != NULL. > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/traps.c | 31 ++++++++++++++++++++----------- > xen/include/public/arch-arm.h | 21 +++++++++++++++++++++ > 2 files changed, 41 insertions(+), 11 deletions(-) > > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c > index 395d0af..750f85a 100644 > --- a/xen/arch/arm/traps.c > +++ b/xen/arch/arm/traps.c > @@ -367,7 +367,6 @@ unsigned long do_arch_0(unsigned int cmd, unsigned long long value) > } > > typedef unsigned long arm_hypercall_t( > - unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, > unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); > > #define HYPERCALL(x) \ > @@ -407,18 +406,28 @@ static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code) > > static void do_trap_hypercall(struct cpu_user_regs *regs, unsigned long iss) > { > + arm_hypercall_t *call = NULL; > local_irq_enable(); > > - regs->r0 = arm_hypercall_table[iss](regs->r0, > - regs->r1, > - regs->r2, > - regs->r3, > - regs->r4, > - regs->r5, > - regs->r6, > - regs->r7, > - regs->r8, > - regs->r9); > + if ( iss != XEN_HYPERCALL_TAG ) { > + printk("%s %d: received an alien hypercall iss=%lx\n", __func__ , > + __LINE__ , iss); > + regs->r0 = -EINVAL; > + return; > + } > + > + call = arm_hypercall_table[regs->r12]; > + if ( call == NULL ) {Xen coding style calls for { on a new line (twice).> + regs->r0 = -ENOSYS; > + return; > + } > + > + regs->r0 = call(regs->r0, regs->r1, regs->r2, regs->r3, regs->r4); > + > +#ifdef DEBUGXen actually uses the confusing double negative "#ifndef NDEBUG"... Since this is an ABI change I want to get it out of the way so I''ll correct both of those as I commit rather than waiting for a resend.> + /* clobber registers */ > + regs->r1 = regs->r2 = regs->r3 = regs->r4 = regs->r12 = 0xDEADBEEF; > +#endif > } > > static void do_cp15_32(struct cpu_user_regs *regs, > diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h > index e3d5c08..4f16bde 100644 > --- a/xen/include/public/arch-arm.h > +++ b/xen/include/public/arch-arm.h > @@ -27,6 +27,27 @@ > #ifndef __XEN_PUBLIC_ARCH_ARM_H__ > #define __XEN_PUBLIC_ARCH_ARM_H__ > > +/* hypercall calling convention > + * ---------------------------- > + * > + * An hypercall is issued using the ARM HVC instruction. > + * > + * The hypercall arguments go on the registers, the first argument on > + * r0, the second argument on r1, the third on r2, and so on.While I''m here I''ll also clarify that we only go to five arguments and below that we clobber those registers regardless of the # of arguments the specific hypercall has.> + * > + * The hypercall number is passed on r12. > + * > + * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG. > + * > + * The return value is passed on r0. > + * > + * The hypercall will clobber r0, r1, r2, r3, r4 and r12. > + * > + */ > + > +#define XEN_HYPERCALL_TAG 0XEA1 > + > + > #ifndef __ASSEMBLY__ > #define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ > typedef struct { type *p; } __guest_handle_ ## name
Ian Campbell
2012-Mar-13 16:09 UTC
Re: [PATCH v3 07/11] arm: use r12 to pass the hypercall number
On Tue, 2012-03-13 at 15:28 +0000, Ian Campbell wrote:> On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > Use r12 to pass the hypercall number and r0-r4 for the hypercall > > arguments.I have just applied this change, with the changes previously discussed and the addition of: ** This is a guest visible ABI change which requires an updated guest kernel ** to the comment. This means that xen-unstable 25024:b8a5e8100c5d and later requires git://xenbits.xen.org/people/dvrabel/linux.git#vexpress-dt changeset ef9437e20b9e549282a4602f1187023e4ad2c697 or later. I will update the wiki page with this in a moment. Ian.
Ian Campbell
2012-Mar-13 16:17 UTC
WARNING: Xen ARMv7 with Virtualization Extensions Guest ABI has changed.
Resending with a more prominent subject line... On Tue, 2012-03-13 at 16:09 +0000, Ian Campbell wrote:> On Tue, 2012-03-13 at 15:28 +0000, Ian Campbell wrote: > > On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > > Use r12 to pass the hypercall number and r0-r4 for the hypercall > > > arguments. > > I have just applied this change, with the changes previously discussed > and the addition of: > ** This is a guest visible ABI change which requires an updated guest kernel ** > to the comment. > > This means that xen-unstable 25024:b8a5e8100c5d and later requires > git://xenbits.xen.org/people/dvrabel/linux.git#vexpress-dt changeset > ef9437e20b9e549282a4602f1187023e4ad2c697 or later. > > I will update the wiki page with this in a moment.Wiki page is now updated. Ian.
Ian Campbell
2012-Mar-13 17:06 UTC
Re: [PATCH v3 05/11] arm: shared_info page allocation and mapping
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> Allocate the shared_info page at domain creation. > > Implement arch_memory_op, only for XENMEM_add_to_physmap with space => XENMAPSPACE_shared_info, so that the guest can map the shared_info page. > > Changes in v3: > > - /MEMF_bits(32)/MEMF_bits(64);I think MEMF_bits(64) is wrong. If you want no limit (which I think is the case here) then you can just pass 0. The rest looked good. Ian.
Ian Campbell
2012-Mar-13 17:24 UTC
Re: [PATCH v3 03/11] arm: support fewer LR registers than virtual irqs
On Tue, 2012-03-13 at 17:31 +0000, Stefano Stabellini wrote:> On Tue, 13 Mar 2012, Ian Campbell wrote: > > On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > > ... > > > > Is this the final version of this patch? > > > > There is a v4 in my queue[0] but it seems to predate this one. > > Yes, sorry for the confusion. I reset the version of this patch when I > included in the "xen/arm: event channels and shared_info page" series.Ah, yes, I just spotted it in that series too. Thanks, Ian.
Stefano Stabellini
2012-Mar-13 17:31 UTC
Re: [PATCH v3 03/11] arm: support fewer LR registers than virtual irqs
On Tue, 13 Mar 2012, Ian Campbell wrote:> On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > ... > > Is this the final version of this patch? > > There is a v4 in my queue[0] but it seems to predate this one.Yes, sorry for the confusion. I reset the version of this patch when I included in the "xen/arm: event channels and shared_info page" series.
Ian Campbell
2012-Mar-14 09:26 UTC
Re: [PATCH v3 03/11] arm: support fewer LR registers than virtual irqs
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> @@ -247,6 +256,8 @@ static void __cpuinit gic_hyp_init(void)> GICH[GICH_HCR] = GICH_HCR_EN; > GICH[GICH_MISR] = GICH_MISR_EOI; > + gic.lr_mask = 0ULL; > + INIT_LIST_HEAD(&gic.lr_pending);I''m not sure this is the correct place for this initialisation. In Tim''s SMP series he added a call to this from gic_init_secondary_cpu, this made sense to me because until now this function has only initialised the per-CPU GICH registers. However you are now adding a global gic initialiser. I think either this initialisation would be better off in gic_init() or we need a new datastructure for per-CPU git information. Ian.
Ian Campbell
2012-Mar-14 09:38 UTC
Re: [PATCH v3 05/11] arm: shared_info page allocation and mapping
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> @@ -118,7 +118,12 @@ static int create_p2m_entries(struct domain *d, > } > /* else: third already valid */ > > - BUG_ON(third[third_table_offset(addr)].p2m.valid); > + if ( third[third_table_offset(addr)].p2m.valid ) > + { > + /* p2m entry already present */ > + free_domheap_page( > + mfn_to_page(third[third_table_offset(addr)].p2m.base)); > + }If there was already an entry here don''t we need to do something with whatever it points to? Either free it or deref or something?> > /* Allocate a new RAM page and attach */ > if (alloc)
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> The link field in pending_irq has a confusing name so rename it to > inflight and comment its behaviour. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>Committed. Thanks.
Ian Campbell
2012-Mar-14 09:48 UTC
Re: [PATCH v3 02/11] arm: fix inflight_irqs list priority ordering
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> Lower priority integers mean higher priority. > Also when we are about to insert the lowest priority IRQ so far, add it > at the end. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>Committed. Thanks.
Ian Campbell
2012-Mar-14 09:49 UTC
Re: [PATCH v3 04/11] arm: replace list_del and INIT_LIST_HEAD with list_del_init
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: This didn''t apply any more. I expect it depended on 03/11?> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/gic.c | 3 +-- > 1 files changed, 1 insertions(+), 2 deletions(-) > > diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c > index 72b122e..4842161 100644 > --- a/xen/arch/arm/gic.c > +++ b/xen/arch/arm/gic.c > @@ -506,8 +506,7 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r > p->desc->status &= ~IRQ_INPROGRESS; > GICC[GICC_DIR] = virq; > } > - list_del(&p->inflight); > - INIT_LIST_HEAD(&p->inflight); > + list_del_init(&p->inflight); > cpu_raise_softirq(current->processor, VGIC_SOFTIRQ); > spin_unlock(¤t->arch.vgic.lock); >
Ian Campbell
2012-Mar-14 09:49 UTC
Re: [PATCH v3 06/11] arm: handle dom0_max_vcpus=0 case properly
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> From: Ian Campbell <ian.campbell@citrix.com> > > Also use xzalloc_array. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>Committed. Thanks.> --- > xen/arch/arm/domain_build.c | 11 ++++++----- > 1 files changed, 6 insertions(+), 5 deletions(-) > > diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c > index cbbc0b9..ef52d1d 100644 > --- a/xen/arch/arm/domain_build.c > +++ b/xen/arch/arm/domain_build.c > @@ -14,13 +14,14 @@ integer_param("dom0_max_vcpus", opt_dom0_max_vcpus); > > struct vcpu *__init alloc_dom0_vcpu0(void) > { > - dom0->vcpu = xmalloc_array(struct vcpu *, opt_dom0_max_vcpus); > + if ( opt_dom0_max_vcpus == 0 ) > + opt_dom0_max_vcpus = num_online_cpus(); > + if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS ) > + opt_dom0_max_vcpus = MAX_VIRT_CPUS; > + > + dom0->vcpu = xzalloc_array(struct vcpu *, opt_dom0_max_vcpus); > if ( !dom0->vcpu ) > - { > - printk("failed to alloc dom0->vccpu\n"); > return NULL; > - } > - memset(dom0->vcpu, 0, opt_dom0_max_vcpus * sizeof(*dom0->vcpu)); > dom0->max_vcpus = opt_dom0_max_vcpus; > > return alloc_vcpu(dom0, 0, 0);
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> Implement xen_version, event_channel_op, memory_op sysctl and physdev_op > hypercalls.I wasn''t sure how useful this patch would be without some of the preceding patches but figured I''d take it anyway. I resolved a conflict in Makefile while applying, please check my working.> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/Makefile | 1 + > xen/arch/arm/physdev.c | 27 +++++++++++++++++++++++++++ > xen/arch/arm/traps.c | 5 +++++ > xen/include/asm-arm/hypercall.h | 1 + > 4 files changed, 34 insertions(+), 0 deletions(-) > create mode 100644 xen/arch/arm/physdev.c > > diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile > index 49b64fe..619430c 100644 > --- a/xen/arch/arm/Makefile > +++ b/xen/arch/arm/Makefile > @@ -14,6 +14,7 @@ obj-y += kernel.o > obj-y += mm.o > obj-y += p2m.o > obj-y += guestcopy.o > +obj-y += physdev.o > obj-y += setup.o > obj-y += time.o > obj-y += smpboot.o > diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c > new file mode 100644 > index 0000000..bcf4337 > --- /dev/null > +++ b/xen/arch/arm/physdev.c > @@ -0,0 +1,27 @@ > +/****************************************************************************** > + * Arch-specific physdev.c > + * > + * Copyright (c) 2012, Citrix Systems > + */ > + > +#include <xen/config.h> > +#include <xen/types.h> > +#include <xen/lib.h> > +#include <xen/errno.h> > +#include <asm/hypercall.h> > + > + > +int do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) > +{ > + printk("%s %d cmd=%d: not implemented yet\n", __func__, __LINE__, cmd); > + return -ENOSYS; > +} > + > +/* > + * Local variables: > + * mode: C > + * c-set-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c > index 750f85a..98bfcd5 100644 > --- a/xen/arch/arm/traps.c > +++ b/xen/arch/arm/traps.c > @@ -376,6 +376,11 @@ static arm_hypercall_t *arm_hypercall_table[] = { > HYPERCALL(arch_0), > HYPERCALL(sched_op), > HYPERCALL(console_io), > + HYPERCALL(xen_version), > + HYPERCALL(event_channel_op), > + HYPERCALL(memory_op), > + HYPERCALL(physdev_op), > + HYPERCALL(sysctl), > }; > > static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code) > diff --git a/xen/include/asm-arm/hypercall.h b/xen/include/asm-arm/hypercall.h > index e840507..454f02e 100644 > --- a/xen/include/asm-arm/hypercall.h > +++ b/xen/include/asm-arm/hypercall.h > @@ -2,6 +2,7 @@ > #define __ASM_ARM_HYPERCALL_H__ > > #include <public/domctl.h> /* for arch_do_domctl */ > +int do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); > > #endif /* __ASM_ARM_HYPERCALL_H__ */ > /*
Ian Campbell
2012-Mar-14 09:49 UTC
Re: [PATCH v3 09/11] arm: implement flush_tlb_all_local and flush_tlb_local
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> Call flush_tlb_all_local from create_p2m_entries after removing a page > from the p2m. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>This as well as 10 & 11 out of 11 didn''t apply, probably due to other patches I skipped in this round.
Ian Campbell
2012-Mar-14 09:50 UTC
Re: [PATCH v3 0/11] xen/arm: event channels and shared_info page
On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote:> Hi all, > this patch series implements support for injecting event channels into > the guest and enables a wider range of hypercalls for ARM guests.I previously applied 07/11 "arm: use r12 to pass the hypercall number" I have now applied: arm: introduce more hypercalls arm: handle dom0_max_vcpus=0 case prope arm: fix inflight_irqs list priority or arm: rename link to inflight I fixed up a trivial contextual conflict in "arm: introduce more hypercalls" (Makefile). Please do check I''ve done the right thing. I think I''ve commented on all the rest. Ian.
Stefano Stabellini
2012-May-25 13:38 UTC
Re: [PATCH v3 03/11] arm: support fewer LR registers than virtual irqs
On Wed, 14 Mar 2012, Ian Campbell wrote:> On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > @@ -247,6 +256,8 @@ static void __cpuinit gic_hyp_init(void) > > > GICH[GICH_HCR] = GICH_HCR_EN; > > GICH[GICH_MISR] = GICH_MISR_EOI; > > + gic.lr_mask = 0ULL; > > + INIT_LIST_HEAD(&gic.lr_pending); > > > I''m not sure this is the correct place for this initialisation. > > In Tim''s SMP series he added a call to this from gic_init_secondary_cpu, > this made sense to me because until now this function has only > initialised the per-CPU GICH registers. > > However you are now adding a global gic initialiser. I think either this > initialisation would be better off in gic_init() or we need a new > datastructure for per-CPU git information.yes, I''ll move it to gic_init
Stefano Stabellini
2012-May-25 13:44 UTC
Re: [PATCH v3 05/11] arm: shared_info page allocation and mapping
On Tue, 13 Mar 2012, Ian Campbell wrote:> On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > Allocate the shared_info page at domain creation. > > > > Implement arch_memory_op, only for XENMEM_add_to_physmap with space => > XENMAPSPACE_shared_info, so that the guest can map the shared_info page. > > > > Changes in v3: > > > > - /MEMF_bits(32)/MEMF_bits(64); > > I think MEMF_bits(64) is wrong. If you want no limit (which I think is > the case here) then you can just pass 0.OK
Stefano Stabellini
2012-May-25 13:54 UTC
Re: [PATCH v3 05/11] arm: shared_info page allocation and mapping
On Wed, 14 Mar 2012, Ian Campbell wrote:> On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > @@ -118,7 +118,12 @@ static int create_p2m_entries(struct domain *d, > > } > > /* else: third already valid */ > > > > - BUG_ON(third[third_table_offset(addr)].p2m.valid); > > + if ( third[third_table_offset(addr)].p2m.valid ) > > + { > > + /* p2m entry already present */ > > + free_domheap_page( > > + mfn_to_page(third[third_table_offset(addr)].p2m.base)); > > + } > > If there was already an entry here don''t we need to do something with > whatever it points to? Either free it or deref or something?We are already doing something: we are free''ing the old page. There is no need to do anything to the p2m entry because it is going to be overwritten by the new one few lines below.
Ian Campbell
2012-May-25 13:58 UTC
Re: [PATCH v3 05/11] arm: shared_info page allocation and mapping
On Fri, 2012-05-25 at 14:54 +0100, Stefano Stabellini wrote:> On Wed, 14 Mar 2012, Ian Campbell wrote: > > On Fri, 2012-03-02 at 14:27 +0000, Stefano Stabellini wrote: > > > @@ -118,7 +118,12 @@ static int create_p2m_entries(struct domain *d, > > > } > > > /* else: third already valid */ > > > > > > - BUG_ON(third[third_table_offset(addr)].p2m.valid); > > > + if ( third[third_table_offset(addr)].p2m.valid ) > > > + { > > > + /* p2m entry already present */ > > > + free_domheap_page( > > > + mfn_to_page(third[third_table_offset(addr)].p2m.base)); > > > + } > > > > If there was already an entry here don''t we need to do something with > > whatever it points to? Either free it or deref or something? > > We are already doing something: we are free''ing the old page. There is > no need to do anything to the p2m entry because it is going to be > overwritten by the new one few lines below.I honestly have no idea WTF I was talking about... Ian.