Xen-ARM Guest DOM启动以及VCPU切换
/*
从hypervisor到DOM的转换比较复杂,简单的步骤有两个阶段:
1.将guest的contest的寄存器信息赋值,其中还包括一些DOM设置信息
2.调用scheduler通过__switch_to调度到设置的VCPU上
*/
------------hypervisor-------------
construct_guest_dom()
{
.....
new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start);
.....
}
void new_thread(struct vcpu *d, unsigned long start_pc, unsigned long start_stack, unsigned long start_info)
{
unsigned long *domain_stack;
struct cpu_info *ci;
struct cpu_user_regs *domain_context;
struct cpu_user_regs *regs = &d->arch.guest_context.user_regs;
domain_stack = alloc_xenheap_pages(STACK_ORDER);
if(domain_stack == NULL) {
return;
}
ci = (struct cpu_info *)domain_stack;
ci->cur_vcpu = d;
domain_stack += (STACK_SIZE - sizeof(struct cpu_user_regs))/sizeof(unsigned long);
domain_context = (struct cpu_user_regs *)domain_stack;
domain_context->r0 = 0;
domain_context->r12 = start_info;//参数传过来
domain_context->r13 = start_stack;
domain_context->r15 = start_pc;//DOM的启始地址
domain_context->psr = 0x13;
regs->r13 = (unsigned long)domain_stack;
regs->r14 = (unsigned long)ret_to_user;
}
调度VCPU代码:
open_softirq(SCHEDULE_SOFTIRQ, __enter_scheduler);
__enter_scheduler调用__switch_to,传给__switch_to的有三个参数:
#define switch_to(prev,next,last) \
do { \
__switch_to(prev,&prev->arch.guest_context, &next->arch.guest_context); \
} while (0)
ENTRY(__switch_to)
disable_irq ip @ ensure IRQs are disabled
add ip, r1, #(OFFSET_USER_REGS + OFFSET_R4)
save_ctx:
stmia ip, {r4 - sl, fp, ip, sp, lr} @ Store most regs on stack
mrc p15, 0, r4, c3, c0, 0
str r4, [r1, #(OFFSET_SYS_REGS + OFFSET_VDACR)]
load_ctx:
ldr r4, [r2, #(OFFSET_SYS_REGS + OFFSET_VDACR)]
mcr p15, 0, r4, c3, c0, 0
add ip, r2, #(OFFSET_USER_REGS + OFFSET_R4)
enable_irq r4
ldmia ip, {r4 - sl, fp, ip, sp, pc} @ Load all regs saved previously
@ mov pc, lr
nop
nop
b .
-------------dom--------------------
ENTRY(stext)
ldr r10, start_info //start_info的地址 -> r10
str r12, [r10] //r12的值 -> xen_start_info变量(start_info标记处)
ldr sp, __init_sp //sp->13
b start_kernel //进入Guest KERNEL
start_info:
.long xen_start_info
从hypervisor到DOM的转换比较复杂,简单的步骤有两个阶段:
1.将guest的contest的寄存器信息赋值,其中还包括一些DOM设置信息
2.调用scheduler通过__switch_to调度到设置的VCPU上
*/
------------hypervisor-------------
construct_guest_dom()
{
.....
new_thread(v, dsi.v_kernentry, vstack_end, vstartinfo_start);
.....
}
void new_thread(struct vcpu *d, unsigned long start_pc, unsigned long start_stack, unsigned long start_info)
{
unsigned long *domain_stack;
struct cpu_info *ci;
struct cpu_user_regs *domain_context;
struct cpu_user_regs *regs = &d->arch.guest_context.user_regs;
domain_stack = alloc_xenheap_pages(STACK_ORDER);
if(domain_stack == NULL) {
return;
}
ci = (struct cpu_info *)domain_stack;
ci->cur_vcpu = d;
domain_stack += (STACK_SIZE - sizeof(struct cpu_user_regs))/sizeof(unsigned long);
domain_context = (struct cpu_user_regs *)domain_stack;
domain_context->r0 = 0;
domain_context->r12 = start_info;//参数传过来
domain_context->r13 = start_stack;
domain_context->r15 = start_pc;//DOM的启始地址
domain_context->psr = 0x13;
regs->r13 = (unsigned long)domain_stack;
regs->r14 = (unsigned long)ret_to_user;
}
调度VCPU代码:
open_softirq(SCHEDULE_SOFTIRQ, __enter_scheduler);
__enter_scheduler调用__switch_to,传给__switch_to的有三个参数:
#define switch_to(prev,next,last) \
do { \
__switch_to(prev,&prev->arch.guest_context, &next->arch.guest_context); \
} while (0)
ENTRY(__switch_to)
disable_irq ip @ ensure IRQs are disabled
add ip, r1, #(OFFSET_USER_REGS + OFFSET_R4)
save_ctx:
stmia ip, {r4 - sl, fp, ip, sp, lr} @ Store most regs on stack
mrc p15, 0, r4, c3, c0, 0
str r4, [r1, #(OFFSET_SYS_REGS + OFFSET_VDACR)]
load_ctx:
ldr r4, [r2, #(OFFSET_SYS_REGS + OFFSET_VDACR)]
mcr p15, 0, r4, c3, c0, 0
add ip, r2, #(OFFSET_USER_REGS + OFFSET_R4)
enable_irq r4
ldmia ip, {r4 - sl, fp, ip, sp, pc} @ Load all regs saved previously
@ mov pc, lr
nop
nop
b .
-------------dom--------------------
ENTRY(stext)
ldr r10, start_info //start_info的地址 -> r10
str r12, [r10] //r12的值 -> xen_start_info变量(start_info标记处)
ldr sp, __init_sp //sp->13
b start_kernel //进入Guest KERNEL
start_info:
.long xen_start_info
评论
发表评论