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