Jae-Min Ryu
2012-Feb-13 07:59 UTC
[PATCH 07/14] arm: implement the functions which are required to create the dom0.
arm: implement the functions which are required to create the dom0. xen/arch/arm/xen/Makefile | 1 + xen/arch/arm/xen/arch_domain.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- xen/arch/arm/xen/armv7.S | 19 ++++++++ xen/arch/arm/xen/domain_build.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- xen/arch/arm/xen/mm.c | 2 - xen/include/asm-arm/current.h | 23 ++++++++++ xen/include/asm-arm/domain.h | 39 +---------------- 7 files changed, 356 insertions(+), 61 deletions(-) Signed-off-by: Jaemin Ryu <jm77.ryu@samsung.com> diff -r 08f39a9da04f xen/arch/arm/xen/Makefile --- a/xen/arch/arm/xen/Makefile Mon Feb 06 11:17:01 2012 +0900 +++ b/xen/arch/arm/xen/Makefile Sun Feb 12 11:46:32 2012 +0900 @@ -21,3 +21,4 @@ obj-y += crash.o obj-y += p2m.o obj-y += perfmon.o obj-y += pci.o +obj-y += armv7.o diff -r 08f39a9da04f xen/arch/arm/xen/arch_domain.c --- a/xen/arch/arm/xen/arch_domain.c Mon Feb 06 11:17:01 2012 +0900 +++ b/xen/arch/arm/xen/arch_domain.c Sun Feb 12 11:46:32 2012 +0900 @@ -31,6 +31,12 @@ #include <xen/irq.h> #include <xen/irq_cpustat.h> #include <xen/softirq.h> +#include <asm/current.h> +#include <asm/cpu-ops.h> +#include <asm/memory.h> +#include <asm/mmu.h> + +struct vcpu *switch_to( struct vcpu *, struct vcpu_guest_context *, struct vcpu_guest_context *); void arch_dump_domain_info(struct domain *d) { @@ -52,33 +58,84 @@ unsigned long hypercall_create_continuat int arch_domain_create(struct domain *d, unsigned int domcr_flags) { - NOT_YET(); + int rc; - return -EINVAL; + rc = 0; + if (is_idle_domain(d)) + return rc; + + d->arch.ioport_caps = rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex); + rc = -ENOMEM; + if (d->arch.ioport_caps == NULL) { + goto failed; + } + + if ((d->shared_info = alloc_xenheap_pages(0, MEMF_bits(32))) == NULL) { + goto failed; + } + + clear_page(d->shared_info); + share_xen_page_with_guest(virt_to_page(d->shared_info), d, XENSHARE_writable); + + d->arch.pirq_irq = xmalloc_array(int, d->nr_pirqs); + if (!d->arch.pirq_irq) { + goto failed; + } + + memset(d->arch.pirq_irq, 0, d->nr_pirqs * sizeof(*d->arch.pirq_irq)); + + d->arch.irq_pirq = xmalloc_array(int, nr_irqs); + if ( !d->arch.irq_pirq ) { + goto failed; + } + + memset(d->arch.irq_pirq, 0, nr_irqs * sizeof(*d->arch.irq_pirq)); + + return 0; + +failed: + d->is_dying = DOMDYING_dead; + xfree(d->arch.pirq_irq); + xfree(d->arch.irq_pirq); + + free_xenheap_page(d->shared_info); + + return rc; } void arch_domain_destroy(struct domain *d) { - NOT_YET(); + free_xenheap_page(d->shared_info); + + xfree(d->arch.pirq_irq); + xfree(d->arch.irq_pirq); } struct vcpu_guest_context *alloc_vcpu_guest_context(void) { - NOT_YET(); + struct vcpu_guest_context *vgc; - return NULL; + vgc = xmalloc(struct vcpu_guest_context); + + return vgc; } void free_vcpu_guest_context(struct vcpu_guest_context *context) { - NOT_YET(); + xfree(context); } struct vcpu *alloc_vcpu_struct(void) { - NOT_YET(); - return NULL; + struct vcpu *v; + + v = xmalloc(struct vcpu); + if ( v != NULL ) + memset(v, 0, sizeof(struct vcpu)); + + + return v; } void arch_vcpu_reset(struct vcpu *v) @@ -88,7 +145,6 @@ void arch_vcpu_reset(struct vcpu *v) int vcpu_initialise(struct vcpu *v) { - NOT_YET(); return 0; } @@ -99,27 +155,32 @@ void vcpu_destroy(struct vcpu *v) void free_vcpu_struct(struct vcpu *v) { - NOT_YET(); + xfree(v); } struct domain *alloc_domain_struct(void) { - NOT_YET(); + struct domain *d; - return NULL; + d = xmalloc(struct domain); + if ( d != NULL ) + memset(d, 0, sizeof(struct domain)); + + return d; } void free_domain_struct(struct domain *d) { - NOT_YET(); + xfree(d); } +/* This is called by arch_final_setup_guest and do_boot_vcpu */ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *ctx) { NOT_YET(); - return 0; + return -EINVAL; } @@ -135,12 +196,17 @@ void dump_pageframe_info(struct domain * void context_switch(struct vcpu *prev, struct vcpu *next) { - NOT_YET(); + ASSERT(prev != next); + ASSERT(vcpu_runnable(next)); + + prev = switch_to(prev, &prev->arch.ctx, &next->arch.ctx); } void continue_running(struct vcpu *same) { NOT_YET(); + + return ; } void sync_lazy_execstate_cpu(unsigned int cpu) @@ -168,6 +234,24 @@ void relinquish_memory(struct domain *d, NOT_YET(); } +void trace_domheap_pages(const char *caption, struct domain *d, struct list_head *list) +{ + struct list_head *ent; + struct page_info *page; + + /* Use a recursive lock, as we may enter 'free_domheap_page'. */ + spin_lock_recursive(&d->page_alloc_lock); + + ent = list->next; + while ( ent != list ) + { + page = list_entry(ent, struct page_info, list); + ent = ent->next; + } + + spin_unlock_recursive(&d->page_alloc_lock); +} + int domain_relinquish_resources(struct domain *d) { NOT_YET(); @@ -177,7 +261,16 @@ int domain_relinquish_resources(struct d void startup_cpu_idle_loop(void) { - NOT_YET(); + while(1) { + if (cpu_is_haltable(smp_processor_id())) { + local_irq_disable(); + cpu_idle(); + local_irq_enable(); + } + + do_tasklet(); + do_softirq(); + } } long arch_do_vcpu_op(int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg) @@ -189,22 +282,33 @@ long arch_do_vcpu_op(int cmd, struct vcp void vcpu_kick(struct vcpu *v) { - NOT_YET(); + bool_t running = v->is_running; + + vcpu_unblock(v); + + if (running && (in_irq() || (v != current))) { + cpu_raise_softirq(v->processor, VCPU_KICK_SOFTIRQ); + } } void vcpu_mark_events_pending(struct vcpu *v) { - NOT_YET(); + int already = test_and_set_bit(0, (unsigned long *)&vcpu_info(v, evtchn_upcall_pending)); + + if (already) { + return; + } + + vcpu_kick(v); } static void vcpu_kick_softirq(void) { - NOT_YET(); } static int __init vcpu_kick_softirq_init(void) { - NOT_YET(); + open_softirq(VCPU_KICK_SOFTIRQ, vcpu_kick_softirq); return 0; } diff -r 08f39a9da04f xen/arch/arm/xen/armv7.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/arm/xen/armv7.S Sun Feb 12 11:46:32 2012 +0900 @@ -0,0 +1,19 @@ +#include <asm/page.h> +#include <asm/cpu-ops.h> +#include <asm/system.h> +#include <asm/asm-macros.h> +#include <asm/asm-offsets.h> +#include <public/arch-arm.h> + + .text +ENTRY(cpu_idle) + dsb + wfi + mov pc, lr + +ENTRY(cpu_halt) + mov pc, lr + +ENTRY(cpu_reset) + mov pc, lr + diff -r 08f39a9da04f xen/arch/arm/xen/domain_build.c --- a/xen/arch/arm/xen/domain_build.c Mon Feb 06 11:17:01 2012 +0900 +++ b/xen/arch/arm/xen/domain_build.c Sun Feb 12 11:46:32 2012 +0900 @@ -33,6 +33,67 @@ #include <public/xen.h> #include <public/version.h> +extern void return_to_guest(); + +void vcpu_context_init(struct vcpu *v, unsigned long stk, unsigned long pc, struct start_info *si) +{ + void *stack; + struct cpu_info *ci; + struct cpu_ctx *cpu_ctx; + + stack = alloc_xenheap_pages(STACK_ORDER, 0); + if(stack == NULL) { + return; + } + + ci = (struct cpu_info *)stack; + ci->vcpu = v; + ci->vsp = 0; + ci->vspsr = PSR_MODE_SVC; + ci->vdacr = DACR_STAT_SVC; + + stack += (STACK_SIZE - sizeof(struct cpu_ctx)); + + cpu_ctx = (struct cpu_ctx *)stack; + cpu_ctx->r0 = 0; + cpu_ctx->r12 = (unsigned long)si; + cpu_ctx->usp = stk; + cpu_ctx->ulr = 0; + cpu_ctx->ssp = (unsigned long)(stack + sizeof(struct cpu_ctx)); + cpu_ctx->pc = pc; + cpu_ctx->spsr = 0x10; + + VCPU_REG(v, r13) = (unsigned long)stack; + VCPU_REG(v, r14) = (unsigned long)return_to_guest; + + VCPU_REG(v, dacr) = DACR_STAT_SVC; + VCPU_REG(v, fcseidr) = 0; + VCPU_REG(v, contextidr) = 0; + VCPU_REG(v, cpar) = (0x40) | (1 << 13); +} + +#define DOM_PFN_ALIGN (SECTION_SIZE >> PAGE_SHIFT) + +static unsigned long alloc_domain_pages(struct domain *d, unsigned int size) +{ + unsigned phys; + unsigned long pages = size >> PAGE_SHIFT; + + d->max_pages = ~(0x0UL); + + phys = alloc_boot_pages(pages, DOM_PFN_ALIGN); + + if (!phys) { + d->tot_pages = 0; + return 0; + } + + d->tot_pages = pages; + + /* Set Page Owner */ + return phys <<= PAGE_SHIFT; +} + /* * domain_construct() should be always invoked in idle domain */ @@ -40,8 +101,132 @@ int domain_construct(struct domain *d, unsigned long img_start, unsigned long img_len, unsigned long dom_size, unsigned int vcpus) { - NOT_YET(); + int i, rc; + struct vcpu *v; + struct elf_binary elf; + struct elf_dom_parms parms; + struct start_info *si; + unsigned long vstart, vend, ventry; + unsigned long pstart, pend, pmap, len; - return -EINVAL; + l1e_t *gpt; + + BUG_ON(d == NULL); + BUG_ON(dom_size & ~SECTION_MASK); + + pstart = alloc_domain_pages(d, dom_size); + if (!pstart) { + return -ENOMEM; + } + + memcpy((pstart + dom_size - img_len), img_start, img_len); + img_start = pstart + dom_size - img_len; + + if ((rc = elf_init(&elf, img_start, img_len)) != 0) { + return rc; + } + + elf_parse_binary(&elf); + + if ((rc = elf_xen_parse(&elf, &parms)) != 0) { + return rc; + } + + d->vcpu = xmalloc_array(struct vcpu *, MAX_VIRT_CPUS); + if (!d->vcpu) { + return -ENOMEM; + } + + memset(d->vcpu, 0, MAX_VIRT_CPUS * sizeof(*d->vcpu)); + d->max_vcpus = MAX_VIRT_CPUS; + + for (i = 0; i < MAX_VIRT_CPUS; i++) { + d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1; + d->shared_info->vcpu_info[i].arch.cpsr = (VPSR_I_BIT | VPSR_F_BIT | VPSR_MODE_SVC); + } + + for (i = 0; i < vcpus; i++) { + if (alloc_vcpu(d, i, i) == NULL) { + return -ENOMEM; + } + } + + vstart = parms.virt_kstart & SECTION_MASK; + vend = round_up(parms.virt_kend, L1_TABLE_SIZE); + ventry = parms.virt_entry; + + len = vend - vstart; + + /* Guest page table is located in the end of vend */ + gpt = (l1e_t *)(pstart + len); + + /* Duplicate L1 page table */ + memcpy(gpt, xen_translation_table, L1_TABLE_SIZE); + + pmap = pstart; + pend = pmap + dom_size; + + + gpt = l1_linear_offset(gpt, vstart); + + /* Create 1:1 mapping */ + do { + *gpt = MK_L1E(pmap, L1E_TYPE_GUEST); + pmap += SECTION_SIZE; + } while(gpt++, pmap < pend); + + /* Activate guest address space to relocate guest image */ + mmu_switch_ttb(gpt & ~(0x4000 - 1)); + + elf.dest = (void *)ventry; + elf_load_binary(&elf); + + si = (struct start_info *)(vend + L1_TABLE_SIZE); + memset(si, 0, PAGE_SIZE); + + + si->nr_pages = d->tot_pages; + si->shared_info = virt_to_maddr(d->shared_info); + si->pt_base = vend; + si->nr_pt_frames = 4; + si->mfn_list = 0; + si->first_p2m_pfn = pstart >> PAGE_SHIFT; + si->flags = 0; + si->min_mfn = pstart >> PAGE_SHIFT; + + if (d->domain_id == 0) { + si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; + } + + v = d->vcpu[0]; + + VCPU_REG(v, ttbr0) = (unsigned long)gpt; + + mmu_switch_ttb(VCPU_REG(idle_vcpu[0], ttbr0)); + + vcpu_context_init(v, 0, ventry, si); + + v->is_initialised = 1; + clear_bit(_VPF_down, &v->pause_flags); + + rc = 0; + + /* DOM0 is permitted full I/O capabilities. */ + rc |= ioports_permit_access(dom0, 0, 0xFFFF); + rc |= iomem_permit_access(dom0, 0UL, ~0UL); + rc |= irqs_permit_access(dom0, 0, d->nr_pirqs - 1); + + return rc; } +int elf_sanity_check(const Elf_Ehdr *ehdr) +{ + if ( !IS_ELF(*ehdr) || + (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) || + (ehdr->e_type != ET_EXEC) ) { + printk("DOM0 image is not a Xen-compatible Elf image.\n"); + return 0; + } + + return 1; +} diff -r 08f39a9da04f xen/arch/arm/xen/mm.c --- a/xen/arch/arm/xen/mm.c Mon Feb 06 11:17:01 2012 +0900 +++ b/xen/arch/arm/xen/mm.c Sun Feb 12 11:46:32 2012 +0900 @@ -217,8 +217,6 @@ unsigned long alloc_page_tables(l1e_t *l return 0; } -// cache_clean_range(page, page + PAGE_SIZE, 0); - wire_page_tables(l1e, page); return page; diff -r 08f39a9da04f xen/include/asm-arm/current.h --- a/xen/include/asm-arm/current.h Mon Feb 06 11:17:01 2012 +0900 +++ b/xen/include/asm-arm/current.h Sun Feb 12 11:46:32 2012 +0900 @@ -27,6 +27,29 @@ #ifndef __ASSEMBLY__ struct vcpu; +struct cpu_ctx { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long usp; + unsigned long ulr; + unsigned long ssp; + unsigned long slr; + unsigned long pc; + unsigned long spsr; +}; + + struct cpu_info { struct vcpu *vcpu; unsigned long vspsr; diff -r 08f39a9da04f xen/include/asm-arm/domain.h --- a/xen/include/asm-arm/domain.h Mon Feb 06 11:17:01 2012 +0900 +++ b/xen/include/asm-arm/domain.h Sun Feb 12 11:46:32 2012 +0900 @@ -8,42 +8,8 @@ #include <asm/iommu.h> #include <public/arch-arm.h> -#if 0 -#define MAPHASH_ENTRIES 8 -#define MAPHASH_HASHFN(pfn) ((pfn) & (MAPHASH_ENTRIES-1)) -#define MAPHASHENT_NOTINUSE ((u16)~0U) - -struct vcpu_maphash { - struct vcpu_maphash_entry { - unsigned long pfn; - uint16_t idx; - uint16_t refcnt; - } hash[MAPHASH_ENTRIES]; -}__cacheline_aligned; - - -#define MAPCACHE_ORDER 8 -#define MAPCACHE_ENTRIES (1 << MAPCACHE_ORDER) - -struct mapcache { - /* The PTEs that provide the mappings, and a cursor into the array. */ - l2e_t *table; - unsigned int cursor; - - /* Protects map_domain_page(). */ - spinlock_t lock; - - /* Which mappings are in use, and which are garbage to reap next epoch? */ - unsigned long inuse[BITS_TO_LONGS(MAPCACHE_ENTRIES)]; - unsigned long garbage[BITS_TO_LONGS(MAPCACHE_ENTRIES)]; - - /* Lock-free per-VCPU hash of recently-used mappings. */ - struct vcpu_maphash vcpu_maphash[MAX_VIRT_CPUS]; -}__cacheline_aligned; -#endif struct arch_domain { -#if 0 /* I/O-port admin-specified access capabilities. */ struct rangeset *ioport_caps; @@ -51,8 +17,7 @@ struct arch_domain int *pirq_irq; unsigned long *pirq_eoi_map; - unsigned long pirq_eoi_map_mfn; -#endif + struct page_list_head relmem_list; }; @@ -61,7 +26,7 @@ struct arch_vcpu struct vcpu_guest_context ctx; } __cacheline_aligned; -//#define VCPU_REG(v, reg) v->arch.ctx.reg +#define VCPU_REG(v, reg) v->arch.ctx.reg #define return_reg(v) ((v)->arch.ctx.r0) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel