[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [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@xxxxxxxxxxx>

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)
 

Attachment: patch07.diff
Description: Binary data

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.