Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 01/40] arm: allocate top level p2m page for all non-idle domains
Not just dom0. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/domain.c | 3 +++ xen/arch/arm/p2m.c | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 5702399..4b38790 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -201,6 +201,9 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) clear_page(d->shared_info); share_xen_page_with_guest( virt_to_page(d->shared_info), d, XENSHARE_writable); + + if ( (rc = p2m_alloc_table(d)) != 0 ) + goto fail; } d->max_vcpus = 8; diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 051a0e8..4f624d8 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -203,7 +203,7 @@ int p2m_alloc_table(struct domain *d) void *p; /* First level P2M is 2 consecutive pages */ - page = alloc_domheap_pages(d, 1, 0); + page = alloc_domheap_pages(NULL, 1, 0); if ( page == NULL ) return -ENOMEM; -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 02/40] arm: handy function to print a walk of a page table
Include helpers for dumping hypervisor walks and guest p2m walks. Useful for debug but not actually used in this patch. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/mm.c | 49 +++++++++++++++++++++++++++++++++++++++++++- xen/arch/arm/p2m.c | 15 +++++++++++++ xen/include/asm-arm/page.h | 26 +++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 10ff883..715a98a 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -26,6 +26,7 @@ #include <xen/preempt.h> #include <xen/errno.h> #include <xen/guest_access.h> +#include <xen/domain_page.h> #include <asm/page.h> #include <asm/current.h> #include <public/memory.h> @@ -42,6 +43,8 @@ static lpae_t xen_xenmap[LPAE_ENTRIES] __attribute__((__aligned__(4096))); /* Non-boot CPUs use this to find the correct pagetables. */ uint64_t boot_httbr; +static paddr_t phys_offset; + /* Limits of the Xen heap */ unsigned long xenheap_mfn_start, xenheap_mfn_end; unsigned long xenheap_virt_end; @@ -53,6 +56,50 @@ unsigned long max_page; extern char __init_begin[], __init_end[]; +void dump_pt_walk(lpae_t *first, paddr_t addr) +{ + lpae_t *second = NULL, *third = NULL; + + if ( first_table_offset(addr) >= LPAE_ENTRIES ) + return; + + printk("1ST[0x%llx] = 0x%"PRIpaddr"\n", + first_table_offset(addr), + first[first_table_offset(addr)].bits); + if ( !first[first_table_offset(addr)].walk.valid || + !first[first_table_offset(addr)].walk.table ) + goto done; + + second = map_domain_page(first[first_table_offset(addr)].walk.base); + printk("2ND[0x%llx] = 0x%"PRIpaddr"\n", + second_table_offset(addr), + second[second_table_offset(addr)].bits); + if ( !second[second_table_offset(addr)].walk.valid || + !second[second_table_offset(addr)].walk.table ) + goto done; + + third = map_domain_page(second[second_table_offset(addr)].walk.base); + printk("3RD[0x%llx] = 0x%"PRIpaddr"\n", + third_table_offset(addr), + third[third_table_offset(addr)].bits); + +done: + if (third) unmap_domain_page(third); + if (second) unmap_domain_page(second); + +} + +void dump_hyp_walk(uint32_t addr) +{ + uint64_t httbr = READ_CP64(HTTBR); + + printk("Walking Hypervisor VA 0x%08"PRIx32" via HTTBR 0x%016"PRIx64"\n", + addr, httbr); + + BUG_ON( (lpae_t *)(unsigned long)(httbr - phys_offset) != xen_pgtable ); + dump_pt_walk(xen_pgtable, addr); +} + /* Map a 4k page in a fixmap entry */ void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes) { @@ -159,7 +206,7 @@ void unmap_domain_page(const void *va) * Changes here may need matching changes in head.S */ void __init setup_pagetables(unsigned long boot_phys_offset) { - paddr_t xen_paddr, phys_offset; + paddr_t xen_paddr; unsigned long dest_va; lpae_t pte, *p; int i; diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 4f624d8..ea385a6 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -5,6 +5,21 @@ #include <xen/domain_page.h> #include <asm/flushtlb.h> +void dump_p2m_lookup(struct domain *d, paddr_t addr) +{ + struct p2m_domain *p2m = &d->arch.p2m; + lpae_t *first; + + printk("dom%d IPA 0x%"PRIpaddr"\n", d->domain_id, addr); + + printk("P2M @ %p mfn:0x%lx\n", + p2m->first_level, page_to_mfn(p2m->first_level)); + + first = __map_domain_page(p2m->first_level); + dump_pt_walk(first, addr); + unmap_domain_page(first); +} + void p2m_load_VTTBR(struct domain *d) { struct p2m_domain *p2m = &d->arch.p2m; diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index b6df64e..183ba5f 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -132,10 +132,28 @@ typedef struct { unsigned long sbz1:5; } __attribute__((__packed__)) lpae_p2m_t; +/* + * Walk is the common bits of p2m and pt entries which are needed to + * simply walk the table (e.g. for debug). + */ +typedef struct { + /* These are used in all kinds of entry. */ + unsigned long valid:1; /* Valid mapping */ + unsigned long table:1; /* == 1 in 4k map entries too */ + + unsigned long pad2:10; + + /* The base address must be approprately aligned for Block entries */ + unsigned long base:28; /* Base address of block or next table */ + + unsigned long pad1:24; +} __attribute__((__packed__)) lpae_walk_t; + typedef union { uint64_t bits; lpae_pt_t pt; lpae_p2m_t p2m; + lpae_walk_t walk; } lpae_t; /* Standard entry type that we''ll use to build Xen''s own pagetables. @@ -252,6 +270,14 @@ static inline void flush_guest_tlb(void) WRITE_CP32(r0 /* dummy */, TLBIALLNSNH); } +/* Print a walk of an arbitrary page table */ +void dump_pt_walk(lpae_t *table, paddr_t addr); + +/* Print a walk of the hypervisor''s page tables for a virtual addr. */ +extern void dump_hyp_walk(uint32_t addr); +/* Print a walk of the p2m for a domain for a physical address. */ +extern void dump_p2m_lookup(struct domain *d, paddr_t addr); + /* Ask the MMU to translate a VA for us */ static inline uint64_t __va_to_par(uint32_t va) { -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 03/40] arm: correct and expand TLB flush CP15 registers
Correct spelling of TLBIALLHIS and correct definition of TLBIALLNSNHIS. Add a few more. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/include/asm-arm/cpregs.h | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/xen/include/asm-arm/cpregs.h b/xen/include/asm-arm/cpregs.h index ee8a287..7a0b49a 100644 --- a/xen/include/asm-arm/cpregs.h +++ b/xen/include/asm-arm/cpregs.h @@ -172,12 +172,19 @@ #define TLBIMVAIS p15,0,c8,c3,1 /* Invalidate unified TLB entry by MVA inner shareable */ #define TLBIASIDIS p15,0,c8,c3,2 /* Invalidate unified TLB by ASID match inner shareable */ #define TLBIMVAAIS p15,0,c8,c3,3 /* Invalidate unified TLB entry by MVA all ASID inner shareable */ +#define ITLBIALL p15,0,c8,c5,0 /* Invalidate instruction TLB */ +#define ITLBIMVA p15,0,c8,c5,1 /* Invalidate instruction TLB entry by MVA */ +#define ITLBIASID p15,0,c8,c5,2 /* Invalidate instruction TLB by ASID match */ #define DTLBIALL p15,0,c8,c6,0 /* Invalidate data TLB */ #define DTLBIMVA p15,0,c8,c6,1 /* Invalidate data TLB entry by MVA */ #define DTLBIASID p15,0,c8,c6,2 /* Invalidate data TLB by ASID match */ -#define TLBILLHIS p15,4,c8,c3,0 /* Invalidate Entire Hyp. Unified TLB inner shareable */ +#define TLBIALL p15,0,c8,c7,0 /* invalidate unified TLB */ +#define TLBIMVA p15,0,c8,c7,1 /* invalidate unified TLB entry by MVA */ +#define TLBIASID p15,0,c8,c7,2 /* invalid unified TLB by ASID match */ +#define TLBIMVAA p15,0,c8,c7,3 /* invalidate unified TLB entries by MVA all ASID */ +#define TLBIALLHIS p15,4,c8,c3,0 /* Invalidate Entire Hyp. Unified TLB inner shareable */ #define TLBIMVAHIS p15,4,c8,c3,1 /* Invalidate Unified Hyp. TLB by MVA inner shareable */ -#define TLBIALLNSNHIS p15,4,c8,c7,4 /* Invalidate Entire Non-Secure Non-Hyp. Unified TLB inner shareable */ +#define TLBIALLNSNHIS p15,4,c8,c3,4 /* Invalidate Entire Non-Secure Non-Hyp. Unified TLB inner shareable */ #define TLBIALLH p15,4,c8,c7,0 /* Invalidate Entire Hyp. Unified TLB */ #define TLBIMVAH p15,4,c8,c7,1 /* Invalidate Unified Hyp. TLB by MVA */ #define TLBIALLNSNH p15,4,c8,c7,4 /* Invalidate Entire Non-Secure Non-Hyp. Unified TLB */ -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 04/40] arm: restore stack on return from trap.
We align the stack before calling into C code but we weren''t undoing this on return. Collapse continue_(non)idle_domain into continue_new_vcpu. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 16 +++------------- xen/arch/arm/entry.S | 5 ++++- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 4b38790..9339a11 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -16,17 +16,6 @@ DEFINE_PER_CPU(struct vcpu *, curr_vcpu); -static void continue_idle_domain(struct vcpu *v) -{ - reset_stack_and_jump(idle_loop); -} - -static void continue_nonidle_domain(struct vcpu *v) -{ - /* check_wakeup_from_wait(); */ - reset_stack_and_jump(return_from_trap); -} - void idle_loop(void) { for ( ; ; ) @@ -72,9 +61,10 @@ static void continue_new_vcpu(struct vcpu *prev) schedule_tail(prev); if ( is_idle_vcpu(current) ) - continue_idle_domain(current); + reset_stack_and_jump(idle_loop); else - continue_nonidle_domain(current); + /* check_wakeup_from_wait(); */ + reset_stack_and_jump(return_to_new_vcpu); } void context_switch(struct vcpu *prev, struct vcpu *next) diff --git a/xen/arch/arm/entry.S b/xen/arch/arm/entry.S index f261a9f..7a22e2d 100644 --- a/xen/arch/arm/entry.S +++ b/xen/arch/arm/entry.S @@ -72,7 +72,9 @@ DEFINE_TRAP_ENTRY(hypervisor) DEFINE_TRAP_ENTRY(irq) DEFINE_TRAP_ENTRY(fiq) -ENTRY(return_from_trap) +return_from_trap: + mov sp, r11 +ENTRY(return_to_new_vcpu) ldr r11, [sp, #UREGS_cpsr] and r11, #PSR_MODE_MASK cmp r11, #PSR_MODE_HYP @@ -82,6 +84,7 @@ ENTRY(return_to_guest) mov r11, sp bic sp, #7 /* Align the stack pointer */ bl leave_hypervisor_tail + mov sp, r11 RESTORE_ONE_BANKED(SP_usr) /* LR_usr is the same physical register as lr and is restored below */ RESTORE_BANKED(svc) -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 05/40] arm: enable interrupts while handling traps
For most traps we can do this as soon as we have saved the necessary state. For IRQs and FIQs we must wait until we have acked the interrupt with the GIC. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/entry.S | 17 ++++++++++++++--- xen/arch/arm/gic.c | 2 ++ xen/arch/arm/traps.c | 1 - 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/xen/arch/arm/entry.S b/xen/arch/arm/entry.S index 7a22e2d..5bc3906 100644 --- a/xen/arch/arm/entry.S +++ b/xen/arch/arm/entry.S @@ -46,6 +46,17 @@ save_guest_regs: ALIGN; \ trap_##trap: \ SAVE_ALL; \ + cpsie i; /* local_irq_enable */ \ + adr lr, return_from_trap; \ + mov r0, sp; \ + mov r11, sp; \ + bic sp, #7; /* Align the stack pointer (noop on guest trap) */ \ + b do_trap_##trap + +#define DEFINE_TRAP_ENTRY_NOIRQ(trap) \ + ALIGN; \ +trap_##trap: \ + SAVE_ALL; \ adr lr, return_from_trap; \ mov r0, sp; \ mov r11, sp; \ @@ -69,8 +80,8 @@ DEFINE_TRAP_ENTRY(supervisor_call) DEFINE_TRAP_ENTRY(prefetch_abort) DEFINE_TRAP_ENTRY(data_abort) DEFINE_TRAP_ENTRY(hypervisor) -DEFINE_TRAP_ENTRY(irq) -DEFINE_TRAP_ENTRY(fiq) +DEFINE_TRAP_ENTRY_NOIRQ(irq) +DEFINE_TRAP_ENTRY_NOIRQ(fiq) return_from_trap: mov sp, r11 @@ -83,7 +94,7 @@ ENTRY(return_to_new_vcpu) ENTRY(return_to_guest) mov r11, sp bic sp, #7 /* Align the stack pointer */ - bl leave_hypervisor_tail + bl leave_hypervisor_tail /* Disables interrupts on return */ mov sp, r11 RESTORE_ONE_BANKED(SP_usr) /* LR_usr is the same physical register as lr and is restored below */ diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index cc9d37b..1a2b95f 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -509,6 +509,8 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq) uint32_t intack = GICC[GICC_IAR]; unsigned int irq = intack & GICC_IA_IRQ; + local_irq_enable(); + if ( irq == 1023 ) /* Spurious interrupt */ return; diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index abc26a3..5ed754f 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -412,7 +412,6 @@ 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(); if ( iss != XEN_HYPERCALL_TAG ) { -- 1.7.9.1
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/traps.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 5ed754f..5d8b7f9 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -373,6 +373,8 @@ typedef unsigned long arm_hypercall_t( [ __HYPERVISOR_ ## x ] = (arm_hypercall_t *) do_ ## x static arm_hypercall_t *arm_hypercall_table[] = { + HYPERCALL(memory_op), + HYPERCALL(domctl), HYPERCALL(arch_0), HYPERCALL(sched_op), HYPERCALL(console_io), -- 1.7.9.1
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 67 +++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/dummy.S | 3 -- xen/include/public/arch-arm.h | 9 ----- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 9339a11..b099d91 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -144,6 +144,17 @@ void free_vcpu_struct(struct vcpu *v) free_xenheap_page(v); } +struct vcpu_guest_context *alloc_vcpu_guest_context(void) +{ + return xmalloc(struct vcpu_guest_context); + +} + +void free_vcpu_guest_context(struct vcpu_guest_context *vgc) +{ + xfree(vgc); +} + int vcpu_initialise(struct vcpu *v) { int rc = 0; @@ -212,6 +223,62 @@ void arch_domain_destroy(struct domain *d) /* domain_vgic_destroy */ } +static int is_guest_psr(uint32_t psr) +{ + switch (psr & PSR_MODE_MASK) + { + case PSR_MODE_USR: + case PSR_MODE_FIQ: + case PSR_MODE_IRQ: + case PSR_MODE_SVC: + case PSR_MODE_ABT: + case PSR_MODE_UND: + case PSR_MODE_SYS: + return 1; + case PSR_MODE_MON: + case PSR_MODE_HYP: + default: + return 0; + } +} + +/* + * Initialise VCPU state. The context can be supplied by either the + * toolstack (XEN_DOMCTL_setvcpucontext) or the guest + * (VCPUOP_initialise) and therefore must be properly validated. + */ +int arch_set_info_guest( + struct vcpu *v, vcpu_guest_context_u c) +{ + struct cpu_user_regs *regs = &c.nat->user_regs; + + if ( !is_guest_psr(regs->cpsr) ) + return -EINVAL; + + if ( regs->spsr_svc && !is_guest_psr(regs->spsr_svc) ) + return -EINVAL; + if ( regs->spsr_abt && !is_guest_psr(regs->spsr_abt) ) + return -EINVAL; + if ( regs->spsr_und && !is_guest_psr(regs->spsr_und) ) + return -EINVAL; + if ( regs->spsr_irq && !is_guest_psr(regs->spsr_irq) ) + return -EINVAL; + if ( regs->spsr_fiq && !is_guest_psr(regs->spsr_fiq) ) + return -EINVAL; + + v->arch.cpu_info->guest_cpu_user_regs = *regs; + + /* XXX other state: + * - SCTLR + * - TTBR0/1 + * - TTBCR + */ + + clear_bit(_VPF_down, &v->pause_flags); + + return 0; +} + void arch_dump_domain_info(struct domain *d) { } diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S index 016340c..3b48917 100644 --- a/xen/arch/arm/dummy.S +++ b/xen/arch/arm/dummy.S @@ -20,11 +20,8 @@ DUMMY(pirq_guest_unbind); DUMMY(pirq_set_affinity); /* VCPU */ -DUMMY(alloc_vcpu_guest_context); DUMMY(arch_get_info_guest); -DUMMY(arch_set_info_guest); DUMMY(arch_vcpu_reset); -DUMMY(free_vcpu_guest_context); DUMMY(sync_vcpu_execstate); NOP(update_vcpu_system_time); DUMMY(vcpu_show_execution_state); diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 1b1bcf3..e439727 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -124,15 +124,6 @@ typedef uint32_t xen_ulong_t; struct vcpu_guest_context { struct cpu_user_regs user_regs; /* User-level CPU registers */ - union { - uint32_t reg[16]; - struct { - uint32_t __pad[12]; - uint32_t sp; /* r13 */ - uint32_t lr; /* r14 */ - uint32_t pc; /* r15 */ - }; - }; }; typedef struct vcpu_guest_context vcpu_guest_context_t; DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 08/40] arm: print domid as part of debug trap
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/traps.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 5d8b7f9..40bb375 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -388,25 +388,26 @@ static arm_hypercall_t *arm_hypercall_table[] = { static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code) { uint32_t reg, *r; - + uint32_t domid = current->domain->domain_id; switch ( code ) { case 0xe0 ... 0xef: reg = code - 0xe0; r = ®s->r0 + reg; - printk("R%d = %#010"PRIx32" at %#010"PRIx32"\n", reg, *r, regs->pc); + printk("DOM%d: R%d = %#010"PRIx32" at %#010"PRIx32"\n", + domid, reg, *r, regs->pc); break; case 0xfd: - printk("Reached %08"PRIx32"\n", regs->pc); + printk("DOM%d: Reached %#010"PRIx32"\n", domid, regs->pc); break; case 0xfe: printk("%c", (char)(regs->r0 & 0xff)); break; case 0xff: - printk("DEBUG\n"); + printk("DOM%d: DEBUG\n", domid); show_execution_state(regs); break; default: - panic("Unhandled debug trap %#x\n", code); + panic("DOM%d: Unhandled debug trap %#x\n", domid, code); break; } } -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 09/40] arm: remove unnecessarily verbose print from p2m_load_VTTBR
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/p2m.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index ea385a6..6df5b62 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -28,8 +28,6 @@ void p2m_load_VTTBR(struct domain *d) vttbr |= ((uint64_t)p2m->vmid&0xff)<<48; - printk("VTTBR dom%d = %"PRIx64"\n", d->domain_id, vttbr); - WRITE_CP64(vttbr, VTTBR); isb(); /* Ensure update is visible */ } -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH 00/40 V2] arm: boot a dom1 to "Calibrating delay loop" then hang
I have (I think) addressed all review comments against non-HACK and non-toolstack (which I''ve left till later) patches in this series, as noted in my various replies to the review. In the list: An "A" in the list below indicates that I think the patch has sufficient Acked-by''s to be committed (assuming the prerequisites can go in). An "X" means I don''t consider this patch for committing. A "!" means I didn''t consider review comments yet. Currently this requires Jan''s "arm: fix build after c/s 25477:e12e0b038219" patch, which I have not included here, in order to build. I intend to commit those patches which are acked and which do not depend on non-acked patches shortly. A 01 arm: allocate top level p2m page for all non-idle domains A 02 arm: handy function to print a walk of a page table A 03 arm: correct and expand TLB flush CP15 registers A 04 arm: restore stack on return from trap. A 05 arm: enable interrupts while handling traps A 06 arm: hook up domctl and memory_op A 07 arm: allocate and setup a guest vcpu. A 08 arm: print domid as part of debug trap A 09 arm: remove unnecessarily verbose print from p2m_load_VTTBR A 10 arm: implement p2m lookup A 11 arm: remove hard tabs from init_idle_domain A 12 arm: stub out sync_vcpu_execstate A 13 arm: implement stub version of flush_tlb_mask. A 14 arm: do not set max_vcpus = 8 in arch_domain_create. A 15 arm: Add simple cpu_{sibling,core}_mask 16 arm: allow p2m to be created with specific MATTR. 17 arm: implement vpl011 (UART) emulator. A 18 arm: context switch a bunch of guest state. A 19 arm: dump a page table walk when va_to_par fails. A 20 arm: dump guest s1 walk on data abort which is not a stage 2 issue. 21 arm: implement vcpu_show_execution_state A 22 arm: use correct attributes for mappings in copy_from_paddr() A 23 arm: map fixmaps non-executable. A 24 arm: fix locking in create_p2m_entries 25 arm: split pending SPIs (global) out from pending PPIs and SGIs (per CPU) 26 arm: use interrupt safe spin locks in vgic_vcpu_inject_irq A 27 arm: map GICV in all domains, not just dom0. 28 arm: enable data-cache at the same time as enabling the MMU, not before A 29 arm: Upgrade guest barriers to Outer-Shareable. Enable Protected Table Walk. A 30 arm: gic.lock can be taken in interrupt context, so lock appropriately. A 31 arm: context switch virtual timer registers A 32 arm: the hyp timer seems to work in newer model versions, default to using it. 33 arm: unwind allocations etc on arch_domain_create_failure X! 34 HACK: arm: initial XENMAPSPACE_gmfn_foreign A 35 arm: move PSR flag definitions into interface, for tools use. X! 36 libxc: add ARM support to xc_dom (PV domain building) 37 arm: implement VGCF_online A 38 arm: fix typo s/approprately/appropriately/g X! 39 HACK: add simple xcbuild X! 40 HACK: arm: disable hypercall continuations.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/p2m.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/p2m.h | 3 +++ 2 files changed, 48 insertions(+), 0 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 6df5b62..ec41d38 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -32,6 +32,51 @@ void p2m_load_VTTBR(struct domain *d) isb(); /* Ensure update is visible */ } +/* + * Lookup the MFN corresponding to a domain''s PFN. + * + * There are no processor functions to do a stage 2 only lookup therefore we + * do a a software walk. + */ +paddr_t p2m_lookup(struct domain *d, paddr_t paddr) +{ + struct p2m_domain *p2m = &d->arch.p2m; + lpae_t pte, *first = NULL, *second = NULL, *third = NULL; + paddr_t maddr = INVALID_PADDR; + + spin_lock(&p2m->lock); + + first = __map_domain_page(p2m->first_level); + + pte = first[first_table_offset(paddr)]; + if ( !pte.p2m.valid || !pte.p2m.table ) + goto done; + + second = map_domain_page(pte.p2m.base); + pte = second[second_table_offset(paddr)]; + if ( !pte.p2m.valid || !pte.p2m.table ) + goto done; + + third = map_domain_page(pte.p2m.base); + pte = third[third_table_offset(paddr)]; + + /* This bit must be one in the level 3 entry */ + if ( !pte.p2m.table ) + pte.bits = 0; + +done: + if ( pte.p2m.valid ) + maddr = (pte.bits & PADDR_MASK & PAGE_MASK) | (paddr & ~PAGE_MASK); + + if (third) unmap_domain_page(third); + if (second) unmap_domain_page(second); + if (first) unmap_domain_page(first); + + spin_unlock(&p2m->lock); + + return maddr; +} + int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, unsigned int order) diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 349923a..666bb88 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -32,6 +32,9 @@ int p2m_alloc_table(struct domain *d); /* */ void p2m_load_VTTBR(struct domain *d); +/* Look up the MFN corresponding to a domain''s PFN. */ +paddr_t p2m_lookup(struct domain *d, paddr_t gpfn); + /* Setup p2m RAM mapping for domain d from start-end. */ int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end); /* Map MMIO regions in the p2m: start_gaddr and end_gaddr is the range -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 11/40] arm: remove hard tabs from init_idle_domain
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/setup.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 0df3c1a..81ababb 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -47,9 +47,9 @@ static __attribute_used__ void init_done(void) static void __init init_idle_domain(void) { - scheduler_init(); - set_current(idle_vcpu[0]); - /* TODO: setup_idle_pagetable(); */ + scheduler_init(); + set_current(idle_vcpu[0]); + /* TODO: setup_idle_pagetable(); */ } static void __init processor_id(void) -- 1.7.9.1
We don''t do lazy exec state switching so there isn''t actually anything to do. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 5 +++++ xen/arch/arm/dummy.S | 1 - 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index b099d91..2c3fc90 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -96,6 +96,11 @@ void sync_local_execstate(void) /* Nothing to do -- no lazy switching */ } +void sync_vcpu_execstate(struct vcpu *v) +{ + /* Nothing to do -- no lazy switching */ +} + void startup_cpu_idle_loop(void) { struct vcpu *v = current; diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S index 3b48917..8eddd15 100644 --- a/xen/arch/arm/dummy.S +++ b/xen/arch/arm/dummy.S @@ -22,7 +22,6 @@ DUMMY(pirq_set_affinity); /* VCPU */ DUMMY(arch_get_info_guest); DUMMY(arch_vcpu_reset); -DUMMY(sync_vcpu_execstate); NOP(update_vcpu_system_time); DUMMY(vcpu_show_execution_state); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 13/40] arm: implement stub version of flush_tlb_mask.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/dummy.S | 1 - xen/arch/arm/smp.c | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletions(-) diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S index 8eddd15..c001e8d 100644 --- a/xen/arch/arm/dummy.S +++ b/xen/arch/arm/dummy.S @@ -48,7 +48,6 @@ DUMMY(domain_get_maximum_gpfn); DUMMY(domain_relinquish_resources); DUMMY(domain_set_time_offset); DUMMY(dom_cow); -DUMMY(flush_tlb_mask); DUMMY(gmfn_to_mfn); DUMMY(hypercall_create_continuation); DUMMY(send_timer_event); diff --git a/xen/arch/arm/smp.c b/xen/arch/arm/smp.c index cad84f5..824c8c8 100644 --- a/xen/arch/arm/smp.c +++ b/xen/arch/arm/smp.c @@ -1,5 +1,14 @@ #include <xen/config.h> +#include <asm/system.h> #include <asm/smp.h> +#include <asm/cpregs.h> +#include <asm/page.h> + +void flush_tlb_mask(const cpumask_t *mask) +{ + /* XXX IPI other processors */ + flush_xen_data_tlb(); +} void smp_call_function( void (*func) (void *info), -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 14/40] arm: do not set max_vcpus = 8 in arch_domain_create.
XEN_DOMCTL_max_vcpus cannot reduce max_vcpus and therefore we can''t create a smaller guest. The limit of 8 (due to GIC limits) should be expressed in MAX_VIRT_CPUS. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 2 -- xen/include/asm-arm/config.h | 2 +- 2 files changed, 1 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 2c3fc90..63bad07 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -212,8 +212,6 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) goto fail; } - d->max_vcpus = 8; - if ( (rc = domain_vgic_init(d)) != 0 ) goto fail; diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h index 91e87e1..7d02cc7 100644 --- a/xen/include/asm-arm/config.h +++ b/xen/include/asm-arm/config.h @@ -27,7 +27,7 @@ #define NR_CPUS 128 #endif -#define MAX_VIRT_CPUS 128 /* XXX */ +#define MAX_VIRT_CPUS 8 #define MAX_HVM_VCPUS MAX_VIRT_CPUS #define asmlinkage /* Nothing needed */ -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 15/40] arm: Add simple cpu_{sibling, core}_mask
This needs to be done for all cpus. The allocations require smp_prepare_cpus to be called a bit later on. In a previous version of this patch these maps were being zeroed (instead of setting the CPU itself in them). This in turn causes cpumask_first to return NR_CPUS, which in turn was causing default_vcpu0_location to misbehave and read off the end of its cnt array. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/dummy.S | 2 -- xen/arch/arm/setup.c | 4 ++-- xen/arch/arm/smpboot.c | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S index c001e8d..03f7489 100644 --- a/xen/arch/arm/dummy.S +++ b/xen/arch/arm/dummy.S @@ -7,8 +7,6 @@ x: .word 0xe7f000f0 /* Undefined instruction */ x: mov pc, lr /* SMP support */ -DUMMY(per_cpu__cpu_core_mask); -DUMMY(per_cpu__cpu_sibling_mask); DUMMY(node_online_map); DUMMY(smp_send_state_dump); diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 81ababb..d6c0178 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -173,8 +173,6 @@ void __init start_xen(unsigned long boot_phys_offset, set_current((struct vcpu *)0xfffff000); /* debug sanity */ idle_vcpu[0] = current; - smp_prepare_cpus(cpus); - init_xen_time(); setup_mm(atag_paddr, fdt_size); @@ -214,6 +212,8 @@ void __init start_xen(unsigned long boot_phys_offset, local_irq_enable(); + smp_prepare_cpus(cpus); + initialize_keytable(); console_init_postirq(); diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c index ea05afc..6463a8d 100644 --- a/xen/arch/arm/smpboot.c +++ b/xen/arch/arm/smpboot.c @@ -52,6 +52,23 @@ unsigned long __initdata ready_cpus = 0; /* ID of the PCPU we''re running on */ DEFINE_PER_CPU(unsigned int, cpu_id); +/* XXX these seem awfully x86ish... */ +/* representing HT siblings of each logical CPU */ +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_mask); +/* representing HT and core siblings of each logical CPU */ +DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_mask); + +static void setup_cpu_sibling_map(int cpu) +{ + if ( !zalloc_cpumask_var(&per_cpu(cpu_sibling_mask, cpu)) || + !zalloc_cpumask_var(&per_cpu(cpu_core_mask, cpu)) ) + panic("No memory for CPU sibling/core maps\n"); + + /* A CPU is a sibling with itself and is always on its own core. */ + cpumask_set_cpu(cpu, per_cpu(cpu_sibling_mask, cpu)); + cpumask_set_cpu(cpu, per_cpu(cpu_core_mask, cpu)); +} + void __init smp_prepare_cpus (unsigned int max_cpus) @@ -65,6 +82,8 @@ smp_prepare_cpus (unsigned int max_cpus) for ( i = 0; i < max_cpus; i++ ) cpumask_set_cpu(i, &cpu_possible_map); cpumask_copy(&cpu_present_map, &cpu_possible_map); + + setup_cpu_sibling_map(0); } void __init @@ -115,6 +134,8 @@ void __cpuinit start_secondary(unsigned long boot_phys_offset, set_current(idle_vcpu[cpuid]); + setup_cpu_sibling_map(cpuid); + /* Run local notifiers */ notify_cpu_starting(cpuid); wmb(); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 16/40] arm: allow p2m to be created with specific MATTR.
Rename p2m_create_entry to p2m_create_table since it can now only be used to insert non-leaf entries into the page table. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/p2m.c | 22 ++++++++++++---------- xen/include/asm-arm/page.h | 6 ++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index ec41d38..35bfa2f 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -91,7 +91,8 @@ int p2m_pod_decrease_reservation(struct domain *d, return -ENOSYS; } -static int p2m_create_entry(struct domain *d, +/* Allocate a new page table page and hook it in via the given entry */ +static int p2m_create_table(struct domain *d, lpae_t *entry) { struct p2m_domain *p2m = &d->arch.p2m; @@ -111,7 +112,7 @@ static int p2m_create_entry(struct domain *d, clear_page(p); unmap_domain_page(p); - pte = mfn_to_p2m_entry(page_to_mfn(page)); + pte = mfn_to_p2m_entry(page_to_mfn(page), MATTR_MEM); write_pte(entry, pte); @@ -122,7 +123,8 @@ static int create_p2m_entries(struct domain *d, int alloc, paddr_t start_gpaddr, paddr_t end_gpaddr, - paddr_t maddr) + paddr_t maddr, + int mattr) { int rc; struct p2m_domain *p2m = &d->arch.p2m; @@ -140,7 +142,7 @@ static int create_p2m_entries(struct domain *d, { if ( !first[first_table_offset(addr)].p2m.valid ) { - rc = p2m_create_entry(d, &first[first_table_offset(addr)]); + rc = p2m_create_table(d, &first[first_table_offset(addr)]); if ( rc < 0 ) { printk("p2m_populate_ram: L1 failed\n"); goto out; @@ -159,7 +161,7 @@ static int create_p2m_entries(struct domain *d, if ( !second[second_table_offset(addr)].p2m.valid ) { - rc = p2m_create_entry(d, &second[second_table_offset(addr)]); + rc = p2m_create_table(d, &second[second_table_offset(addr)]); if ( rc < 0 ) { printk("p2m_populate_ram: L2 failed\n"); goto out; @@ -198,11 +200,11 @@ static int create_p2m_entries(struct domain *d, goto out; } - pte = mfn_to_p2m_entry(page_to_mfn(page)); + pte = mfn_to_p2m_entry(page_to_mfn(page), mattr); write_pte(&third[third_table_offset(addr)], pte); } else { - lpae_t pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT); + lpae_t pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr); write_pte(&third[third_table_offset(addr)], pte); maddr += PAGE_SIZE; } @@ -226,7 +228,7 @@ int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end) { - return create_p2m_entries(d, 1, start, end, 0); + return create_p2m_entries(d, 1, start, end, 0, MATTR_MEM); } int map_mmio_regions(struct domain *d, @@ -234,7 +236,7 @@ int map_mmio_regions(struct domain *d, paddr_t end_gaddr, paddr_t maddr) { - return create_p2m_entries(d, 0, start_gaddr, end_gaddr, maddr); + return create_p2m_entries(d, 0, start_gaddr, end_gaddr, maddr, MATTR_DEV); } int guest_physmap_add_page(struct domain *d, @@ -244,7 +246,7 @@ int guest_physmap_add_page(struct domain *d, { return create_p2m_entries(d, 0, gpfn << PAGE_SHIFT, (gpfn + (1<<page_order)) << PAGE_SHIFT, - mfn << PAGE_SHIFT); + mfn << PAGE_SHIFT, MATTR_MEM); } void guest_physmap_remove_page(struct domain *d, diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 183ba5f..2783c30 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -46,6 +46,8 @@ #define DEV_WC BUFFERABLE #define DEV_CACHED WRITEBACK +#define MATTR_DEV 0x1 +#define MATTR_MEM 0xf #ifndef __ASSEMBLY__ @@ -187,7 +189,7 @@ static inline lpae_t mfn_to_xen_entry(unsigned long mfn) return e; } -static inline lpae_t mfn_to_p2m_entry(unsigned long mfn) +static inline lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr) { paddr_t pa = ((paddr_t) mfn) << PAGE_SHIFT; lpae_t e = (lpae_t) { @@ -196,7 +198,7 @@ static inline lpae_t mfn_to_p2m_entry(unsigned long mfn) .p2m.sh = LPAE_SH_OUTER, .p2m.write = 1, .p2m.read = 1, - .p2m.mattr = 0xf, + .p2m.mattr = mattr, .p2m.table = 1, .p2m.valid = 1, }; -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 17/40] arm: implement vpl011 (UART) emulator.
This is not interended to provide a full emulation, but rather just enough to satisfy the use made by Linux'' boot time decompressor code (which is too early for DT etc) Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/Makefile | 1 + xen/arch/arm/domain.c | 5 ++ xen/arch/arm/io.c | 1 + xen/arch/arm/io.h | 1 + xen/arch/arm/vpl011.c | 145 ++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/vpl011.h | 34 ++++++++++ xen/include/asm-arm/domain.h | 8 ++ 7 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 xen/arch/arm/vpl011.c create mode 100644 xen/arch/arm/vpl011.h diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 9440a21..5a87ba6 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -25,6 +25,7 @@ obj-y += shutdown.o obj-y += traps.o obj-y += vgic.o obj-y += vtimer.o +obj-y += vpl011.o #obj-bin-y += ....o diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 63bad07..931261b 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -13,6 +13,7 @@ #include "gic.h" #include "vtimer.h" +#include "vpl011.h" DEFINE_PER_CPU(struct vcpu *, curr_vcpu); @@ -215,6 +216,10 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) if ( (rc = domain_vgic_init(d)) != 0 ) goto fail; + /* Domain 0 gets a real UART not an emulated one */ + if ( d->domain_id && (rc = domain_uart0_init(d)) != 0 ) + goto fail; + rc = 0; fail: return rc; diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c index 4461225..18f6164 100644 --- a/xen/arch/arm/io.c +++ b/xen/arch/arm/io.c @@ -25,6 +25,7 @@ static const struct mmio_handler *const mmio_handlers[] { &vgic_distr_mmio_handler, + &uart0_mmio_handler, }; #define MMIO_HANDLER_NR ARRAY_SIZE(mmio_handlers) diff --git a/xen/arch/arm/io.h b/xen/arch/arm/io.h index 8cc5ca7..9a507f5 100644 --- a/xen/arch/arm/io.h +++ b/xen/arch/arm/io.h @@ -40,6 +40,7 @@ struct mmio_handler { }; extern const struct mmio_handler vgic_distr_mmio_handler; +extern const struct mmio_handler uart0_mmio_handler; extern int handle_mmio(mmio_info_t *info); diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c new file mode 100644 index 0000000..5dc8b28 --- /dev/null +++ b/xen/arch/arm/vpl011.c @@ -0,0 +1,145 @@ +/* + * xen/arch/arm/vpl011.c + * + * ARM PL011 UART Emulator (DEBUG) + * + * Ian Campbell <ian.campbell@citrix.com> + * Copyright (c) 2012 Citrix Systems. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This is not intended to be a full emulation of a PL011 + * device. Rather it is intended to provide a sufficient veneer of one + * that early code (such as Linux''s boot time decompressor) which + * hardcodes output directly to such a device are able to make progress. + * + * This device is not intended to be enumerable or exposed to the OS + * (e.g. via Device Tree). + */ + +#include <xen/config.h> +#include <xen/lib.h> +#include <xen/sched.h> +#include <xen/errno.h> +#include <xen/ctype.h> + +#include "io.h" + +#define UART0_START 0x1c090000 +#define UART0_END (UART0_START+65536) + +#define UARTDR 0x000 +#define UARTFR 0x018 + +int domain_uart0_init(struct domain *d) +{ + ASSERT( d->domain_id ); + + spin_lock_init(&d->arch.uart0.lock); + d->arch.uart0.idx = 0; + + d->arch.uart0.buf = xzalloc_array(char, VPL011_BUF_SIZE); + if ( !d->arch.uart0.buf ) + return -ENOMEM; + + return 0; + +} + +static void uart0_print_char(char c) +{ + struct vpl011 *uart = ¤t->domain->arch.uart0; + + /* Accept only printable characters, newline, and horizontal tab. */ + if ( !isprint(c) && (c != ''\n'') && (c != ''\t'') ) + return ; + + spin_lock(&uart->lock); + uart->buf[uart->idx++] = c; + if ( (uart->idx == (VPL011_BUF_SIZE - 2)) || (c == ''\n'') ) + { + if ( c != ''\n'' ) + uart->buf[uart->idx++] = ''\n''; + uart->buf[uart->idx] = ''\0''; + printk(XENLOG_G_DEBUG "DOM%u: %s", + current->domain->domain_id, uart->buf); + uart->idx = 0; + } + spin_unlock(&uart->lock); +} + +static int uart0_mmio_check(struct vcpu *v, paddr_t addr) +{ + return addr >= UART0_START && addr < UART0_END; +} + +static int uart0_mmio_read(struct vcpu *v, mmio_info_t *info) +{ + struct hsr_dabt dabt = info->dabt; + struct cpu_user_regs *regs = guest_cpu_user_regs(); + uint32_t *r = ®s->r0 + dabt.reg; + int offset = (int)(info->gpa - UART0_START); + + switch ( offset ) + { + case UARTDR: + *r = 0; + return 1; + case UARTFR: + *r = 0x87; /* All holding registers empty, ready to send etc */ + return 1; + default: + printk("VPL011: unhandled read r%d offset %#08x\n", + dabt.reg, offset); + domain_crash_synchronous(); + } +} + +static int uart0_mmio_write(struct vcpu *v, mmio_info_t *info) +{ + struct hsr_dabt dabt = info->dabt; + struct cpu_user_regs *regs = guest_cpu_user_regs(); + uint32_t *r = ®s->r0 + dabt.reg; + int offset = (int)(info->gpa - UART0_START); + + switch ( offset ) + { + case UARTDR: + /* ignore any status bits */ + uart0_print_char((int)((*r) & 0xFF)); + return 1; + case UARTFR: + /* Silently ignore */ + return 1; + default: + printk("VPL011: unhandled write r%d=%"PRIx32" offset %#08x\n", + dabt.reg, *r, offset); + domain_crash_synchronous(); + } +} + +const struct mmio_handler uart0_mmio_handler = { + .check_handler = uart0_mmio_check, + .read_handler = uart0_mmio_read, + .write_handler = uart0_mmio_write, +}; + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/xen/arch/arm/vpl011.h b/xen/arch/arm/vpl011.h new file mode 100644 index 0000000..952d812 --- /dev/null +++ b/xen/arch/arm/vpl011.h @@ -0,0 +1,34 @@ +/* + * xen/arch/arm/vpl011.h + * + * ARM PL011 Emulation Support + * + * Ian Campbell <ian.campbell@citrix.com> + * Copyright (c) 2012 Citrix Systems. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_VPL011_H__ +#define __ARCH_ARM_VPL011_H__ + +extern int domain_uart0_init(struct domain *d); + +#endif + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 10ed540..f295a82 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -48,6 +48,14 @@ struct arch_domain struct vgic_irq_rank *shared_irqs; struct pending_irq *pending_irqs; } vgic; + + struct vpl011 { +#define VPL011_BUF_SIZE 128 + char *buf; + int idx; + spinlock_t lock; + } uart0; + } __cacheline_aligned; struct arch_vcpu -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 18/40] arm: context switch a bunch of guest state.
I haven''t investigated what if any of this could be done lazily. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 122 +++++++++++++++++++++++++++++++++++++++-- xen/arch/arm/gic.c | 25 ++++++++- xen/arch/arm/gic.h | 9 ++- xen/include/asm-arm/cpregs.h | 29 +++++++++- xen/include/asm-arm/domain.h | 33 ++++++++++- xen/include/public/arch-arm.h | 3 + 6 files changed, 208 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 931261b..d11be78 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -36,12 +36,124 @@ void idle_loop(void) static void ctxt_switch_from(struct vcpu *p) { + /* CP 15 */ + p->arch.csselr = READ_CP32(CSSELR); + + /* Control Registers */ + p->arch.actlr = READ_CP32(ACTLR); + p->arch.sctlr = READ_CP32(SCTLR); + p->arch.cpacr = READ_CP32(CPACR); + + p->arch.contextidr = READ_CP32(CONTEXTIDR); + p->arch.tpidrurw = READ_CP32(TPIDRURW); + p->arch.tpidruro = READ_CP32(TPIDRURO); + p->arch.tpidrprw = READ_CP32(TPIDRPRW); + + /* XXX only save these if ThumbEE e.g. ID_PFR0.THUMB_EE_SUPPORT */ + p->arch.teecr = READ_CP32(TEECR); + p->arch.teehbr = READ_CP32(TEEHBR); + + p->arch.joscr = READ_CP32(JOSCR); + p->arch.jmcr = READ_CP32(JMCR); + + isb(); + + /* MMU */ + p->arch.vbar = READ_CP32(VBAR); + p->arch.ttbcr = READ_CP32(TTBCR); + /* XXX save 64 bit TTBR if guest is LPAE */ + p->arch.ttbr0 = READ_CP32(TTBR0); + p->arch.ttbr1 = READ_CP32(TTBR1); + + p->arch.dacr = READ_CP32(DACR); + p->arch.par = READ_CP64(PAR); + p->arch.mair0 = READ_CP32(MAIR0); + p->arch.mair1 = READ_CP32(MAIR1); + + /* Fault Status */ + p->arch.dfar = READ_CP32(DFAR); + p->arch.ifar = READ_CP32(IFAR); + p->arch.dfsr = READ_CP32(DFSR); + p->arch.ifsr = READ_CP32(IFSR); + p->arch.adfsr = READ_CP32(ADFSR); + p->arch.aifsr = READ_CP32(AIFSR); + + /* XXX MPU */ + + /* XXX VFP */ + + /* XXX VGIC */ + gic_save_state(p); + + isb(); context_saved(p); } static void ctxt_switch_to(struct vcpu *n) { + uint32_t hcr; + + hcr = READ_CP32(HCR); + WRITE_CP32(hcr & ~HCR_VM, HCR); + isb(); + p2m_load_VTTBR(n->domain); + isb(); + + /* XXX VGIC */ + gic_restore_state(n); + + /* XXX VFP */ + + /* XXX MPU */ + + /* Fault Status */ + WRITE_CP32(n->arch.dfar, DFAR); + WRITE_CP32(n->arch.ifar, IFAR); + WRITE_CP32(n->arch.dfsr, DFSR); + WRITE_CP32(n->arch.ifsr, IFSR); + WRITE_CP32(n->arch.adfsr, ADFSR); + WRITE_CP32(n->arch.aifsr, AIFSR); + + /* MMU */ + WRITE_CP32(n->arch.vbar, VBAR); + WRITE_CP32(n->arch.ttbcr, TTBCR); + /* XXX restore 64 bit TTBR if guest is LPAE */ + WRITE_CP32(n->arch.ttbr0, TTBR0); + WRITE_CP32(n->arch.ttbr1, TTBR1); + + WRITE_CP32(n->arch.dacr, DACR); + WRITE_CP64(n->arch.par, PAR); + WRITE_CP32(n->arch.mair0, MAIR0); + WRITE_CP32(n->arch.mair1, MAIR1); + isb(); + + /* Control Registers */ + WRITE_CP32(n->arch.actlr, ACTLR); + WRITE_CP32(n->arch.sctlr, SCTLR); + WRITE_CP32(n->arch.cpacr, CPACR); + + WRITE_CP32(n->arch.contextidr, CONTEXTIDR); + WRITE_CP32(n->arch.tpidrurw, TPIDRURW); + WRITE_CP32(n->arch.tpidruro, TPIDRURO); + WRITE_CP32(n->arch.tpidrprw, TPIDRPRW); + + /* XXX only restore these if ThumbEE e.g. ID_PFR0.THUMB_EE_SUPPORT */ + WRITE_CP32(n->arch.teecr, TEECR); + WRITE_CP32(n->arch.teehbr, TEEHBR); + + WRITE_CP32(n->arch.joscr, JOSCR); + WRITE_CP32(n->arch.jmcr, JMCR); + + isb(); + + /* CP 15 */ + WRITE_CP32(n->arch.csselr, CSSELR); + + isb(); + + WRITE_CP32(hcr, HCR); + isb(); } static void schedule_tail(struct vcpu *prev) @@ -258,6 +370,7 @@ static int is_guest_psr(uint32_t psr) int arch_set_info_guest( struct vcpu *v, vcpu_guest_context_u c) { + struct vcpu_guest_context *ctxt = c.nat; struct cpu_user_regs *regs = &c.nat->user_regs; if ( !is_guest_psr(regs->cpsr) ) @@ -276,11 +389,10 @@ int arch_set_info_guest( v->arch.cpu_info->guest_cpu_user_regs = *regs; - /* XXX other state: - * - SCTLR - * - TTBR0/1 - * - TTBCR - */ + v->arch.sctlr = ctxt->sctlr; + v->arch.ttbr0 = ctxt->ttbr0; + v->arch.ttbr1 = ctxt->ttbr1; + v->arch.ttbcr = ctxt->ttbcr; clear_bit(_VPF_down, &v->pause_flags); diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 1a2b95f..339c327 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -61,6 +61,30 @@ static struct { irq_desc_t irq_desc[NR_IRQS]; unsigned nr_lrs; +void gic_save_state(struct vcpu *v) +{ + int i; + + for ( i=0; i<nr_lrs; i++) + v->arch.gic_lr[i] = GICH[GICH_LR + i]; + /* Disable until next VCPU scheduled */ + GICH[GICH_HCR] = 0; + isb(); +} + +void gic_restore_state(struct vcpu *v) +{ + int i; + + if ( is_idle_vcpu(v) ) + return; + + for ( i=0; i<nr_lrs; i++) + GICH[GICH_LR + i] = v->arch.gic_lr[i]; + GICH[GICH_HCR] = GICH_HCR_EN; + isb(); +} + static unsigned int gic_irq_startup(struct irq_desc *desc) { uint32_t enabler; @@ -263,7 +287,6 @@ static void __cpuinit gic_hyp_init(void) vtr = GICH[GICH_VTR]; nr_lrs = (vtr & GICH_VTR_NRLRGS) + 1; - GICH[GICH_HCR] = GICH_HCR_EN; GICH[GICH_MISR] = GICH_MISR_EOI; } diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h index ff8d0a2..ac9cf3a 100644 --- a/xen/arch/arm/gic.h +++ b/xen/arch/arm/gic.h @@ -70,8 +70,8 @@ #define GICH_MISR (0x10/4) #define GICH_EISR0 (0x20/4) #define GICH_EISR1 (0x24/4) -#define GICH_ELRSR0 (0x30/4) -#define GICH_ELRSR1 (0x34/4) +#define GICH_ELSR0 (0x30/4) +#define GICH_ELSR1 (0x34/4) #define GICH_APR (0xF0/4) #define GICH_LR (0x100/4) @@ -149,6 +149,11 @@ extern void gic_init_secondary_cpu(void); extern void gic_disable_cpu(void); /* setup the gic virtual interface for a guest */ extern void gicv_setup(struct domain *d); + +/* Context switch */ +extern void gic_save_state(struct vcpu *v); +extern void gic_restore_state(struct vcpu *v); + #endif /* diff --git a/xen/include/asm-arm/cpregs.h b/xen/include/asm-arm/cpregs.h index 7a0b49a..bd46942 100644 --- a/xen/include/asm-arm/cpregs.h +++ b/xen/include/asm-arm/cpregs.h @@ -88,6 +88,19 @@ * arguments, which are cp,opc1,crn,crm,opc2. */ +/* Coprocessor 14 */ + +/* CP14 CR0: */ +#define TEECR p14,6,c0,c0,0 /* ThumbEE Configuration Register */ + +/* CP14 CR1: */ +#define TEEHBR p14,6,c1,c0,0 /* ThumbEE Handler Base Register */ +#define JOSCR p14,7,c1,c0,0 /* Jazelle OS Control Register */ + +/* CP14 CR2: */ +#define JMCR p14,7,c2,c0,0 /* Jazelle Main Configuration Register */ + + /* Coprocessor 15 */ /* CP15 CR0: CPUID and Cache Type Registers */ @@ -112,6 +125,8 @@ /* CP15 CR1: System Control Registers */ #define SCTLR p15,0,c1,c0,0 /* System Control Register */ +#define ACTLR p15,0,c1,c0,1 /* Auxiliary Control Register */ +#define CPACR p15,0,c1,c0,2 /* Coprocessor Access Control Register */ #define SCR p15,0,c1,c1,0 /* Secure Configuration Register */ #define NSACR p15,0,c1,c1,2 /* Non-Secure Access Control Register */ #define HSCTLR p15,4,c1,c0,0 /* Hyp. System Control Register */ @@ -127,12 +142,15 @@ #define VTTBR p15,6,c2 /* Virtualization Translation Table Base Register */ /* CP15 CR3: Domain Access Control Register */ +#define DACR p15,0,c3,c0,0 /* Domain Access Control Register */ /* CP15 CR4: */ /* CP15 CR5: Fault Status Registers */ #define DFSR p15,0,c5,c0,0 /* Data Fault Status Register */ #define IFSR p15,0,c5,c0,1 /* Instruction Fault Status Register */ +#define ADFSR p15,0,c5,c1,0 /* Auxiliary Data Fault Status Register */ +#define AIFSR p15,0,c5,c1,1 /* Auxiliary Instruction Fault Status Register */ #define HSR p15,4,c5,c2,0 /* Hyp. Syndrome Register */ /* CP15 CR6: Fault Address Registers */ @@ -144,6 +162,7 @@ /* CP15 CR7: Cache and address translation operations */ #define PAR p15,0,c7 /* Physical Address Register */ + #define ICIALLUIS p15,0,c7,c1,0 /* Invalidate all instruction caches to PoU inner shareable */ #define BPIALLIS p15,0,c7,c1,6 /* Invalidate entire branch predictor array inner shareable */ #define ICIALLU p15,0,c7,c5,0 /* Invalidate all instruction caches to PoU */ @@ -192,20 +211,24 @@ /* CP15 CR9: */ /* CP15 CR10: */ -#define MAIR0 p15,0,c10,c2,0 /* Memory Attribute Indirection Register 0 */ -#define MAIR1 p15,0,c10,c2,1 /* Memory Attribute Indirection Register 1 */ +#define MAIR0 p15,0,c10,c2,0 /* Memory Attribute Indirection Register 0 AKA PRRR */ +#define MAIR1 p15,0,c10,c2,1 /* Memory Attribute Indirection Register 1 AKA NMRR */ #define HMAIR0 p15,4,c10,c2,0 /* Hyp. Memory Attribute Indirection Register 0 */ #define HMAIR1 p15,4,c10,c2,1 /* Hyp. Memory Attribute Indirection Register 1 */ /* CP15 CR11: DMA Operations for TCM Access */ /* CP15 CR12: */ +#define VBAR p15,0,c12,c0,0 /* Vector Base Address Register */ #define HVBAR p15,4,c12,c0,0 /* Hyp. Vector Base Address Register */ /* CP15 CR13: */ #define FCSEIDR p15,0,c13,c0,0 /* FCSE Process ID Register */ #define CONTEXTIDR p15,0,c13,c0,1 /* Context ID Register */ -#define HTPIDR p15,4,c13,c0,2 /* Hyp. Software Thread ID Register */ +#define TPIDRURW p15,0,c13,c0,2 /* Software Thread ID, User, R/W */ +#define TPIDRURO p15,0,c13,c0,3 /* Software Thread ID, User, R/O */ +#define TPIDRPRW p15,0,c13,c0,4 /* Software Thread ID, Priveleged */ +#define HTPIDR p15,4,c13,c0,2 /* HYp Software Thread Id Register */ /* CP15 CR14: */ #define CNTPCT p15,0,c14 /* Time counter value */ diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index f295a82..620b26e 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -81,8 +81,37 @@ struct arch_vcpu */ struct cpu_info *cpu_info; - uint32_t sctlr; - uint32_t ttbr0, ttbr1, ttbcr; + /* Fault Status */ + uint32_t dfar, ifar; + uint32_t dfsr, ifsr; + uint32_t adfsr, aifsr; + + /* MMU */ + uint32_t vbar; + uint32_t ttbcr; + uint32_t ttbr0, ttbr1; + + uint32_t dacr; + uint64_t par; + uint32_t mair0, mair1; + + /* Control Registers */ + uint32_t actlr, sctlr; + uint32_t cpacr; + + uint32_t contextidr; + uint32_t tpidrurw; + uint32_t tpidruro; + uint32_t tpidrprw; + + uint32_t teecr, teehbr; + uint32_t joscr, jmcr; + + /* CP 15 */ + uint32_t csselr; + + uint32_t gic_hcr, gic_vmcr, gic_apr; + uint32_t gic_lr[64]; struct { struct vgic_irq_rank private_irqs; diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index e439727..e915cbf 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -124,6 +124,9 @@ typedef uint32_t xen_ulong_t; struct vcpu_guest_context { struct cpu_user_regs user_regs; /* User-level CPU registers */ + + uint32_t sctlr; + uint32_t ttbr0, ttbr1, ttbcr; }; typedef struct vcpu_guest_context vcpu_guest_context_t; DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 19/40] arm: dump a page table walk when va_to_par fails.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/include/asm-arm/page.h | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 2783c30..6efe23c 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -296,7 +296,11 @@ static inline uint64_t va_to_par(uint32_t va) { uint64_t par = __va_to_par(va); /* It is not OK to call this with an invalid VA */ - if ( par & PAR_F ) panic_PAR(par, "Hypervisor"); + if ( par & PAR_F ) + { + dump_hyp_walk(va); + panic_PAR(par, "Hypervisor"); + } return par; } -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 20/40] arm: dump guest s1 walk on data abort which is not a stage 2 issue.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/traps.c | 75 +++++++++++++++++++++++++++++++++++--- xen/include/asm-arm/processor.h | 1 + 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 40bb375..d8eb5a9 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -28,6 +28,7 @@ #include <xen/errno.h> #include <xen/hypercall.h> #include <xen/softirq.h> +#include <xen/domain_page.h> #include <public/xen.h> #include <asm/regs.h> #include <asm/cpregs.h> @@ -528,6 +529,62 @@ static void do_cp15_64(struct cpu_user_regs *regs, } +void dump_guest_s1_walk(struct domain *d, uint32_t addr) +{ + uint32_t ttbcr = READ_CP32(TTBCR); + uint32_t ttbr0 = READ_CP32(TTBR0); + paddr_t paddr; + uint32_t offset; + uint32_t *first = NULL, *second = NULL; + + printk("dom%d VA 0x%08"PRIx32"\n", d->domain_id, addr); + printk(" TTBCR: 0x%08"PRIx32"\n", ttbcr); + printk(" TTBR0: 0x%08"PRIx32" = 0x%"PRIpaddr"\n", + ttbr0, p2m_lookup(d, ttbr0 & PAGE_MASK)); + + if ( ttbcr & TTBCR_EAE ) + { + printk("Cannot handle LPAE guest PT walk\n"); + return; + } + if ( (ttbcr & TTBCR_N_MASK) != 0 ) + { + printk("Cannot handle TTBR1 guest walks\n"); + return; + } + + paddr = p2m_lookup(d, ttbr0 & PAGE_MASK); + if ( paddr == INVALID_PADDR ) + { + printk("Failed TTBR0 maddr lookup\n"); + goto done; + } + first = map_domain_page(paddr>>PAGE_SHIFT); + + offset = addr >> (12+10); + printk("1ST[0x%"PRIx32"] (0x%"PRIpaddr") = 0x%08"PRIx32"\n", + offset, paddr, first[offset]); + if ( !(first[offset] & 0x1) || + !(first[offset] & 0x2) ) + goto done; + + paddr = p2m_lookup(d, first[offset] & PAGE_MASK); + + if ( paddr == INVALID_PADDR ) + { + printk("Failed L1 entry maddr lookup\n"); + goto done; + } + second = map_domain_page(paddr>>PAGE_SHIFT); + offset = (addr >> 12) & 0x3FF; + printk("2ND[0x%"PRIx32"] (0x%"PRIpaddr") = 0x%08"PRIx32"\n", + offset, paddr, second[offset]); + +done: + if (second) unmap_domain_page(second); + if (first) unmap_domain_page(first); +} + static void do_trap_data_abort_guest(struct cpu_user_regs *regs, struct hsr_dabt dabt) { @@ -535,11 +592,12 @@ static void do_trap_data_abort_guest(struct cpu_user_regs *regs, int level = -1; mmio_info_t info; + info.dabt = dabt; + info.gva = READ_CP32(HDFAR); + if (dabt.s1ptw) goto bad_data_abort; - info.dabt = dabt; - info.gva = READ_CP32(HDFAR); info.gpa = gva_to_ipa(info.gva); if (handle_mmio(&info)) @@ -553,18 +611,23 @@ bad_data_abort: msg = decode_fsc( dabt.dfsc, &level); printk("Guest data abort: %s%s%s\n" - " gva=%"PRIx32" gpa=%"PRIpaddr"\n", + " gva=%"PRIx32"\n", msg, dabt.s1ptw ? " S2 during S1" : "", fsc_level_str(level), - info.gva, info.gpa); - if (dabt.valid) + info.gva); + if ( !dabt.s1ptw ) + printk(" gpa=%"PRIpaddr"\n", info.gpa); + if ( dabt.valid ) printk(" size=%d sign=%d write=%d reg=%d\n", dabt.size, dabt.sign, dabt.write, dabt.reg); else printk(" instruction syndrome invalid\n"); printk(" eat=%d cm=%d s1ptw=%d dfsc=%d\n", dabt.eat, dabt.cache, dabt.s1ptw, dabt.dfsc); - + if ( !dabt.s1ptw ) + dump_p2m_lookup(current->domain, info.gpa); + else + dump_guest_s1_walk(current->domain, info.gva); show_execution_state(regs); panic("Unhandled guest data abort\n"); } diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index ec6fb48..81924a4 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -25,6 +25,7 @@ #define PSR_JAZELLE (1<<24) /* Jazelle Mode */ /* TTBCR Translation Table Base Control Register */ +#define TTBCR_EAE 0x80000000 #define TTBCR_N_MASK 0x07 #define TTBCR_N_16KB 0x00 #define TTBCR_N_8KB 0x01 -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 21/40] arm: implement vcpu_show_execution_state
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/dummy.S | 1 - xen/arch/arm/traps.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S index 03f7489..cab9522 100644 --- a/xen/arch/arm/dummy.S +++ b/xen/arch/arm/dummy.S @@ -21,7 +21,6 @@ DUMMY(pirq_set_affinity); DUMMY(arch_get_info_guest); DUMMY(arch_vcpu_reset); NOP(update_vcpu_system_time); -DUMMY(vcpu_show_execution_state); /* Page Reference & Type Maintenance */ DUMMY(get_page); diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index d8eb5a9..f5f43da 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -170,7 +170,13 @@ void panic_PAR(uint64_t par, const char *when) panic("Error during %s-to-physical address translation\n", when); } -void show_registers(struct cpu_user_regs *regs) +struct reg_ctxt { + uint32_t sctlr; + uint32_t ttbr0, ttbr1, ttbcr; +}; +static void _show_registers(struct cpu_user_regs *regs, + struct reg_ctxt *ctxt, + int guest_mode) { static const char *mode_strings[] = { [PSR_MODE_USR] = "USR", @@ -187,7 +193,7 @@ void show_registers(struct cpu_user_regs *regs) print_xen_info(); printk("CPU: %d\n", smp_processor_id()); printk("PC: %08"PRIx32, regs->pc); - if ( !guest_mode(regs) ) + if ( !guest_mode ) print_symbol(" %s", regs->pc); printk("\n"); printk("CPSR: %08"PRIx32" MODE:%s\n", regs->cpsr, @@ -199,7 +205,7 @@ void show_registers(struct cpu_user_regs *regs) printk(" R8: %08"PRIx32" R9: %08"PRIx32" R10:%08"PRIx32" R11:%08"PRIx32" R12:%08"PRIx32"\n", regs->r8, regs->r9, regs->r10, regs->r11, regs->r12); - if ( guest_mode(regs) ) + if ( guest_mode ) { printk("USR: SP: %08"PRIx32" LR: %08"PRIx32" CPSR:%08"PRIx32"\n", regs->sp_usr, regs->lr_usr, regs->cpsr); @@ -217,8 +223,8 @@ void show_registers(struct cpu_user_regs *regs) regs->r8_fiq, regs->r9_fiq, regs->r10_fiq, regs->r11_fiq, regs->r11_fiq); printk("\n"); printk("TTBR0 %08"PRIx32" TTBR1 %08"PRIx32" TTBCR %08"PRIx32"\n", - READ_CP32(TTBR0), READ_CP32(TTBR1), READ_CP32(TTBCR)); - printk("SCTLR %08"PRIx32"\n", READ_CP32(SCTLR)); + ctxt->ttbr0, ctxt->ttbr1, ctxt->ttbcr); + printk("SCTLR %08"PRIx32"\n", ctxt->sctlr); printk("VTTBR %010"PRIx64"\n", READ_CP64(VTTBR)); printk("\n"); } @@ -241,6 +247,26 @@ void show_registers(struct cpu_user_regs *regs) printk("\n"); } +void show_registers(struct cpu_user_regs *regs) +{ + struct reg_ctxt ctxt; + ctxt.sctlr = READ_CP32(SCTLR); + ctxt.ttbcr = READ_CP32(TTBCR); + ctxt.ttbr0 = READ_CP32(TTBR0); + ctxt.ttbr1 = READ_CP32(TTBR1); + _show_registers(regs, &ctxt, guest_mode(regs)); +} + +void vcpu_show_registers(const struct vcpu *v) +{ + struct reg_ctxt ctxt; + ctxt.sctlr = v->arch.sctlr; + ctxt.ttbcr = v->arch.ttbcr; + ctxt.ttbr0 = v->arch.ttbr0; + ctxt.ttbr1 = v->arch.ttbr1; + _show_registers(&v->arch.cpu_info->guest_cpu_user_regs, &ctxt, 1); +} + static void show_guest_stack(struct cpu_user_regs *regs) { printk("GUEST STACK GOES HERE\n"); @@ -334,6 +360,26 @@ void show_execution_state(struct cpu_user_regs *regs) show_stack(regs); } +void vcpu_show_execution_state(struct vcpu *v) +{ + printk("*** Dumping Dom%d vcpu#%d state: ***\n", + v->domain->domain_id, v->vcpu_id); + + if ( v == current ) + { + show_execution_state(guest_cpu_user_regs()); + return; + } + + vcpu_pause(v); /* acceptably dangerous */ + + vcpu_show_registers(v); + if ( !usr_mode(&v->arch.cpu_info->guest_cpu_user_regs) ) + show_guest_stack(&v->arch.cpu_info->guest_cpu_user_regs); + + vcpu_unpause(v); +} + static void do_unexpected_trap(const char *msg, struct cpu_user_regs *regs) { printk("Unexpected Trap: %s\n", msg); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 22/40] arm: use correct attributes for mappings in copy_from_paddr()
The DTB is in RAM (hence bufferable), kernel is in flash and therefor requires a device type mapping (hence dev shared). Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: David Vrabel <david.vrabel@citrix.com> --- xen/arch/arm/kernel.c | 8 ++++---- xen/arch/arm/setup.c | 2 +- xen/include/asm-arm/page.h | 15 +++++++++++++++ xen/include/asm-arm/setup.h | 2 +- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index 130d488..2d56130 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -39,7 +39,7 @@ struct minimal_dtb_header { * @paddr: source physical address * @len: length to copy */ -void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len) +void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx) { void *src = (void *)FIXMAP_ADDR(FIXMAP_MISC); @@ -51,7 +51,7 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len) s = paddr & (PAGE_SIZE-1); l = min(PAGE_SIZE - s, len); - set_fixmap(FIXMAP_MISC, p, DEV_SHARED); + set_fixmap(FIXMAP_MISC, p, attrindx); memcpy(dst, src + s, l); paddr += l; @@ -111,7 +111,7 @@ static int kernel_try_zimage_prepare(struct kernel_info *info) /* * Check for an appended DTB. */ - copy_from_paddr(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, sizeof(dtb_hdr)); + copy_from_paddr(&dtb_hdr, KERNEL_FLASH_ADDRESS + end - start, sizeof(dtb_hdr), DEV_SHARED); if (be32_to_cpu(dtb_hdr.magic) == DTB_MAGIC) { end += be32_to_cpu(dtb_hdr.total_size); } @@ -151,7 +151,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info) if ( info->kernel_img == NULL ) panic("Cannot allocate temporary buffer for kernel.\n"); - copy_from_paddr(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE); + copy_from_paddr(info->kernel_img, KERNEL_FLASH_ADDRESS, KERNEL_FLASH_SIZE, DEV_SHARED); if ( (rc = elf_init(&info->elf.elf, info->kernel_img, KERNEL_FLASH_SIZE )) != 0 ) return rc; diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index d6c0178..fd70553 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -122,7 +122,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) * TODO: handle other payloads too. */ device_tree_flattened = mfn_to_virt(alloc_boot_pages(dtb_pages, 1)); - copy_from_paddr(device_tree_flattened, dtb_paddr, dtb_size); + copy_from_paddr(device_tree_flattened, dtb_paddr, dtb_size, BUFFERABLE); /* Add non-xenheap memory */ init_boot_pages(pfn_to_paddr(xenheap_mfn_start + xenheap_pages), diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 6efe23c..2b6c1780 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -36,6 +36,14 @@ #define MAIR0VAL 0xeeaa4400 #define MAIR1VAL 0xff000004 +/* + * Attribute Indexes. + * + * These are valid in the AttrIndx[2:0] field of an LPAE stage 1 page + * table entry. They are indexes into the bytes of the MAIR* + * registers, as defined above. + * + */ #define UNCACHED 0x0 #define BUFFERABLE 0x1 #define WRITETHROUGH 0x2 @@ -46,6 +54,13 @@ #define DEV_WC BUFFERABLE #define DEV_CACHED WRITEBACK +/* + * Stage 2 Memory Type. + * + * These are valid in the MemAttr[3:0] field of an LPAE stage 2 page + * table entry. + * + */ #define MATTR_DEV 0x1 #define MATTR_MEM 0xf diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h index 05ff89e..6433b4e 100644 --- a/xen/include/asm-arm/setup.h +++ b/xen/include/asm-arm/setup.h @@ -3,7 +3,7 @@ #include <public/version.h> -void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len); +void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx); void arch_get_xen_caps(xen_capabilities_info_t *info); -- 1.7.9.1
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/mm.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 715a98a..40ac176 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -106,6 +106,7 @@ void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes) lpae_t pte = mfn_to_xen_entry(mfn); pte.pt.table = 1; /* 4k mappings always have this bit set */ pte.pt.ai = attributes; + pte.pt.xn = 1; write_pte(xen_fixmap + third_table_offset(FIXMAP_ADDR(map)), pte); flush_xen_data_tlb_va(FIXMAP_ADDR(map)); } -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 24/40] arm: fix locking in create_p2m_entries
For some reason we were holding the lock over only the unmaps at the end of the function, rather than for the whole walk. We might want to be more clever in the future, but for now lets just lock for the whole walk+create process. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/p2m.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 35bfa2f..5f20246 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -132,6 +132,8 @@ static int create_p2m_entries(struct domain *d, paddr_t addr; unsigned long cur_first_offset = ~0, cur_second_offset = ~0; + spin_lock(&p2m->lock); + /* XXX Don''t actually handle 40 bit guest physical addresses */ BUG_ON(start_gpaddr & 0x8000000000ULL); BUG_ON(end_gpaddr & 0x8000000000ULL); @@ -213,8 +215,6 @@ static int create_p2m_entries(struct domain *d, rc = 0; out: - spin_lock(&p2m->lock); - if (third) unmap_domain_page(third); if (second) unmap_domain_page(second); if (first) unmap_domain_page(first); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 25/40] arm: split pending SPIs (global) out from pending PPIs and SGIs (per CPU)
This tracks SPIs in struct arch_domain and PPIs+SGIs in struct arch_vcpu which seems more logical. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/vgic.c | 12 +++++++----- xen/include/asm-arm/domain.h | 10 ++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 629a0da..af3523f 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -82,9 +82,8 @@ int domain_vgic_init(struct domain *d) d->arch.vgic.shared_irqs xmalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d)); d->arch.vgic.pending_irqs - 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++) + xzalloc_array(struct pending_irq, d->arch.vgic.nr_lines); + for (i=0; i<d->arch.vgic.nr_lines; i++) 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); @@ -98,6 +97,10 @@ int vcpu_vgic_init(struct vcpu *v) spin_lock_init(&v->arch.vgic.private_irqs.lock); + memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs)); + for (i = 0; i < 32; i++) + INIT_LIST_HEAD(&v->arch.vgic.pending_irqs[i].inflight); + /* For SGI and PPI the target is always this CPU */ for ( i = 0 ; i < 8 ; i++ ) v->arch.vgic.private_irqs.itargets[i] @@ -535,8 +538,7 @@ struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq) /* Pending irqs allocation strategy: the first vgic.nr_lines irqs * are used for SPIs; the rests are used for per cpu irqs */ if ( irq < 32 ) - n = &v->domain->arch.vgic.pending_irqs[irq + (v->vcpu_id * 32) - + v->domain->arch.vgic.nr_lines]; + n = &v->arch.vgic.pending_irqs[irq]; else n = &v->domain->arch.vgic.pending_irqs[irq - 32]; return n; diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 620b26e..32deb52 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -46,6 +46,10 @@ struct arch_domain int ctlr; int nr_lines; 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; } vgic; @@ -114,7 +118,13 @@ struct arch_vcpu uint32_t gic_lr[64]; struct { + /* + * SGIs and PPIs are per-VCPU, SPIs are domain global and in + * struct arch_domain. + */ + struct pending_irq pending_irqs[32]; 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 -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 26/40] arm: use interrupt safe spin locks in vgic_vcpu_inject_irq
This function can be called in both interrupt and regular context. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/vgic.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index af3523f..91d6166 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -550,6 +550,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual) uint8_t priority; struct vgic_irq_rank *rank = vgic_irq_rank(v, 8, idx); struct pending_irq *iter, *n = irq_to_pending(v, irq); + unsigned long flags; /* irq still pending */ if (!list_empty(&n->inflight)) @@ -566,7 +567,7 @@ 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); + spin_lock_irqsave(&v->arch.vgic.lock, flags); list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight ) { if ( iter->priority > priority ) @@ -577,7 +578,7 @@ 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); + spin_unlock_irqrestore(&v->arch.vgic.lock, flags); /* we have a new higher priority irq, inject it into the guest */ } -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 27/40] arm: map GICV in all domains, not just dom0.
This requires that we allocate all p2m pages from domheap without a particular dom because max pages is not setup yet so there is no allocation available to us. At some point we should create a separate p2m allocation (similar to x86''s shadow allocation) and use that. Also we seem to have been calling p2m_alloc_table twice for dom0. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/domain.c | 10 +++++++--- xen/arch/arm/domain_build.c | 5 ----- xen/arch/arm/gic.c | 7 ++----- xen/arch/arm/gic.h | 2 +- xen/arch/arm/p2m.c | 3 ++- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index d11be78..a7b7d4a 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -323,10 +323,13 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) if ( (rc = p2m_alloc_table(d)) != 0 ) goto fail; - } - if ( (rc = domain_vgic_init(d)) != 0 ) - goto fail; + if ( (rc = gicv_setup(d)) != 0 ) + goto fail; + + if ( (rc = domain_vgic_init(d)) != 0 ) + goto fail; + } /* Domain 0 gets a real UART not an emulated one */ if ( d->domain_id && (rc = domain_uart0_init(d)) != 0 ) @@ -334,6 +337,7 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) rc = 0; fail: + /*XXX unwind allocations etc */ return rc; } diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 72e775c..1b19e54 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -270,9 +270,6 @@ int construct_dom0(struct domain *d) d->max_pages = ~0U; - if ( (rc = p2m_alloc_table(d)) != 0 ) - return rc; - rc = prepare_dtb(d, &kinfo); if ( rc < 0 ) return rc; @@ -288,8 +285,6 @@ int construct_dom0(struct domain *d) printk("Map VGIC MMIO regions 1:1 in the P2M %#llx->%#llx\n", 0x2C008000ULL, 0x2DFFFFFFULL); map_mmio_regions(d, 0x2C008000, 0x2DFFFFFF, 0x2C008000); - gicv_setup(d); - printk("Routing peripheral interrupts to guest\n"); /* TODO Get from device tree */ gic_route_irq_to_guest(d, 34, "timer0"); diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 339c327..47995b4 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -541,14 +541,11 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq) do_IRQ(regs, irq, is_fiq); } -void gicv_setup(struct domain *d) +int gicv_setup(struct domain *d) { /* map the gic virtual cpu interface in the gic cpu interface region of * the guest */ - printk("mapping GICC at %#"PRIx32" to %#"PRIx32"\n", - GIC_BASE_ADDRESS + GIC_CR_OFFSET, - GIC_BASE_ADDRESS + GIC_VR_OFFSET); - map_mmio_regions(d, GIC_BASE_ADDRESS + GIC_CR_OFFSET, + return map_mmio_regions(d, GIC_BASE_ADDRESS + GIC_CR_OFFSET, GIC_BASE_ADDRESS + GIC_CR_OFFSET + (2 * PAGE_SIZE) - 1, GIC_BASE_ADDRESS + GIC_VR_OFFSET); } diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h index ac9cf3a..018d820 100644 --- a/xen/arch/arm/gic.h +++ b/xen/arch/arm/gic.h @@ -148,7 +148,7 @@ extern void gic_init_secondary_cpu(void); /* Take down a CPU''s per-CPU GIC interface */ extern void gic_disable_cpu(void); /* setup the gic virtual interface for a guest */ -extern void gicv_setup(struct domain *d); +extern int gicv_setup(struct domain *d); /* Context switch */ extern void gic_save_state(struct vcpu *v); diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 5f20246..67bfeba 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -4,6 +4,7 @@ #include <xen/errno.h> #include <xen/domain_page.h> #include <asm/flushtlb.h> +#include "gic.h" void dump_p2m_lookup(struct domain *d, paddr_t addr) { @@ -102,7 +103,7 @@ static int p2m_create_table(struct domain *d, BUG_ON(entry->p2m.valid); - page = alloc_domheap_page(d, 0); + page = alloc_domheap_page(NULL, 0); if ( page == NULL ) return -ENOMEM; -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 28/40] arm: enable data-cache at the same time as enabling the MMU, not before
With enough warnings enabled the model seemed to be complaining that pages cached before paging was enabled had been mapped with to inconsistent sets of attributes. I''m not convinced that isn''t a model issue, nor am I convinced this has really fixed anything, but it seems sensible enough. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/head.S | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/head.S b/xen/arch/arm/head.S index 9a7714a..cdbe011 100644 --- a/xen/arch/arm/head.S +++ b/xen/arch/arm/head.S @@ -148,10 +148,11 @@ hyp: * Exceptions in LE ARM, * Low-latency IRQs disabled, * Write-implies-XN disabled (for now), - * I-cache and d-cache enabled, + * D-cache disabled (for now), + * I-cache enabled, * Alignment checking enabled, * MMU translation disabled (for now). */ - ldr r0, =(HSCTLR_BASE|SCTLR_A|SCTLR_C) + ldr r0, =(HSCTLR_BASE|SCTLR_A) mcr CP32(r0, HSCTLR) /* Write Xen''s PT''s paddr into the HTTBR */ @@ -210,7 +211,7 @@ pt_ready: ldr r1, =paging /* Explicit vaddr, not RIP-relative */ mrc CP32(r0, HSCTLR) - orr r0, r0, #0x1 /* Add in the MMU enable bit */ + orr r0, r0, #(SCTLR_M|SCTLR_C) /* Enable MMU and D-cache */ dsb /* Flush PTE writes and finish reads */ mcr CP32(r0, HSCTLR) /* now paging is enabled */ isb /* Now, flush the icache */ -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 29/40] arm: Upgrade guest barriers to Outer-Shareable. Enable Protected Table Walk.
Upgrading barriers is conservative and may not be necessary. Protected Table Walk traps stage 1 page tables which refer to device memory (per stage 2) using a non-device mapping. This generally indicates a guest error but trapping it as a fault for now helps us know if something odd is going on. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/domain_build.c | 2 +- xen/include/asm-arm/processor.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 1b19e54..a9e7f43 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -333,7 +333,7 @@ int construct_dom0(struct domain *d) WRITE_CP32(SCTLR_BASE, SCTLR); - WRITE_CP32(HCR_AMO|HCR_IMO|HCR_VM, HCR); + WRITE_CP32(HCR_PTW|HCR_BSU_OUTER|HCR_AMO|HCR_IMO|HCR_VM, HCR); isb(); local_abort_enable(); diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index 81924a4..9b3c9dd 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -76,6 +76,10 @@ #define HCR_TWI (1<<13) #define HCR_DC (1<<12) #define HCR_BSU_MASK (3<<10) +#define HCR_BSU_NONE (0<<10) +#define HCR_BSU_INNER (1<<10) +#define HCR_BSU_OUTER (2<<10) +#define HCR_BSU_FULL (3<<10) #define HCR_FB (1<<9) #define HCR_VA (1<<8) #define HCR_VI (1<<7) -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 30/40] arm: gic.lock can be taken in interrupt context, so lock appropriately.
In particular it is taken by gic_set_guest_irq which is called by vgic_vcpu_inject_irq Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/gic.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 47995b4..1baccba 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -329,19 +329,19 @@ int __init gic_init(void) /* Set up the per-CPU parts of the GIC for a secondary CPU */ void __cpuinit gic_init_secondary_cpu(void) { - spin_lock(&gic.lock); + spin_lock_irq(&gic.lock); gic_cpu_init(); gic_hyp_init(); - spin_unlock(&gic.lock); + spin_unlock_irq(&gic.lock); } /* Shut down the per-CPU GIC interface */ void gic_disable_cpu(void) { - spin_lock(&gic.lock); + spin_lock_irq(&gic.lock); gic_cpu_disable(); gic_hyp_disable(); - spin_unlock(&gic.lock); + spin_unlock_irq(&gic.lock); } void gic_route_irqs(void) @@ -439,7 +439,7 @@ void gic_set_guest_irq(unsigned int virtual_irq, events_maintenance(current); - spin_lock(&gic.lock); + spin_lock_irq(&gic.lock); if ( list_empty(&gic.lr_pending) ) { @@ -465,7 +465,7 @@ void gic_set_guest_irq(unsigned int virtual_irq, list_add_tail(&n->lr_queue, &gic.lr_pending); out: - spin_unlock(&gic.lock); + spin_unlock_irq(&gic.lock); return; } @@ -557,7 +557,7 @@ static void events_maintenance(struct vcpu *v) (unsigned long *)&vcpu_info(v, evtchn_upcall_pending)); if (!already_pending && gic.event_mask != 0) { - spin_lock(&gic.lock); + spin_lock_irq(&gic.lock); while ((i = find_next_bit((const long unsigned int *) &gic.event_mask, sizeof(uint64_t), i)) < sizeof(uint64_t)) { @@ -567,7 +567,7 @@ static void events_maintenance(struct vcpu *v) i++; } - spin_unlock(&gic.lock); + spin_unlock_irq(&gic.lock); } } @@ -583,7 +583,7 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r sizeof(eisr), i)) < sizeof(eisr)) { struct pending_irq *p; - spin_lock(&gic.lock); + spin_lock_irq(&gic.lock); lr = GICH[GICH_LR + i]; virq = lr & GICH_LR_VIRTUAL_MASK; GICH[GICH_LR + i] = 0; @@ -599,7 +599,7 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r } else { gic_inject_irq_stop(); } - spin_unlock(&gic.lock); + spin_unlock_irq(&gic.lock); spin_lock(¤t->arch.vgic.lock); p = irq_to_pending(current, virq); -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 31/40] arm: context switch virtual timer registers
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/domain.c | 10 ++++++++++ xen/include/asm-arm/cpregs.h | 3 +++ xen/include/asm-arm/domain.h | 5 +++++ 3 files changed, 18 insertions(+), 0 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index a7b7d4a..2b5515d 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -49,6 +49,11 @@ static void ctxt_switch_from(struct vcpu *p) p->arch.tpidruro = READ_CP32(TPIDRURO); p->arch.tpidrprw = READ_CP32(TPIDRPRW); + /* Arch timer */ + p->arch.cntvoff = READ_CP64(CNTVOFF); + p->arch.cntv_cval = READ_CP64(CNTV_CVAL); + p->arch.cntv_ctl = READ_CP32(CNTV_CTL); + /* XXX only save these if ThumbEE e.g. ID_PFR0.THUMB_EE_SUPPORT */ p->arch.teecr = READ_CP32(TEECR); p->arch.teehbr = READ_CP32(TEEHBR); @@ -128,6 +133,11 @@ static void ctxt_switch_to(struct vcpu *n) WRITE_CP32(n->arch.mair1, MAIR1); isb(); + /* Arch timer */ + WRITE_CP64(n->arch.cntvoff, CNTVOFF); + WRITE_CP64(n->arch.cntv_cval, CNTV_CVAL); + WRITE_CP32(n->arch.cntv_ctl, CNTV_CTL); + /* Control Registers */ WRITE_CP32(n->arch.actlr, ACTLR); WRITE_CP32(n->arch.sctlr, SCTLR); diff --git a/xen/include/asm-arm/cpregs.h b/xen/include/asm-arm/cpregs.h index bd46942..34a9e93 100644 --- a/xen/include/asm-arm/cpregs.h +++ b/xen/include/asm-arm/cpregs.h @@ -238,10 +238,13 @@ #define CNTP_CTL p15,0,c14,c2,1 /* Physical Timer control register */ #define CNTVCT p15,1,c14 /* Time counter value + offset */ #define CNTP_CVAL p15,2,c14 /* Physical Timer comparator */ +#define CNTV_CVAL p15,3,c14 /* Virt. Timer comparator */ #define CNTVOFF p15,4,c14 /* Time counter offset */ #define CNTHCTL p15,4,c14,c1,0 /* Time counter hyp. control */ #define CNTHP_TVAL p15,4,c14,c2,0 /* Hyp. Timer value */ #define CNTHP_CTL p15,4,c14,c2,1 /* Hyp. Timer control register */ +#define CNTV_TVAL p15,0,c14,c3,0 /* Virt. Timer value */ +#define CNTV_CTL p15,0,c14,c3,1 /* Virt. TImer control register */ #define CNTHP_CVAL p15,6,c14 /* Hyp. Timer comparator */ /* CP15 CR15: Implementation Defined Registers */ diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h index 32deb52..230ea8c 100644 --- a/xen/include/asm-arm/domain.h +++ b/xen/include/asm-arm/domain.h @@ -111,6 +111,11 @@ struct arch_vcpu uint32_t teecr, teehbr; uint32_t joscr, jmcr; + /* Arch timers */ + uint64_t cntvoff; + uint64_t cntv_cval; + uint32_t cntv_ctl; + /* CP 15 */ uint32_t csselr; -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 32/40] arm: the hyp timer seems to work in newer model versions, default to using it.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/time.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index 437dc71..1587fa2 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -27,8 +27,12 @@ #include <xen/time.h> #include <asm/system.h> -/* Unfortunately the hypervisor timer interrupt appears to be buggy */ -#define USE_HYP_TIMER 0 +/* + * Unfortunately the hypervisor timer interrupt appears to be buggy in + * some versions of the model. Disable this to use the physical timer + * instead. + */ +#define USE_HYP_TIMER 1 /* For fine-grained timekeeping, we use the ARM "Generic Timer", a * register-mapped time source in the SoC. */ -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 33/40] arm: unwind allocations etc on arch_domain_create_failure
This involves adding the necessary teardown/free functions for some modules. Don''t initialise full arch domain state for the idle domain, it''s not needed. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/domain.c | 42 +++++++++++++++++++++++++----------------- xen/arch/arm/gic.h | 3 +++ xen/arch/arm/p2m.c | 15 +++++++++++++++ xen/arch/arm/vgic.c | 6 ++++++ xen/arch/arm/vpl011.c | 5 +++++ xen/arch/arm/vpl011.h | 1 + xen/include/asm-arm/p2m.h | 3 +++ 7 files changed, 58 insertions(+), 17 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 2b5515d..ac6a30d 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -317,37 +317,45 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) { int rc; + /* Idle domains do not need this setup */ + if ( is_idle_domain(d) ) + return 0; + rc = -ENOMEM; if ( (rc = p2m_init(d)) != 0 ) goto fail; - if ( !is_idle_domain(d) ) - { - rc = -ENOMEM; - if ( (d->shared_info = alloc_xenheap_pages(0, 0)) == NULL ) - goto fail; + if ( (d->shared_info = alloc_xenheap_pages(0, 0)) == NULL ) + goto fail; - clear_page(d->shared_info); - share_xen_page_with_guest( - virt_to_page(d->shared_info), d, XENSHARE_writable); + clear_page(d->shared_info); + share_xen_page_with_guest( + virt_to_page(d->shared_info), d, XENSHARE_writable); - if ( (rc = p2m_alloc_table(d)) != 0 ) - goto fail; + if ( (rc = p2m_alloc_table(d)) != 0 ) + goto fail; - if ( (rc = gicv_setup(d)) != 0 ) - goto fail; + if ( (rc = gicv_setup(d)) != 0 ) + goto fail; - if ( (rc = domain_vgic_init(d)) != 0 ) - goto fail; - } + if ( (rc = domain_vgic_init(d)) != 0 ) + goto fail; /* Domain 0 gets a real UART not an emulated one */ if ( d->domain_id && (rc = domain_uart0_init(d)) != 0 ) goto fail; - rc = 0; + return 0; + fail: - /*XXX unwind allocations etc */ + d->is_dying = DOMDYING_dead; + free_xenheap_page(d->shared_info); + + p2m_teardown(d); + + domain_vgic_free(d); + domain_uart0_free(d); + return rc; } diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h index 018d820..e36d6ad 100644 --- a/xen/arch/arm/gic.h +++ b/xen/arch/arm/gic.h @@ -125,7 +125,10 @@ #define VGIC_IRQ_EVTCHN_CALLBACK 31 extern int domain_vgic_init(struct domain *d); +extern void domain_vgic_free(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); extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq); diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 67bfeba..073216b 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -288,6 +288,21 @@ int p2m_alloc_table(struct domain *d) return 0; } +void p2m_teardown(struct domain *d) +{ + struct p2m_domain *p2m = &d->arch.p2m; + struct page_info *pg; + + spin_lock(&p2m->lock); + + while ( (pg = page_list_remove_head(&p2m->pages)) ) + free_domheap_page(pg); + + p2m->first_level = NULL; + + spin_unlock(&p2m->lock); +} + int p2m_init(struct domain *d) { struct p2m_domain *p2m = &d->arch.p2m; diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 91d6166..06bbd0c 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -90,6 +90,12 @@ int domain_vgic_init(struct domain *d) return 0; } +void domain_vgic_free(struct domain *d) +{ + xfree(d->arch.vgic.shared_irqs); + xfree(d->arch.vgic.pending_irqs); +} + int vcpu_vgic_init(struct vcpu *v) { int i; diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c index 5dc8b28..1522667 100644 --- a/xen/arch/arm/vpl011.c +++ b/xen/arch/arm/vpl011.c @@ -56,6 +56,11 @@ int domain_uart0_init(struct domain *d) } +void domain_uart0_free(struct domain *d) +{ + xfree(d->arch.uart0.buf); +} + static void uart0_print_char(char c) { struct vpl011 *uart = ¤t->domain->arch.uart0; diff --git a/xen/arch/arm/vpl011.h b/xen/arch/arm/vpl011.h index 952d812..eabd99d 100644 --- a/xen/arch/arm/vpl011.h +++ b/xen/arch/arm/vpl011.h @@ -21,6 +21,7 @@ #define __ARCH_ARM_VPL011_H__ extern int domain_uart0_init(struct domain *d); +extern void domain_uart0_free(struct domain *d); #endif diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index 666bb88..14e71bf 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -23,6 +23,9 @@ struct p2m_domain { /* Init the datastructures for later use by the p2m code */ int p2m_init(struct domain *d); +/* Return all the p2m resources to Xen. */ +void p2m_teardown(struct domain *d); + /* Allocate a new p2m table for a domain. * * Returns 0 for success or -errno. -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 34/40] HACK: arm: initial XENMAPSPACE_gmfn_foreign
Should use same interface as hybrid x86. --- xen/arch/arm/mm.c | 32 ++++++++++++++++++++++++++------ xen/arch/x86/mm.c | 2 ++ xen/include/public/arch-arm.h | 1 + xen/include/public/memory.h | 12 +++++++----- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 40ac176..d369ee3 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -470,12 +470,32 @@ static int xenmem_add_to_physmap_once( switch ( xatp->space ) { - case XENMAPSPACE_shared_info: - if ( xatp->idx == 0 ) - mfn = virt_to_mfn(d->shared_info); - break; - default: - return -ENOSYS; + case XENMAPSPACE_shared_info: + if ( xatp->idx == 0 ) + mfn = virt_to_mfn(d->shared_info); + break; + case XENMAPSPACE_gmfn_foreign: + { + paddr_t maddr; + struct domain *od; + + rc = rcu_lock_target_domain_by_id(xatp->foreign_domid, &od); + if ( rc < 0 ) + return rc; + maddr = p2m_lookup(od, xatp->idx << PAGE_SHIFT); + if ( maddr == INVALID_PADDR ) + { + printk("bad p2m lookup\n"); + dump_p2m_lookup(od, xatp->idx << PAGE_SHIFT); + rcu_unlock_domain(od); + return -EINVAL; + } + mfn = maddr >> PAGE_SHIFT; + rcu_unlock_domain(od); + break; + } + default: + return -ENOSYS; } domain_lock(d); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index c543f03..8190fa0 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4573,6 +4573,8 @@ static int xenmem_add_to_physmap_once( mfn = idx; page = mfn_to_page(mfn); break; + case XENMAPSPACE_gmfn_foreign: + return -ENOSYS; } default: break; diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index e915cbf..b52bfc7 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -121,6 +121,7 @@ typedef uint64_t xen_pfn_t; #define XEN_LEGACY_MAX_VCPUS 1 typedef uint32_t xen_ulong_t; +#define PRI_xen_ulong PRIx32 struct vcpu_guest_context { struct cpu_user_regs user_regs; /* User-level CPU registers */ diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 86d02c8..b2adfbe 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -212,11 +212,13 @@ struct xen_add_to_physmap { uint16_t size; /* Source mapping space. */ -#define XENMAPSPACE_shared_info 0 /* shared info page */ -#define XENMAPSPACE_grant_table 1 /* grant table page */ -#define XENMAPSPACE_gmfn 2 /* GMFN */ -#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ - unsigned int space; +#define XENMAPSPACE_shared_info 0 /* shared info page */ +#define XENMAPSPACE_grant_table 1 /* grant table page */ +#define XENMAPSPACE_gmfn 2 /* GMFN */ +#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ +#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */ + uint16_t space; + domid_t foreign_domid; /* IFF gmfn_foreign */ #define XENMAPIDX_grant_table_status 0x80000000 -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:29 UTC
[PATCH V2 35/40] arm: move PSR flag definitions into interface, for tools use.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/arch/arm/entry.S | 1 + xen/include/asm-arm/page.h | 2 ++ xen/include/asm-arm/processor.h | 21 --------------------- xen/include/asm-arm/system.h | 2 +- xen/include/public/arch-arm.h | 23 ++++++++++++++++++++++- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/xen/arch/arm/entry.S b/xen/arch/arm/entry.S index 5bc3906..2ff32a1 100644 --- a/xen/arch/arm/entry.S +++ b/xen/arch/arm/entry.S @@ -1,5 +1,6 @@ #include <xen/config.h> #include <asm/asm_defns.h> +#include <public/xen.h> #define SAVE_ONE_BANKED(reg) mrs r11, reg; str r11, [sp, #UREGS_##reg] #define RESTORE_ONE_BANKED(reg) ldr r11, [sp, #UREGS_##reg]; msr reg, r11 diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 2b6c1780..f3e4d1a 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -2,6 +2,8 @@ #define __ARM_PAGE_H__ #include <xen/config.h> +#include <public/xen.h> +#include <asm/processor.h> #define PADDR_BITS 40 #define PADDR_MASK ((1ULL << PADDR_BITS)-1) diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index 9b3c9dd..3849b23 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -3,27 +3,6 @@ #include <asm/cpregs.h> -/* PSR bits (CPSR, SPSR)*/ - -/* 0-4: Mode */ -#define PSR_MODE_MASK 0x1f -#define PSR_MODE_USR 0x10 -#define PSR_MODE_FIQ 0x11 -#define PSR_MODE_IRQ 0x12 -#define PSR_MODE_SVC 0x13 -#define PSR_MODE_MON 0x16 -#define PSR_MODE_ABT 0x17 -#define PSR_MODE_HYP 0x1a -#define PSR_MODE_UND 0x1b -#define PSR_MODE_SYS 0x1f - -#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 */ -#define PSR_JAZELLE (1<<24) /* Jazelle Mode */ - /* TTBCR Translation Table Base Control Register */ #define TTBCR_EAE 0x80000000 #define TTBCR_N_MASK 0x07 diff --git a/xen/include/asm-arm/system.h b/xen/include/asm-arm/system.h index 7963ea5..216ef1f 100644 --- a/xen/include/asm-arm/system.h +++ b/xen/include/asm-arm/system.h @@ -3,7 +3,7 @@ #define __ASM_SYSTEM_H #include <xen/lib.h> -#include <asm/processor.h> +#include <public/arch-arm.h> #define nop() \ asm volatile ( "nop" ) diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index b52bfc7..7ebe966 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -139,7 +139,28 @@ struct arch_shared_info { }; typedef struct arch_shared_info arch_shared_info_t; typedef uint64_t xen_callback_t; -#endif +#endif /* ifndef __ASSEMBLY __ */ + +/* PSR bits (CPSR, SPSR)*/ + +/* 0-4: Mode */ +#define PSR_MODE_MASK 0x1f +#define PSR_MODE_USR 0x10 +#define PSR_MODE_FIQ 0x11 +#define PSR_MODE_IRQ 0x12 +#define PSR_MODE_SVC 0x13 +#define PSR_MODE_MON 0x16 +#define PSR_MODE_ABT 0x17 +#define PSR_MODE_HYP 0x1a +#define PSR_MODE_UND 0x1b +#define PSR_MODE_SYS 0x1f + +#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 */ +#define PSR_JAZELLE (1<<24) /* Jazelle Mode */ #endif /* __XEN_PUBLIC_ARCH_ARM_H__ */ -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:30 UTC
[PATCH V2 36/40] libxc: add ARM support to xc_dom (PV domain building)
Includes ARM zImage support. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxc/Makefile | 1 + tools/libxc/xc_dom.h | 5 +- tools/libxc/xc_dom_arm.c | 135 +++++++++++++++++++++++++++- tools/libxc/xc_dom_armzimageloader.c | 167 ++++++++++++++++++++++++++++++++++ tools/libxc/xc_dom_core.c | 12 ++- tools/libxc/xg_private.h | 4 + 6 files changed, 315 insertions(+), 9 deletions(-) create mode 100644 tools/libxc/xc_dom_armzimageloader.c diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index ca38cbd..a01d457 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -59,6 +59,7 @@ GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c GUEST_SRCS-y += xc_dom_elfloader.c GUEST_SRCS-$(CONFIG_X86) += xc_dom_bzimageloader.c +GUEST_SRCS-$(CONFIG_ARM) += xc_dom_armzimageloader.c GUEST_SRCS-y += xc_dom_binloader.c GUEST_SRCS-y += xc_dom_compat_linux.c diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h index 2aef64a..4db8fad 100644 --- a/tools/libxc/xc_dom.h +++ b/tools/libxc/xc_dom.h @@ -93,6 +93,7 @@ struct xc_dom_image { void *p2m_guest; /* physical memory */ + xen_pfn_t rambase_pfn; xen_pfn_t total_pages; struct xc_dom_phys *phys_pages; int realmodearea_log; @@ -286,7 +287,7 @@ static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn) { if (dom->shadow_enabled) return pfn; - return dom->p2m_host[pfn]; + return dom->p2m_host[pfn - dom->rambase_pfn]; } static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom, @@ -294,7 +295,7 @@ static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom, { if (xc_dom_feature_translated(dom)) return pfn; - return dom->p2m_host[pfn]; + return dom->p2m_host[pfn - dom->rambase_pfn]; } /* --- arch bits --------------------------------------------------- */ diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c index 122d0e8..9099cad 100644 --- a/tools/libxc/xc_dom_arm.c +++ b/tools/libxc/xc_dom_arm.c @@ -18,14 +18,138 @@ * Copyright (c) 2011, Citrix Systems */ #include <inttypes.h> + #include <xen/xen.h> +#include <xen/io/protocols.h> + #include "xg_private.h" #include "xc_dom.h" +/* ------------------------------------------------------------------------ */ +/* + * arm guests are hybrid and start off with paging disabled, therefore no + * pagetables and nothing to do here. + */ +static int count_pgtables_arm(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + return 0; +} + +static int setup_pgtables_arm(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int alloc_magic_pages(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + /* XXX + * dom->p2m_guest + * dom->start_info_pfn + * dom->xenstore_pfn + * dom->console_pfn + */ + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int start_info_arm(struct xc_dom_image *dom) +{ + DOMPRINTF_CALLED(dom->xch); + /* XXX */ + return 0; +} + +static int shared_info_arm(struct xc_dom_image *dom, void *ptr) +{ + DOMPRINTF_CALLED(dom->xch); + /* XXX */ + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static int vcpu_arm(struct xc_dom_image *dom, void *ptr) +{ + vcpu_guest_context_t *ctxt = ptr; + + DOMPRINTF_CALLED(dom->xch); + + /* clear everything */ + memset(ctxt, 0, sizeof(*ctxt)); + + ctxt->user_regs.pc = dom->parms.virt_entry; + ctxt->user_regs.r0 = 0; /* SBZ */ + ctxt->user_regs.r1 = 2272; /* Machine NR: Versatile Express */ + + ctxt->user_regs.r2 = 0xffffffff; //devicetree_seg //dtb_paddr; //atags or dtb /* XXX using APPEND right now */ + ctxt->user_regs.r3 = 0xdeadbeef; + ctxt->sctlr = /* #define SCTLR_BASE */0x00c50078; + 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; + + DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx32, + ctxt->user_regs.cpsr, ctxt->user_regs.pc); + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static struct xc_dom_arch xc_dom_32 = { + .guest_type = "xen-3.0-armv7l", + .native_protocol = XEN_IO_PROTO_ABI_ARM, + .page_shift = PAGE_SHIFT_ARM, + .sizeof_pfn = 8, + .alloc_magic_pages = alloc_magic_pages, + .count_pgtables = count_pgtables_arm, + .setup_pgtables = setup_pgtables_arm, + .start_info = start_info_arm, + .shared_info = shared_info_arm, + .vcpu = vcpu_arm, +}; + +static void __init register_arch_hooks(void) +{ + xc_dom_register_arch_hooks(&xc_dom_32); +} + int arch_setup_meminit(struct xc_dom_image *dom) { - errno = ENOSYS; - return -1; + int rc; + xen_pfn_t pfn, allocsz, i; + + dom->shadow_enabled = 1; + + dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages); + + /* setup initial p2m */ + for ( pfn = 0; pfn < dom->total_pages; pfn++ ) + dom->p2m_host[pfn] = pfn + dom->rambase_pfn; + + /* allocate guest memory */ + for ( i = rc = allocsz = 0; + (i < dom->total_pages) && !rc; + i += allocsz ) + { + allocsz = dom->total_pages - i; + if ( allocsz > 1024*1024 ) + allocsz = 1024*1024; + + rc = xc_domain_populate_physmap_exact( + dom->xch, dom->guest_domid, allocsz, + 0, 0, &dom->p2m_host[i]); + } + + return 0; } int arch_setup_bootearly(struct xc_dom_image *dom) @@ -36,9 +160,14 @@ int arch_setup_bootearly(struct xc_dom_image *dom) int arch_setup_bootlate(struct xc_dom_image *dom) { - DOMPRINTF("%s: doing nothing", __FUNCTION__); + /* XXX + * map shared info + * map grant tables + * setup shared info + */ return 0; } + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_dom_armzimageloader.c b/tools/libxc/xc_dom_armzimageloader.c new file mode 100644 index 0000000..220176d --- /dev/null +++ b/tools/libxc/xc_dom_armzimageloader.c @@ -0,0 +1,167 @@ +/* + * Xen domain builder -- ARM zImage bits + * + * Parse and load ARM zImage kernel images. + * + * Copyright (C) 2012, Citrix Systems. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> + +#include "xg_private.h" +#include "xc_dom.h" + +#include <arpa/inet.h> /* XXX ntohl is not the right function... */ + +#define ZIMAGE_MAGIC_OFFSET 0x24 +#define ZIMAGE_START_OFFSET 0x28 +#define ZIMAGE_END_OFFSET 0x2c + +#define ZIMAGE_MAGIC 0x016f2818 + +struct minimal_dtb_header { + uint32_t magic; + uint32_t total_size; + /* There are other fields but we don''t use them yet. */ +}; + +#define DTB_MAGIC 0xd00dfeed + +static int xc_dom_probe_zimage_kernel(struct xc_dom_image *dom) +{ + uint32_t *zimage; + uint32_t end; + + if ( dom->kernel_blob == NULL ) + { + xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, + "%s: no kernel image loaded", __FUNCTION__); + return -EINVAL; + } + + if ( dom->kernel_size < 0x30 /*sizeof(struct setup_header)*/ ) + { + xc_dom_printf(dom->xch, "%s: kernel image too small", __FUNCTION__); + return -EINVAL; + } + + zimage = (uint32_t *)dom->kernel_blob; + if ( zimage[ZIMAGE_MAGIC_OFFSET/4] != ZIMAGE_MAGIC ) + { + xc_dom_printf(dom->xch, "%s: kernel is not a bzImage", __FUNCTION__); + return -EINVAL; + } + + end = zimage[ZIMAGE_END_OFFSET/4]; + + /* + * Check for an appended DTB. + */ + if ( end + sizeof(struct minimal_dtb_header) < dom->kernel_size ) { + struct minimal_dtb_header *dtb_hdr; + dtb_hdr = (struct minimal_dtb_header *)(dom->kernel_blob + end); + if (ntohl/*be32_to_cpu*/(dtb_hdr->magic) == DTB_MAGIC) { + xc_dom_printf(dom->xch, "%s: found an appended DTB", __FUNCTION__); + end += ntohl/*be32_to_cpu*/(dtb_hdr->total_size); + } + } + + dom->kernel_size = end; + + return 0; +} + +static int xc_dom_parse_zimage_kernel(struct xc_dom_image *dom) +{ + uint32_t *zimage; + uint32_t start, entry_addr; + uint64_t v_start, v_end; + uint64_t rambase = 0x80000000; /* XXX */ + + DOMPRINTF_CALLED(dom->xch); + + zimage = (uint32_t *)dom->kernel_blob; + + dom->rambase_pfn = rambase >> XC_PAGE_SHIFT; + + v_start = rambase + 0x8000; /* XXX */ + v_end = v_start + dom->kernel_size; + + start = zimage[ZIMAGE_START_OFFSET/4]; + + if (start == 0) + entry_addr = v_start; + else + entry_addr = start; + + /* find kernel segment */ + dom->kernel_seg.vstart = v_start; + dom->kernel_seg.vend = v_end; + + dom->parms.virt_entry = entry_addr; + + dom->guest_type = "xen-3.0-armv7l"; + DOMPRINTF("%s: %s: RAM starts at %"PRI_xen_pfn, + __FUNCTION__, dom->guest_type, dom->rambase_pfn); + DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "", + __FUNCTION__, dom->guest_type, + dom->kernel_seg.vstart, dom->kernel_seg.vend); + return 0; +} + +static int xc_dom_load_zimage_kernel(struct xc_dom_image *dom) +{ + void *dst; + + DOMPRINTF_CALLED(dom->xch); + + dst = xc_dom_seg_to_ptr(dom, &dom->kernel_seg); + + DOMPRINTF("%s: kernel sed %#"PRIx64"-%#"PRIx64, + __func__, dom->kernel_seg.vstart, dom->kernel_seg.vend); + DOMPRINTF("%s: copy %zd bytes from blob %p to dst %p", + __func__, dom->kernel_size, dom->kernel_blob, dst); + + memcpy(dst, dom->kernel_blob, dom->kernel_size); + + return 0; +} + +static struct xc_dom_loader zimage_loader = { + .name = "Linux zImage (ARM)", + .probe = xc_dom_probe_zimage_kernel, + .parser = xc_dom_parse_zimage_kernel, + .loader = xc_dom_load_zimage_kernel, +}; + +static void __init register_loader(void) +{ + xc_dom_register_loader(&zimage_loader); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c index fea9de5..b0d48d5 100644 --- a/tools/libxc/xc_dom_core.c +++ b/tools/libxc/xc_dom_core.c @@ -307,15 +307,17 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn, xen_pfn_t count) { struct xc_dom_phys *phys; + xen_pfn_t offset; unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom); char *mode = "unset"; - if ( pfn > dom->total_pages || /* multiple checks to avoid overflows */ + offset = pfn-dom->rambase_pfn; + if ( offset > dom->total_pages || /* multiple checks to avoid overflows */ count > dom->total_pages || - pfn > dom->total_pages - count ) + offset > dom->total_pages - count ) { - DOMPRINTF("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")", - __FUNCTION__, pfn, dom->total_pages); + DOMPRINTF("%s: pfn %"PRI_xen_pfn" out of range (0x%" PRIpfn " > 0x%" PRIpfn ")", + __FUNCTION__, pfn, offset, dom->total_pages); return NULL; } @@ -599,6 +601,8 @@ struct xc_dom_image *xc_dom_allocate(xc_interface *xch, dom->parms.virt_hv_start_low = UNSET_ADDR; dom->parms.elf_paddr_offset = UNSET_ADDR; + dom->rambase_pfn = 0; + dom->alloc_malloc += sizeof(*dom); return dom; diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index a29fa26..a271942 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -148,6 +148,10 @@ typedef l4_pgentry_64_t l4_pgentry_t; #define l4_table_offset(_a) l4_table_offset_x86_64(_a) #endif +#define PAGE_SHIFT_ARM 12 +#define PAGE_SIZE_ARM (1UL << PAGE_SHIFT_ARM) +#define PAGE_MASK_ARM (~(PAGE_SIZE_ARM-1)) + #define PAGE_SHIFT_X86 12 #define PAGE_SIZE_X86 (1UL << PAGE_SHIFT_X86) #define PAGE_MASK_X86 (~(PAGE_SIZE_X86-1)) -- 1.7.9.1
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxc/xc_dom_arm.c | 2 ++ xen/arch/arm/domain.c | 5 ++++- xen/include/public/arch-arm.h | 4 ++++ 3 files changed, 10 insertions(+), 1 deletions(-) diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c index 9099cad..bea409b 100644 --- a/tools/libxc/xc_dom_arm.c +++ b/tools/libxc/xc_dom_arm.c @@ -96,6 +96,8 @@ static int vcpu_arm(struct xc_dom_image *dom, void *ptr) ctxt->user_regs.cpsr = PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC; + ctxt->flags = VGCF_online; + DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx32, ctxt->user_regs.cpsr, ctxt->user_regs.pc); diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index ac6a30d..f61568b 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -416,7 +416,10 @@ int arch_set_info_guest( v->arch.ttbr1 = ctxt->ttbr1; v->arch.ttbcr = ctxt->ttbcr; - clear_bit(_VPF_down, &v->pause_flags); + if ( ctxt->flags & VGCF_online ) + clear_bit(_VPF_down, &v->pause_flags); + else + set_bit(_VPF_down, &v->pause_flags); return 0; } diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index 7ebe966..6e0fe47 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -124,6 +124,10 @@ typedef uint32_t xen_ulong_t; #define PRI_xen_ulong PRIx32 struct vcpu_guest_context { +#define _VGCF_online 0 +#define VGCF_online (1<<_VGCF_online) + uint32_t flags; /* VGCF_* */ + struct cpu_user_regs user_regs; /* User-level CPU registers */ uint32_t sctlr; -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:30 UTC
[PATCH V2 38/40] arm: fix typo s/approprately/appropriately/g
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Tim Deegan <tim@xen.org> --- xen/include/asm-arm/page.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index f3e4d1a..9511c45 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -102,7 +102,7 @@ typedef struct { unsigned long af:1; /* Access Flag */ unsigned long ng:1; /* Not-Global */ - /* The base address must be approprately aligned for Block entries */ + /* The base address must be appropriately aligned for Block entries */ unsigned long base:28; /* Base address of block or next table */ unsigned long sbz:12; /* Must be zero */ @@ -137,7 +137,7 @@ typedef struct { unsigned long af:1; /* Access Flag */ unsigned long sbz4:1; - /* The base address must be approprately aligned for Block entries */ + /* The base address must be appropriately aligned for Block entries */ unsigned long base:28; /* Base address of block or next table */ unsigned long sbz3:12; @@ -162,7 +162,7 @@ typedef struct { unsigned long pad2:10; - /* The base address must be approprately aligned for Block entries */ + /* The base address must be appropriately aligned for Block entries */ unsigned long base:28; /* Base address of block or next table */ unsigned long pad1:24; -- 1.7.9.1
Based on init-xenstore-domain.c. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- tools/xcutils/Makefile | 6 ++- tools/xcutils/xcbuild.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletions(-) create mode 100644 tools/xcutils/xcbuild.c diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile index 6c502f1..dcd2c84 100644 --- a/tools/xcutils/Makefile +++ b/tools/xcutils/Makefile @@ -11,7 +11,7 @@ XEN_ROOT = $(CURDIR)/../.. include $(XEN_ROOT)/tools/Rules.mk -PROGRAMS = xc_restore xc_save readnotes lsevtchn +PROGRAMS = xc_restore xc_save readnotes lsevtchn xcbuild CFLAGS += -Werror @@ -19,6 +19,7 @@ CFLAGS_xc_restore.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) CFLAGS_xc_save.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore) CFLAGS_readnotes.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) CFLAGS_lsevtchn.o := $(CFLAGS_libxenctrl) +CFLAGS_xcbuild.o := $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) .PHONY: all all: build @@ -32,6 +33,9 @@ xc_restore: xc_restore.o xc_save: xc_save.o $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) +xcbuild: xcbuild.o + $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS) + readnotes: readnotes.o $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS) diff --git a/tools/xcutils/xcbuild.c b/tools/xcutils/xcbuild.c new file mode 100644 index 0000000..54f5c38 --- /dev/null +++ b/tools/xcutils/xcbuild.c @@ -0,0 +1,100 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#include <errno.h> + +#include <xenctrl.h> +#include <xentoollog.h> +#include <xc_dom.h> + +int main(int argc, char **argv) +{ + xentoollog_logger *logger; + xc_interface *xch; + int rv; + const char *image; + uint32_t domid; + xen_domain_handle_t handle; + int maxmem = 128; /* MB */ + int memory_kb = 2*(maxmem + 1)*1024; /* bit of slack... */ + struct xc_dom_image *dom; + + image = (argc < 2) ? "guest.img" : argv[1]; + printf("Image: %s\n", image); + printf("Memory: %dKB\n", memory_kb); + + logger = (xentoollog_logger*) + xtl_createlogger_stdiostream(stderr, XTL_DEBUG, 0); + if ( logger == NULL ) + { + perror("xtl_createlogger_stdiostream"); + exit(1); + } + + xch = xc_interface_open(logger, logger, 0); + if ( xch == NULL ) + { + perror("xc_interface_open"); + exit(1); + } + + rv = xc_dom_loginit(xch); + if (rv) return rv; + + //rv = xc_flask_context_to_sid(xch, argv[3], strlen(argv[3]), &ssid); + //if (rv) return rv; + + rv = xc_domain_create(xch, 0 /* ssid */, handle, 0 /* flags */, &domid); + printf("xc_domain_create: %d (%d)\n", rv, errno); + if ( rv < 0 ) + { + perror("xc_domain_create"); + exit(1); + } + + printf("building dom%d\n", domid); + + rv = xc_domain_max_vcpus(xch, domid, 1); + if ( rv < 0) + { + perror("xc_domain_max_vcpus"); + exit(1); + } + + rv = xc_domain_setmaxmem(xch, domid, memory_kb); + if ( rv < 0) + { + perror("xc_domain_setmaxmem"); + exit(1); + } + + dom = xc_dom_allocate(xch, "", NULL); + rv = xc_dom_kernel_file(dom, image); + if (rv) return rv; + rv = xc_dom_boot_xen_init(dom, xch, domid); + if (rv) return rv; + rv = xc_dom_parse_image(dom); + if (rv) return rv; + rv = xc_dom_mem_init(dom, 2*maxmem);/* XXX */ + if (rv) return rv; + rv = xc_dom_boot_mem_init(dom); + if (rv) return rv; + rv = xc_dom_build_image(dom); + if (rv) return rv; + rv = xc_dom_boot_image(dom); + if (rv) return rv; + + xc_dom_release(dom); + + rv = xc_domain_unpause(xch, domid); + if ( rv ) + { + perror("xc_domain_unpause"); + exit(1); + } + + xc_interface_close(xch); + + return 0; +} -- 1.7.9.1
Ian Campbell
2012-Jun-26 10:30 UTC
[PATCH V2 40/40] HACK: arm: disable hypercall continuations.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/include/xen/sched.h | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 53804c8..15fa6b4 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -577,10 +577,14 @@ unsigned long hypercall_create_continuation( unsigned int op, const char *format, ...); void hypercall_cancel_continuation(void); +#ifdef CONFIG_ARM +#define hypercall_preempt_check() (0) +#else #define hypercall_preempt_check() (unlikely( \ softirq_pending(smp_processor_id()) | \ local_events_need_delivery() \ )) +#endif extern struct domain *domain_list; -- 1.7.9.1
Ian Campbell
2012-Jun-26 15:26 UTC
Re: [PATCH 00/40 V2] arm: boot a dom1 to "Calibrating delay loop" then hang
On Tue, 2012-06-26 at 11:29 +0100, Ian Campbell wrote:> I intend to commit those patches which are acked and which do not depend > on non-acked patches shortly. > > A 01 arm: allocate top level p2m page for all non-idle domains > A 02 arm: handy function to print a walk of a page table > A 03 arm: correct and expand TLB flush CP15 registers > A 04 arm: restore stack on return from trap. > A 05 arm: enable interrupts while handling traps > A 06 arm: hook up domctl and memory_op > A 07 arm: allocate and setup a guest vcpu. > A 08 arm: print domid as part of debug trap > A 09 arm: remove unnecessarily verbose print from p2m_load_VTTBR > A 10 arm: implement p2m lookup > A 11 arm: remove hard tabs from init_idle_domain > A 12 arm: stub out sync_vcpu_execstate > A 13 arm: implement stub version of flush_tlb_mask. > A 14 arm: do not set max_vcpus = 8 in arch_domain_create. > A 15 arm: Add simple cpu_{sibling,core}_maskI have applied these. [...]> A 18 arm: context switch a bunch of guest state. > A 19 arm: dump a page table walk when va_to_par fails. > A 20 arm: dump guest s1 walk on data abort which is not a stage 2 issue.And these. [...]> A 22 arm: use correct attributes for mappings in copy_from_paddr()This didn''t apply without "16 arm: allow p2m to be created with specific MATTR.", skipped.> A 23 arm: map fixmaps non-executable. > A 24 arm: fix locking in create_p2m_entriesApplied these too. After this point there were increasingly more rejects due to missing patches, so I stopped. Ian.
Tim Deegan
2012-Jun-28 11:00 UTC
Re: [PATCH V2 17/40] arm: implement vpl011 (UART) emulator.
At 10:29 +0000 on 26 Jun (1340706581), Ian Campbell wrote:> This is not interended to provide a full emulation, but rather just enough to > satisfy the use made by Linux'' boot time decompressor code (which is too early > for DT etc) > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Tim Deegan <tim@xen.org>
Tim Deegan
2012-Jun-28 11:02 UTC
Re: [PATCH V2 28/40] arm: enable data-cache at the same time as enabling the MMU, not before
At 10:29 +0000 on 26 Jun (1340706592), Ian Campbell wrote:> With enough warnings enabled the model seemed to be complaining that pages > cached before paging was enabled had been mapped with to inconsistent sets of > attributes. I''m not convinced that isn''t a model issue, nor am I convinced > this has really fixed anything, but it seems sensible enough. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Tim Deegan <tim@xen.org>
Tim Deegan
2012-Jun-28 11:05 UTC
Re: [PATCH V2 33/40] arm: unwind allocations etc on arch_domain_create_failure
At 10:29 +0000 on 26 Jun (1340706597), Ian Campbell wrote:> This involves adding the necessary teardown/free functions for some modules. > > Don''t initialise full arch domain state for the idle domain, it''s not needed. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Tim Deegan <tim@xen.org>
At 10:30 +0000 on 26 Jun (1340706601), Ian Campbell wrote:> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Tim Deegan <tim@xen.org>
Ian Campbell
2012-Jun-28 12:46 UTC
Re: [PATCH V2 16/40] arm: allow p2m to be created with specific MATTR.
On Tue, 2012-06-26 at 11:29 +0100, Ian Campbell wrote:> Rename p2m_create_entry to p2m_create_table since it can now only be used to > insert non-leaf entries into the page table. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>This change should also have incorporated the following which somehow ended up in [PATCH V2 22/40] arm: use correct attributes for mappings in copy_from_paddr() I''ll move them over... diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 6efe23c..2b6c1780 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -36,6 +36,14 @@ #define MAIR0VAL 0xeeaa4400 #define MAIR1VAL 0xff000004 +/* + * Attribute Indexes. + * + * These are valid in the AttrIndx[2:0] field of an LPAE stage 1 page + * table entry. They are indexes into the bytes of the MAIR* + * registers, as defined above. + * + */ #define UNCACHED 0x0 #define BUFFERABLE 0x1 #define WRITETHROUGH 0x2 @@ -46,6 +54,13 @@ #define DEV_WC BUFFERABLE #define DEV_CACHED WRITEBACK +/* + * Stage 2 Memory Type. + * + * These are valid in the MemAttr[3:0] field of an LPAE stage 2 page + * table entry. + * + */ #define MATTR_DEV 0x1 #define MATTR_MEM 0xf
Stefano Stabellini
2012-Jun-28 13:00 UTC
Re: [PATCH V2 16/40] arm: allow p2m to be created with specific MATTR.
On Tue, 26 Jun 2012, Ian Campbell wrote:> Rename p2m_create_entry to p2m_create_table since it can now only be used to > insert non-leaf entries into the page table. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>> xen/arch/arm/p2m.c | 22 ++++++++++++---------- > xen/include/asm-arm/page.h | 6 ++++-- > 2 files changed, 16 insertions(+), 12 deletions(-) > > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c > index ec41d38..35bfa2f 100644 > --- a/xen/arch/arm/p2m.c > +++ b/xen/arch/arm/p2m.c > @@ -91,7 +91,8 @@ int p2m_pod_decrease_reservation(struct domain *d, > return -ENOSYS; > } > > -static int p2m_create_entry(struct domain *d, > +/* Allocate a new page table page and hook it in via the given entry */ > +static int p2m_create_table(struct domain *d, > lpae_t *entry) > { > struct p2m_domain *p2m = &d->arch.p2m; > @@ -111,7 +112,7 @@ static int p2m_create_entry(struct domain *d, > clear_page(p); > unmap_domain_page(p); > > - pte = mfn_to_p2m_entry(page_to_mfn(page)); > + pte = mfn_to_p2m_entry(page_to_mfn(page), MATTR_MEM); > > write_pte(entry, pte); > > @@ -122,7 +123,8 @@ static int create_p2m_entries(struct domain *d, > int alloc, > paddr_t start_gpaddr, > paddr_t end_gpaddr, > - paddr_t maddr) > + paddr_t maddr, > + int mattr) > { > int rc; > struct p2m_domain *p2m = &d->arch.p2m; > @@ -140,7 +142,7 @@ static int create_p2m_entries(struct domain *d, > { > if ( !first[first_table_offset(addr)].p2m.valid ) > { > - rc = p2m_create_entry(d, &first[first_table_offset(addr)]); > + rc = p2m_create_table(d, &first[first_table_offset(addr)]); > if ( rc < 0 ) { > printk("p2m_populate_ram: L1 failed\n"); > goto out; > @@ -159,7 +161,7 @@ static int create_p2m_entries(struct domain *d, > > if ( !second[second_table_offset(addr)].p2m.valid ) > { > - rc = p2m_create_entry(d, &second[second_table_offset(addr)]); > + rc = p2m_create_table(d, &second[second_table_offset(addr)]); > if ( rc < 0 ) { > printk("p2m_populate_ram: L2 failed\n"); > goto out; > @@ -198,11 +200,11 @@ static int create_p2m_entries(struct domain *d, > goto out; > } > > - pte = mfn_to_p2m_entry(page_to_mfn(page)); > + pte = mfn_to_p2m_entry(page_to_mfn(page), mattr); > > write_pte(&third[third_table_offset(addr)], pte); > } else { > - lpae_t pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT); > + lpae_t pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr); > write_pte(&third[third_table_offset(addr)], pte); > maddr += PAGE_SIZE; > } > @@ -226,7 +228,7 @@ int p2m_populate_ram(struct domain *d, > paddr_t start, > paddr_t end) > { > - return create_p2m_entries(d, 1, start, end, 0); > + return create_p2m_entries(d, 1, start, end, 0, MATTR_MEM); > } > > int map_mmio_regions(struct domain *d, > @@ -234,7 +236,7 @@ int map_mmio_regions(struct domain *d, > paddr_t end_gaddr, > paddr_t maddr) > { > - return create_p2m_entries(d, 0, start_gaddr, end_gaddr, maddr); > + return create_p2m_entries(d, 0, start_gaddr, end_gaddr, maddr, MATTR_DEV); > } > > int guest_physmap_add_page(struct domain *d, > @@ -244,7 +246,7 @@ int guest_physmap_add_page(struct domain *d, > { > return create_p2m_entries(d, 0, gpfn << PAGE_SHIFT, > (gpfn + (1<<page_order)) << PAGE_SHIFT, > - mfn << PAGE_SHIFT); > + mfn << PAGE_SHIFT, MATTR_MEM); > } > > void guest_physmap_remove_page(struct domain *d, > diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h > index 183ba5f..2783c30 100644 > --- a/xen/include/asm-arm/page.h > +++ b/xen/include/asm-arm/page.h > @@ -46,6 +46,8 @@ > #define DEV_WC BUFFERABLE > #define DEV_CACHED WRITEBACK > > +#define MATTR_DEV 0x1 > +#define MATTR_MEM 0xf > > #ifndef __ASSEMBLY__ > > @@ -187,7 +189,7 @@ static inline lpae_t mfn_to_xen_entry(unsigned long mfn) > return e; > } > > -static inline lpae_t mfn_to_p2m_entry(unsigned long mfn) > +static inline lpae_t mfn_to_p2m_entry(unsigned long mfn, unsigned int mattr) > { > paddr_t pa = ((paddr_t) mfn) << PAGE_SHIFT; > lpae_t e = (lpae_t) { > @@ -196,7 +198,7 @@ static inline lpae_t mfn_to_p2m_entry(unsigned long mfn) > .p2m.sh = LPAE_SH_OUTER, > .p2m.write = 1, > .p2m.read = 1, > - .p2m.mattr = 0xf, > + .p2m.mattr = mattr, > .p2m.table = 1, > .p2m.valid = 1, > }; > -- > 1.7.9.1 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel >
Stefano Stabellini
2012-Jun-28 13:04 UTC
Re: [PATCH V2 21/40] arm: implement vcpu_show_execution_state
On Tue, 26 Jun 2012, Ian Campbell wrote:> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>> xen/arch/arm/dummy.S | 1 - > xen/arch/arm/traps.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---- > 2 files changed, 51 insertions(+), 6 deletions(-) > > diff --git a/xen/arch/arm/dummy.S b/xen/arch/arm/dummy.S > index 03f7489..cab9522 100644 > --- a/xen/arch/arm/dummy.S > +++ b/xen/arch/arm/dummy.S > @@ -21,7 +21,6 @@ DUMMY(pirq_set_affinity); > DUMMY(arch_get_info_guest); > DUMMY(arch_vcpu_reset); > NOP(update_vcpu_system_time); > -DUMMY(vcpu_show_execution_state); > > /* Page Reference & Type Maintenance */ > DUMMY(get_page); > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c > index d8eb5a9..f5f43da 100644 > --- a/xen/arch/arm/traps.c > +++ b/xen/arch/arm/traps.c > @@ -170,7 +170,13 @@ void panic_PAR(uint64_t par, const char *when) > panic("Error during %s-to-physical address translation\n", when); > } > > -void show_registers(struct cpu_user_regs *regs) > +struct reg_ctxt { > + uint32_t sctlr; > + uint32_t ttbr0, ttbr1, ttbcr; > +}; > +static void _show_registers(struct cpu_user_regs *regs, > + struct reg_ctxt *ctxt, > + int guest_mode) > { > static const char *mode_strings[] = { > [PSR_MODE_USR] = "USR", > @@ -187,7 +193,7 @@ void show_registers(struct cpu_user_regs *regs) > print_xen_info(); > printk("CPU: %d\n", smp_processor_id()); > printk("PC: %08"PRIx32, regs->pc); > - if ( !guest_mode(regs) ) > + if ( !guest_mode ) > print_symbol(" %s", regs->pc); > printk("\n"); > printk("CPSR: %08"PRIx32" MODE:%s\n", regs->cpsr, > @@ -199,7 +205,7 @@ void show_registers(struct cpu_user_regs *regs) > printk(" R8: %08"PRIx32" R9: %08"PRIx32" R10:%08"PRIx32" R11:%08"PRIx32" R12:%08"PRIx32"\n", > regs->r8, regs->r9, regs->r10, regs->r11, regs->r12); > > - if ( guest_mode(regs) ) > + if ( guest_mode ) > { > printk("USR: SP: %08"PRIx32" LR: %08"PRIx32" CPSR:%08"PRIx32"\n", > regs->sp_usr, regs->lr_usr, regs->cpsr); > @@ -217,8 +223,8 @@ void show_registers(struct cpu_user_regs *regs) > regs->r8_fiq, regs->r9_fiq, regs->r10_fiq, regs->r11_fiq, regs->r11_fiq); > printk("\n"); > printk("TTBR0 %08"PRIx32" TTBR1 %08"PRIx32" TTBCR %08"PRIx32"\n", > - READ_CP32(TTBR0), READ_CP32(TTBR1), READ_CP32(TTBCR)); > - printk("SCTLR %08"PRIx32"\n", READ_CP32(SCTLR)); > + ctxt->ttbr0, ctxt->ttbr1, ctxt->ttbcr); > + printk("SCTLR %08"PRIx32"\n", ctxt->sctlr); > printk("VTTBR %010"PRIx64"\n", READ_CP64(VTTBR)); > printk("\n"); > } > @@ -241,6 +247,26 @@ void show_registers(struct cpu_user_regs *regs) > printk("\n"); > } > > +void show_registers(struct cpu_user_regs *regs) > +{ > + struct reg_ctxt ctxt; > + ctxt.sctlr = READ_CP32(SCTLR); > + ctxt.ttbcr = READ_CP32(TTBCR); > + ctxt.ttbr0 = READ_CP32(TTBR0); > + ctxt.ttbr1 = READ_CP32(TTBR1); > + _show_registers(regs, &ctxt, guest_mode(regs)); > +} > + > +void vcpu_show_registers(const struct vcpu *v) > +{ > + struct reg_ctxt ctxt; > + ctxt.sctlr = v->arch.sctlr; > + ctxt.ttbcr = v->arch.ttbcr; > + ctxt.ttbr0 = v->arch.ttbr0; > + ctxt.ttbr1 = v->arch.ttbr1; > + _show_registers(&v->arch.cpu_info->guest_cpu_user_regs, &ctxt, 1); > +} > + > static void show_guest_stack(struct cpu_user_regs *regs) > { > printk("GUEST STACK GOES HERE\n"); > @@ -334,6 +360,26 @@ void show_execution_state(struct cpu_user_regs *regs) > show_stack(regs); > } > > +void vcpu_show_execution_state(struct vcpu *v) > +{ > + printk("*** Dumping Dom%d vcpu#%d state: ***\n", > + v->domain->domain_id, v->vcpu_id); > + > + if ( v == current ) > + { > + show_execution_state(guest_cpu_user_regs()); > + return; > + } > + > + vcpu_pause(v); /* acceptably dangerous */ > + > + vcpu_show_registers(v); > + if ( !usr_mode(&v->arch.cpu_info->guest_cpu_user_regs) ) > + show_guest_stack(&v->arch.cpu_info->guest_cpu_user_regs); > + > + vcpu_unpause(v); > +} > + > static void do_unexpected_trap(const char *msg, struct cpu_user_regs *regs) > { > printk("Unexpected Trap: %s\n", msg); > -- > 1.7.9.1 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel >
Stefano Stabellini
2012-Jun-28 13:06 UTC
Re: [PATCH V2 26/40] arm: use interrupt safe spin locks in vgic_vcpu_inject_irq
On Tue, 26 Jun 2012, Ian Campbell wrote:> This function can be called in both interrupt and regular context. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>> xen/arch/arm/vgic.c | 5 +++-- > 1 files changed, 3 insertions(+), 2 deletions(-) > > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index af3523f..91d6166 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -550,6 +550,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual) > uint8_t priority; > struct vgic_irq_rank *rank = vgic_irq_rank(v, 8, idx); > struct pending_irq *iter, *n = irq_to_pending(v, irq); > + unsigned long flags; > > /* irq still pending */ > if (!list_empty(&n->inflight)) > @@ -566,7 +567,7 @@ 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); > + spin_lock_irqsave(&v->arch.vgic.lock, flags); > list_for_each_entry ( iter, &v->arch.vgic.inflight_irqs, inflight ) > { > if ( iter->priority > priority ) > @@ -577,7 +578,7 @@ 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); > + spin_unlock_irqrestore(&v->arch.vgic.lock, flags); > /* we have a new higher priority irq, inject it into the guest */ > } > > -- > 1.7.9.1 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel >
Stefano Stabellini
2012-Jun-28 13:08 UTC
Re: [PATCH V2 25/40] arm: split pending SPIs (global) out from pending PPIs and SGIs (per CPU)
On Tue, 26 Jun 2012, Ian Campbell wrote:> This tracks SPIs in struct arch_domain and PPIs+SGIs in struct arch_vcpu which > seems more logical. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>> xen/arch/arm/vgic.c | 12 +++++++----- > xen/include/asm-arm/domain.h | 10 ++++++++++ > 2 files changed, 17 insertions(+), 5 deletions(-) > > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index 629a0da..af3523f 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -82,9 +82,8 @@ int domain_vgic_init(struct domain *d) > d->arch.vgic.shared_irqs > xmalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d)); > d->arch.vgic.pending_irqs > - 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++) > + xzalloc_array(struct pending_irq, d->arch.vgic.nr_lines); > + for (i=0; i<d->arch.vgic.nr_lines; i++) > 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); > @@ -98,6 +97,10 @@ int vcpu_vgic_init(struct vcpu *v) > > spin_lock_init(&v->arch.vgic.private_irqs.lock); > > + memset(&v->arch.vgic.pending_irqs, 0, sizeof(v->arch.vgic.pending_irqs)); > + for (i = 0; i < 32; i++) > + INIT_LIST_HEAD(&v->arch.vgic.pending_irqs[i].inflight); > + > /* For SGI and PPI the target is always this CPU */ > for ( i = 0 ; i < 8 ; i++ ) > v->arch.vgic.private_irqs.itargets[i] > @@ -535,8 +538,7 @@ struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq) > /* Pending irqs allocation strategy: the first vgic.nr_lines irqs > * are used for SPIs; the rests are used for per cpu irqs */ > if ( irq < 32 ) > - n = &v->domain->arch.vgic.pending_irqs[irq + (v->vcpu_id * 32) > - + v->domain->arch.vgic.nr_lines]; > + n = &v->arch.vgic.pending_irqs[irq]; > else > n = &v->domain->arch.vgic.pending_irqs[irq - 32]; > return n; > diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h > index 620b26e..32deb52 100644 > --- a/xen/include/asm-arm/domain.h > +++ b/xen/include/asm-arm/domain.h > @@ -46,6 +46,10 @@ struct arch_domain > int ctlr; > int nr_lines; > 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; > } vgic; > > @@ -114,7 +118,13 @@ struct arch_vcpu > uint32_t gic_lr[64]; > > struct { > + /* > + * SGIs and PPIs are per-VCPU, SPIs are domain global and in > + * struct arch_domain. > + */ > + struct pending_irq pending_irqs[32]; > 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 > -- > 1.7.9.1 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel >