aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/arm/asm-offsets.c4
-rw-r--r--xen/arch/arm/domain.c113
-rw-r--r--xen/arch/arm/domain_build.c3
-rw-r--r--xen/arch/arm/entry.S16
-rw-r--r--xen/arch/arm/setup.c5
-rw-r--r--xen/include/asm-arm/current.h35
-rw-r--r--xen/include/asm-arm/domain.h21
-rw-r--r--xen/include/asm-arm/regs.h4
-rw-r--r--xen/include/asm-arm/system.h2
9 files changed, 101 insertions, 102 deletions
diff --git a/xen/arch/arm/asm-offsets.c b/xen/arch/arm/asm-offsets.c
index ee5d5d483e..cc1a72a659 100644
--- a/xen/arch/arm/asm-offsets.c
+++ b/xen/arch/arm/asm-offsets.c
@@ -7,6 +7,7 @@
#include <xen/config.h>
#include <xen/types.h>
+#include <xen/sched.h>
#include <public/xen.h>
#include <asm/current.h>
@@ -65,7 +66,10 @@ void __dummy__(void)
BLANK();
DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+
+ OFFSET(VCPU_arch_saved_context, struct vcpu, arch.saved_context);
}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 0b559343ad..a0b9d38740 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -44,7 +44,7 @@ void idle_loop(void)
static void ctxt_switch_from(struct vcpu *p)
{
-
+ context_saved(p);
}
static void ctxt_switch_to(struct vcpu *n)
@@ -52,52 +52,36 @@ static void ctxt_switch_to(struct vcpu *n)
p2m_load_VTTBR(n->domain);
}
-static void __context_switch(void)
+static void schedule_tail(struct vcpu *prev)
{
- struct cpu_user_regs *stack_regs = guest_cpu_user_regs();
- unsigned int cpu = smp_processor_id();
- struct vcpu *p = per_cpu(curr_vcpu, cpu);
- struct vcpu *n = current;
-
- ASSERT(p != n);
- ASSERT(cpumask_empty(n->vcpu_dirty_cpumask));
-
- if ( !is_idle_vcpu(p) )
- {
- memcpy(&p->arch.user_regs, stack_regs, CTXT_SWITCH_STACK_BYTES);
- ctxt_switch_from(p);
- }
+ /* Re-enable interrupts before restoring state which may fault. */
+ local_irq_enable();
- if ( !is_idle_vcpu(n) )
- {
- memcpy(stack_regs, &n->arch.user_regs, CTXT_SWITCH_STACK_BYTES);
- ctxt_switch_to(n);
- }
-
- per_cpu(curr_vcpu, cpu) = n;
+ ctxt_switch_from(prev);
+ /* TODO
+ update_runstate_area(current);
+ */
+ ctxt_switch_to(current);
}
-static void schedule_tail(struct vcpu *v)
+static void continue_new_vcpu(struct vcpu *prev)
{
- if ( is_idle_vcpu(v) )
- continue_idle_domain(v);
+ schedule_tail(prev);
+
+ if ( is_idle_vcpu(current) )
+ continue_idle_domain(current);
else
- continue_nonidle_domain(v);
+ continue_nonidle_domain(current);
}
void context_switch(struct vcpu *prev, struct vcpu *next)
{
- unsigned int cpu = smp_processor_id();
-
ASSERT(local_irq_is_enabled());
-
- printk("context switch %d:%d%s -> %d:%d%s\n",
- prev->domain->domain_id, prev->vcpu_id, is_idle_vcpu(prev) ? " (idle)" : "",
- next->domain->domain_id, next->vcpu_id, is_idle_vcpu(next) ? " (idle)" : "");
+ ASSERT(prev != next);
+ ASSERT(cpumask_empty(next->vcpu_dirty_cpumask));
/* TODO
- if (prev != next)
update_runstate_area(prev);
*/
@@ -105,60 +89,19 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
set_current(next);
- if ( (per_cpu(curr_vcpu, cpu) == next) ||
- (is_idle_vcpu(next) && cpu_online(cpu)) )
- {
- local_irq_enable();
- }
- else
- {
- __context_switch();
-
- /* Re-enable interrupts before restoring state which may fault. */
- local_irq_enable();
- }
-
- context_saved(prev);
-
- /* TODO
- if (prev != next)
- update_runstate_area(next);
- */
-
- schedule_tail(next);
- BUG();
+ prev = __context_switch(prev, next);
+ schedule_tail(prev);
}
void continue_running(struct vcpu *same)
{
- schedule_tail(same);
- BUG();
-}
-
-int __sync_local_execstate(void)
-{
- unsigned long flags;
- int switch_required;
-
- local_irq_save(flags);
-
- switch_required = (this_cpu(curr_vcpu) != current);
-
- if ( switch_required )
- {
- ASSERT(current == idle_vcpu[smp_processor_id()]);
- __context_switch();
- }
-
- local_irq_restore(flags);
-
- return switch_required;
+ /* Nothing to do */
}
void sync_local_execstate(void)
{
- (void)__sync_local_execstate();
+ /* Nothing to do -- no lazy switching */
}
void startup_cpu_idle_loop(void)
@@ -213,6 +156,18 @@ int vcpu_initialise(struct vcpu *v)
{
int rc = 0;
+ v->arch.stack = alloc_xenheap_pages(STACK_ORDER, MEMF_node(vcpu_to_node(v)));
+ if ( v->arch.stack == NULL )
+ return -ENOMEM;
+
+ v->arch.cpu_info = (struct cpu_info *)(v->arch.stack
+ + STACK_SIZE
+ - sizeof(struct cpu_info));
+
+ memset(&v->arch.saved_context, 0, sizeof(v->arch.saved_context));
+ v->arch.saved_context.sp = (uint32_t)v->arch.cpu_info;
+ v->arch.saved_context.pc = (uint32_t)continue_new_vcpu;
+
if ( (rc = vcpu_vgic_init(v)) != 0 )
return rc;
@@ -224,7 +179,7 @@ int vcpu_initialise(struct vcpu *v)
void vcpu_destroy(struct vcpu *v)
{
-
+ free_xenheap_pages(v->arch.stack, STACK_ORDER);
}
int arch_domain_create(struct domain *d, unsigned int domcr_flags)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index cbbc0b9562..9240209351 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -5,6 +5,7 @@
#include <xen/domain_page.h>
#include <xen/sched.h>
#include <asm/irq.h>
+#include <asm/regs.h>
#include "gic.h"
#include "kernel.h"
@@ -71,7 +72,7 @@ int construct_dom0(struct domain *d)
int rc;
struct vcpu *v = d->vcpu[0];
- struct cpu_user_regs *regs = &v->arch.user_regs;
+ struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
/* Sanity! */
BUG_ON(d->domain_id != 0);
diff --git a/xen/arch/arm/entry.S b/xen/arch/arm/entry.S
index 16a8f36c2c..d78115d536 100644
--- a/xen/arch/arm/entry.S
+++ b/xen/arch/arm/entry.S
@@ -105,3 +105,19 @@ ENTRY(return_to_hypervisor)
pop {r0-r12}
add sp, #(UREGS_R8_fiq - UREGS_sp); /* SP, LR, SPSR, PC */
eret
+
+/*
+ * struct vcpu *__context_switch(struct vcpu *prev, struct vcpu *next)
+ *
+ * r0 - prev
+ * r1 - next
+ *
+ * Returns prev in r0
+ */
+ENTRY(__context_switch)
+ add ip, r0, #VCPU_arch_saved_context
+ stmia ip!, {r4 - sl, fp, sp, lr} /* Save register state */
+
+ add r4, r1, #VCPU_arch_saved_context
+ ldmia r4, {r4 - sl, fp, sp, pc} /* Load registers and return */
+
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 4c1d89ceb1..4c0244cfaa 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -42,7 +42,7 @@
static unsigned int __initdata max_cpus = NR_CPUS;
/* Xen stack for bringing up the first CPU. */
-unsigned char init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE)));
+unsigned char __initdata init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE)));
extern char __init_begin[], __init_end[], __bss_start[];
@@ -61,7 +61,6 @@ static void __init init_idle_domain(void)
{
scheduler_init();
set_current(idle_vcpu[0]);
- this_cpu(curr_vcpu) = current;
/* TODO: setup_idle_pagetable(); */
}
@@ -175,7 +174,7 @@ void __init start_xen(unsigned long boot_phys_offset,
console_init_preirq();
#endif
- set_current((struct vcpu *)0xfffff000); /* debug sanity */
+ __set_current((struct vcpu *)0xfffff000); /* debug sanity */
idle_vcpu[0] = current;
set_processor_id(0); /* needed early, for smp_processor_id() */
diff --git a/xen/include/asm-arm/current.h b/xen/include/asm-arm/current.h
index 826efa56b8..72d494566b 100644
--- a/xen/include/asm-arm/current.h
+++ b/xen/include/asm-arm/current.h
@@ -5,49 +5,54 @@
#include <xen/percpu.h>
#include <public/xen.h>
+#include <asm/percpu.h>
+
#ifndef __ASSEMBLY__
struct vcpu;
+/*
+ * Which VCPU is "current" on this PCPU.
+ */
+DECLARE_PER_CPU(struct vcpu *, curr_vcpu);
+
struct cpu_info {
struct cpu_user_regs guest_cpu_user_regs;
unsigned long elr;
+ /* The following are valid iff this VCPU is current */
unsigned int processor_id;
- struct vcpu *current_vcpu;
unsigned long per_cpu_offset;
+ unsigned int pad;
};
static inline struct cpu_info *get_cpu_info(void)
{
- register unsigned long sp asm ("sp");
- return (struct cpu_info *)((sp & ~(STACK_SIZE - 1)) + STACK_SIZE - sizeof(struct cpu_info));
+ register unsigned long sp asm ("sp");
+ return (struct cpu_info *)((sp & ~(STACK_SIZE - 1)) + STACK_SIZE - sizeof(struct cpu_info));
}
-#define get_current() (get_cpu_info()->current_vcpu)
-#define set_current(vcpu) (get_cpu_info()->current_vcpu = (vcpu))
-#define current (get_current())
-
#define get_processor_id() (get_cpu_info()->processor_id)
#define set_processor_id(id) do { \
struct cpu_info *ci__ = get_cpu_info(); \
ci__->per_cpu_offset = __per_cpu_offset[ci__->processor_id = (id)]; \
} while (0)
+#define get_current() (this_cpu(curr_vcpu))
+#define __set_current(vcpu) (this_cpu(curr_vcpu) = (vcpu))
+#define set_current(vcpu) do { \
+ vcpu->arch.cpu_info->processor_id = get_processor_id(); \
+ __set_current(vcpu); \
+} while (0)
+#define current (get_current())
+
#define guest_cpu_user_regs() (&get_cpu_info()->guest_cpu_user_regs)
#define reset_stack_and_jump(__fn) \
__asm__ __volatile__ ( \
"mov sp,%0; b "STR(__fn) \
: : "r" (guest_cpu_user_regs()) : "memory" )
-#endif
-
-/*
- * Which VCPU's state is currently running on each CPU?
- * This is not necesasrily the same as 'current' as a CPU may be
- * executing a lazy state switch.
- */
-DECLARE_PER_CPU(struct vcpu *, curr_vcpu);
+#endif
#endif /* __ARM_CURRENT_H__ */
/*
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 3372d14a98..c1afd19f92 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -47,7 +47,26 @@ struct arch_domain
struct arch_vcpu
{
- struct cpu_user_regs user_regs;
+ struct {
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t sl;
+ uint32_t fp;
+ uint32_t sp;
+ uint32_t pc;
+ } saved_context;
+
+ void *stack;
+
+ /*
+ * Points into ->stack, more convenient than doing pointer arith
+ * all the time.
+ */
+ struct cpu_info *cpu_info;
uint32_t sctlr;
uint32_t ttbr0, ttbr1, ttbcr;
diff --git a/xen/include/asm-arm/regs.h b/xen/include/asm-arm/regs.h
index ee095bf467..54f6ed82ae 100644
--- a/xen/include/asm-arm/regs.h
+++ b/xen/include/asm-arm/regs.h
@@ -28,9 +28,7 @@
(diff == 0); \
})
-#define return_reg(v) ((v)->arch.user_regs.r0)
-
-#define CTXT_SWITCH_STACK_BYTES (sizeof(struct cpu_user_regs))
+#define return_reg(v) ((v)->arch.cpu_info->guest_cpu_user_regs.r0)
#endif /* __ARM_REGS_H__ */
/*
diff --git a/xen/include/asm-arm/system.h b/xen/include/asm-arm/system.h
index 731d89f600..7963ea5824 100644
--- a/xen/include/asm-arm/system.h
+++ b/xen/include/asm-arm/system.h
@@ -191,6 +191,8 @@ static inline int local_fiq_is_enabled(void)
return !!(flags & PSR_FIQ_MASK);
}
+extern struct vcpu *__context_switch(struct vcpu *prev, struct vcpu *next);
+
#endif
/*
* Local variables: