Ian Campbell
2012-Jun-28 14:47 UTC
[PATCH 01/21] 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> Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/p2m.c | 22 ++++++++++++---------- xen/include/asm-arm/page.h | 21 +++++++++++++++++++-- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index cf12870..5f20246 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; @@ -142,7 +144,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; @@ -161,7 +163,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; @@ -200,11 +202,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 4c3fd0d..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,15 @@ #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 #ifndef __ASSEMBLY__ @@ -187,7 +204,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 +213,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-28 14:47 UTC
[PATCH 0/21 V3] arm: boot a dom1 to "Calibrating delay loop" then hang
A bunch of this series went in in the last batch and Tim & Stefano have now acked a bunch more. As before, 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. Once #06 has an ack I intend to commit #01..#15 and #21. #21 isn''t an ARM patch but has acks from both Keir and Jan. #06 derives from "use interrupt safe spin locks in vgic_vcpu_inject_irq" but has enough new stuff that I didn''t feel comfortable carrying Stefano''s ack over. #18 requires #17 which I haven''t addressed review on yet and which likely requires considerable cleanup anyhow. A 01 arm: allow p2m to be created with specific MATTR. A 02 arm: implement vpl011 (UART) emulator. A 03 arm: implement vcpu_show_execution_state A 04 arm: use correct attributes for mappings in copy_from_paddr() A 05 arm: split pending SPIs (global) out from pending PPIs and SGIs (per CPU) 06 arm: make vgic lock safe for use in interrupt context. A 07 arm: map GICV in all domains, not just dom0. A 08 arm: enable data-cache at the same time as enabling the MMU, not before A 09 arm: Upgrade guest barriers to Outer-Shareable. Enable Protected Table Walk. A 10 arm: gic.lock can be taken in interrupt context, so lock appropriately. A 11 arm: context switch virtual timer registers A 12 arm: the hyp timer seems to work in newer model versions, default to using it. A 13 arm: unwind allocations etc on arch_domain_create_failure A 14 arm: move PSR flag definitions into interface, for tools use. A 15 arm: fix typo s/approprately/appropriately/g X! 16 HACK: arm: initial XENMAPSPACE_gmfn_foreign ! 17 libxc: add ARM support to xc_dom (PV domain building) A 18 arm: implement VGCF_online X! 19 HACK: add simple xcbuild X! 20 HACK: arm: disable hypercall continuations. A 21 xen: add assertion in default_vcpu0_location to protect against broken masks
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> --- 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 80387fd..d11be78 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); @@ -327,6 +328,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 8907f22..620b26e 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
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
Ian Campbell
2012-Jun-28 14:47 UTC
[PATCH 04/21] 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/setup.h | 2 +- 3 files changed, 6 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/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
Ian Campbell
2012-Jun-28 14:47 UTC
[PATCH 05/21] 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> 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
Ian Campbell
2012-Jun-28 14:47 UTC
[PATCH 06/21] arm: make vgic lock safe for use in interrupt context.
In particular vgic_vcpu_inject_irq can be called in both interupt and regular context. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> --- xen/arch/arm/gic.c | 4 ++-- xen/arch/arm/vgic.c | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 339c327..1e60d3b 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -604,14 +604,14 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r } spin_unlock(&gic.lock); - spin_lock(¤t->arch.vgic.lock); + spin_lock_irq(¤t->arch.vgic.lock); p = irq_to_pending(current, virq); if ( p->desc != NULL ) { p->desc->status &= ~IRQ_INPROGRESS; GICC[GICC_DIR] = virq; } list_del_init(&p->inflight); - spin_unlock(¤t->arch.vgic.lock); + spin_unlock_irq(¤t->arch.vgic.lock); i++; } diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index af3523f..a217151 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -114,8 +114,8 @@ int vcpu_vgic_init(struct vcpu *v) return 0; } -#define vgic_lock(v) spin_lock(&(v)->domain->arch.vgic.lock) -#define vgic_unlock(v) spin_unlock(&(v)->domain->arch.vgic.lock) +#define vgic_lock(v) spin_lock_irq(&(v)->domain->arch.vgic.lock) +#define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock) #define vgic_lock_rank(v, r) spin_lock(&(r)->lock) #define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock) @@ -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,18 +567,18 @@ 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 ) { list_add_tail(&n->inflight, &iter->inflight); - spin_unlock(&v->arch.vgic.lock); + spin_unlock_irqrestore(&v->arch.vgic.lock, flags); return; } } 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-28 14:47 UTC
[PATCH 07/21] 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 1e60d3b..b304923 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-28 14:47 UTC
[PATCH 08/21] 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> Acked-by: Tim Deegan <tim@xen.org> --- 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-28 14:47 UTC
[PATCH 09/21] 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-28 14:47 UTC
[PATCH 10/21] 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 b304923..ee83825 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_irq(¤t->arch.vgic.lock); p = irq_to_pending(current, virq); -- 1.7.9.1
Ian Campbell
2012-Jun-28 14:47 UTC
[PATCH 11/21] 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-28 14:48 UTC
[PATCH 12/21] 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-28 14:48 UTC
[PATCH 13/21] 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> Acked-by: Tim Deegan <tim@xen.org> --- 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 a217151..f2fa927 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-28 14:48 UTC
[PATCH 14/21] 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 e915cbf..eb1add9 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -138,7 +138,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-28 14:48 UTC
[PATCH 15/21] 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
Ian Campbell
2012-Jun-28 14:48 UTC
[PATCH 16/21] 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 eb1add9..7ebe966 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-28 14:48 UTC
[PATCH 17/21] 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> Acked-by: Tim Deegan <tim@xen.org> --- 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
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-28 14:48 UTC
[PATCH 20/21] 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-28 14:48 UTC
[PATCH 21/21] xen: add assertion in default_vcpu0_location to protect against broken masks
When setting up the cpu sibling/etc masks on ARM I accidentally and incorrectly omitted a CPU from it''s own sibling mask which caused this function to return an invalid cpu number which caused errors later when we tried to access per_cpu data for that invalid cpu. Add an assert to catch this in the future. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Acked-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org> --- xen/common/domctl.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 9f1a9ad..7ca6b08 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -192,6 +192,7 @@ static unsigned int default_vcpu0_location(cpumask_t *online) cpu = cpumask_first(&cpu_exclude_map); if ( cpumask_weight(&cpu_exclude_map) > 1 ) cpu = cpumask_next(cpu, &cpu_exclude_map); + ASSERT(cpu < nr_cpu_ids); for_each_cpu(i, online) { if ( cpumask_test_cpu(i, &cpu_exclude_map) ) -- 1.7.9.1
Stefano Stabellini
2012-Jul-02 15:42 UTC
Re: [PATCH 06/21] arm: make vgic lock safe for use in interrupt context.
On Thu, 28 Jun 2012, Ian Campbell wrote:> In particular vgic_vcpu_inject_irq can be called in both interupt and regular^> context.ack, typo aside> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > --- > xen/arch/arm/gic.c | 4 ++-- > xen/arch/arm/vgic.c | 11 ++++++----- > 2 files changed, 8 insertions(+), 7 deletions(-) > > diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c > index 339c327..1e60d3b 100644 > --- a/xen/arch/arm/gic.c > +++ b/xen/arch/arm/gic.c > @@ -604,14 +604,14 @@ static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *r > } > spin_unlock(&gic.lock); > > - spin_lock(¤t->arch.vgic.lock); > + spin_lock_irq(¤t->arch.vgic.lock); > p = irq_to_pending(current, virq); > if ( p->desc != NULL ) { > p->desc->status &= ~IRQ_INPROGRESS; > GICC[GICC_DIR] = virq; > } > list_del_init(&p->inflight); > - spin_unlock(¤t->arch.vgic.lock); > + spin_unlock_irq(¤t->arch.vgic.lock); > > i++; > } > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index af3523f..a217151 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -114,8 +114,8 @@ int vcpu_vgic_init(struct vcpu *v) > return 0; > } > > -#define vgic_lock(v) spin_lock(&(v)->domain->arch.vgic.lock) > -#define vgic_unlock(v) spin_unlock(&(v)->domain->arch.vgic.lock) > +#define vgic_lock(v) spin_lock_irq(&(v)->domain->arch.vgic.lock) > +#define vgic_unlock(v) spin_unlock_irq(&(v)->domain->arch.vgic.lock) > > #define vgic_lock_rank(v, r) spin_lock(&(r)->lock) > #define vgic_unlock_rank(v, r) spin_unlock(&(r)->lock) > @@ -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,18 +567,18 @@ 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 ) > { > list_add_tail(&n->inflight, &iter->inflight); > - spin_unlock(&v->arch.vgic.lock); > + spin_unlock_irqrestore(&v->arch.vgic.lock, flags); > return; > } > } > 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 >
Ian Campbell
2012-Jul-03 10:07 UTC
Re: [PATCH 0/21 V3] arm: boot a dom1 to "Calibrating delay loop" then hang
On Thu, 2012-06-28 at 15:47 +0100, Ian Campbell wrote:> A bunch of this series went in in the last batch and Tim & Stefano have > now acked a bunch more. > > As before, 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. > > Once #06 has an ack I intend to commit #01..#15 and #21.#06 now acked therefore I have now committed the following:> A 01 arm: allow p2m to be created with specific MATTR. > A 02 arm: implement vpl011 (UART) emulator. > A 03 arm: implement vcpu_show_execution_state > A 04 arm: use correct attributes for mappings in copy_from_paddr() > A 05 arm: split pending SPIs (global) out from pending PPIs and SGIs (per CPU) > 06 arm: make vgic lock safe for use in interrupt context. > A 07 arm: map GICV in all domains, not just dom0. > A 08 arm: enable data-cache at the same time as enabling the MMU, not before > A 09 arm: Upgrade guest barriers to Outer-Shareable. Enable Protected Table Walk. > A 10 arm: gic.lock can be taken in interrupt context, so lock appropriately. > A 11 arm: context switch virtual timer registers > A 12 arm: the hyp timer seems to work in newer model versions, default to using it. > A 13 arm: unwind allocations etc on arch_domain_create_failure > A 14 arm: move PSR flag definitions into interface, for tools use. > A 15 arm: fix typo s/approprately/appropriately/g[...]> A 21 xen: add assertion in default_vcpu0_location to protect against broken masksI didn''t commit:> X! 16 HACK: arm: initial XENMAPSPACE_gmfn_foreign > ! 17 libxc: add ARM support to xc_dom (PV domain building) > A 18 arm: implement VGCF_online > X! 19 HACK: add simple xcbuild > X! 20 HACK: arm: disable hypercall continuations.Ian.