xenarm代码片段注释
ENTRY(ret_to_user)
test_all_events:
disable_irq r1 @ ensure IRQs are disabled
bl get_irq_stat @ get softirq pending status
ldr r1, [r0, #OFFSET_SOFTIRQ_PENDING]@指针操作,返回值放到r0中
ldr r0, =0xffff
tst r1, r0 @ bit mask check is needed!!!
beq test_guest_events
enable_irq r1 @ sti @ r1.. ok??????
bl do_softirq
b test_all_events
/*
disable_irq r1
.macro disable_irq, temp
msr cpsr_c, #PSR_STATUS_I | PSR_MODE_SVC //只更改控制位0~8,禁止中断标志位
.endm
*/
ENTRY(test_guest_events)
vcpu r10 @从在xenheap中堆栈页的最下部分得到vcpu结构
ldr r11, [r10, #OFFSET_VCPU_INFO] @获得vcpu_info
ldrb r9, [r11, #OFFSET_EVTCHN_UPCALL_MASK] @r9为evtchn_upcall_mask
tst r9, #0xFF @如果r9为非零则,bne,否则,要处理upcall信息
bne restore @如果不为0,那么就b restore
ldrb r12, [r11, #OFFSET_EVTCHN_UPCALL_PENDING] @r12为evtchn_upcall_pending
tst r12, #0xFF
beq restore @如果为0,那么也 b restore 没有evtchn @如果r12仍然为0,那么说明没有guest events事件要处理
/*
.macro vcpu rd @通过这种方式得到vcpuinfo.STACK上面是context,下面是cpuinfo
ldr rd, =(~(STACK_SIZE - 1))
and rd, r13, rd
ldr rd, [rd]
.endm
*/
/*
* Send event to guest domain
* 操作的都是vcpu->arch.guest_context.内容
* 但是把domain_guest的信息全部保存在了vcpu->arch.guest_context.sysusrregs的vksp中
*/
ENTRY(do_upcall)
vcpu r10
ldr r11, [r10, #OFFSET_VCPU_INFO] @r11指向的是vcpu_info
add r10, r10, #(OFFSET_ARCH_VCPU + OFFSET_GUEST_CONTEXT) @r10指向了guest_context
@--------lr指向event_callback
ldr lr, [r10, #OFFSET_HYPERVISOR_CALLBACK] @ lr event_callback--
cmp lr, #0 @ 如果没有设置call back,那么就restore
beq restore
@--upcall_mask, 屏蔽掉evtchn
mov r9, #0x01
strb r9, [r11, #OFFSET_EVTCHN_UPCALL_MASK] @r11指向的是vcpu_info
@----------------------------------
mov r4, #PSR_MODE_SVC
str r4, [r10, #(OFFSET_SYS_REGS + OFFSET_VPSR)] @r10指向的是guest_context svc
@--将domain_context保存在vksp的下面
@ Load virtual kernel stack pointer
ldr r11, [r10, #(OFFSET_SYS_REGS + OFFSET_VKSP)] @r11指向guest_context指定的stack pointer--domain_stack ?
@ Align VKSP in 8-byte boundary
sub r12, r11, #S_FRAME_SIZE @ r12指向domain_context
tst r12, #4
bicne r12, r12, #4
tst r12, #4
1:
bne 1b
@ Update effective virtual kernel stack pointer.更新的vksp r12指向了新的stack top--这样便于保存信息
str r12, [r10, #(OFFSET_SYS_REGS + OFFSET_VKSP)]@改变stack了,stack top 距离原来的stack 有1个user regs
@ Create bounce frame in guest stack
@ 将domain_context的信息都保存在vksp下面的一个S_FRAME_SIZE区间中
ldmia sp!, {r0-r8}
stmia r12!, {r0-r8}
ldmia sp!, {r0-r8}
stmia r12!, {r0-r8}
@---------------------------------------------
sub r12, r12, #S_FRAME_SIZE @ r12重新指向vksp下面的位置,因为上面的4条指令,已经更改了它的位置
ldr r0, =.LCupcall
stmia r0, {r12,lr}
ldmia r0, {sp, lr}^ //lr = event_upcall 和sp=vksp
ldr r0, [r12, #S_CONTEXT] @ r0 context
ldr r1, [r12, #S_PSR] @ r1 psr
ldr r2, [r10, #(OFFSET_SYS_REGS + OFFSET_VFAR)] @r2 far
ldr r3, [r10, #(OFFSET_SYS_REGS + OFFSET_VFSR)] @r3 fsr
mov r7, #PSR_MODE_USR @user_mod -> r7
msr spsr, r7 @r7->spsr
ldr r5, =DOMAIN_KERNEL_VALUE
mcr p15, 0, r5, c3, c0, 0 @ Load DAC
movs pc, lr
ENTRY(restore)
@与swi放在一起看,会更清楚一些
@进入到guest的环境中
@将sp内容保存在数据结构vcpu context中,设置进入guest的一些寄存器c3 cpsr r0~r15.(原来的
guest信息全部保存在此?莫非是)
@将sp内容全部弹出
vcpu r4
add r5, r4, #(OFFSET_ARCH_VCPU + OFFSET_GUEST_CONTEXT)//r5保存了guest_context
ldr r1, [sp, #S_PSR] //r1 保存了psr 是 13 svc
and r3, r1, #PSR_MODE_MASK
str r3, [r5, #(OFFSET_SYS_REGS + OFFSET_VPS)]//保存spr到guest_context.sys_regs中
bic r1, r1, #PSR_MODE_MASK //位清除指令
orr r1, r1, #PSR_MODE_USR //0x10
cmp r3, #PSR_MODE_USR
ldreq r7, =DOMAIN_HYPERVISOR_VALUE
ldrne r7, =DOMAIN_KERNEL_VALUE
mcr p15, 0, r7, c3, c0, 0 @改变域控制
mrc p15, 0, r3, c2, c0, 0 @ arbitrary read of cp15
mov r3, r3 @ wait for completion
sub pc, pc, #4 @ flush instruction pipeline
@下面的操作sp指向的栈地址把原来存储的寄存器全部弹出了
ldr lr, [sp, #S_PC]! @ Get PC ?1
msr spsr, r1 @ save in spsr_svc user模式 ?2
ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr LDM DB 传送前地址-4 ^的作用是用户模式寄存器
mov r0, r0
add sp, sp, #S_FRAME_SIZE - S_PC @这里sp指针指向framesize后部
movs pc, lr @ return & move spsr_svc into cpsr ?4
test_all_events:
disable_irq r1 @ ensure IRQs are disabled
bl get_irq_stat @ get softirq pending status
ldr r1, [r0, #OFFSET_SOFTIRQ_PENDING]@指针操作,返回值放到r0中
ldr r0, =0xffff
tst r1, r0 @ bit mask check is needed!!!
beq test_guest_events
enable_irq r1 @ sti @ r1.. ok??????
bl do_softirq
b test_all_events
/*
disable_irq r1
.macro disable_irq, temp
msr cpsr_c, #PSR_STATUS_I | PSR_MODE_SVC //只更改控制位0~8,禁止中断标志位
.endm
*/
ENTRY(test_guest_events)
vcpu r10 @从在xenheap中堆栈页的最下部分得到vcpu结构
ldr r11, [r10, #OFFSET_VCPU_INFO] @获得vcpu_info
ldrb r9, [r11, #OFFSET_EVTCHN_UPCALL_MASK] @r9为evtchn_upcall_mask
tst r9, #0xFF @如果r9为非零则,bne,否则,要处理upcall信息
bne restore @如果不为0,那么就b restore
ldrb r12, [r11, #OFFSET_EVTCHN_UPCALL_PENDING] @r12为evtchn_upcall_pending
tst r12, #0xFF
beq restore @如果为0,那么也 b restore 没有evtchn @如果r12仍然为0,那么说明没有guest events事件要处理
/*
.macro vcpu rd @通过这种方式得到vcpuinfo.STACK上面是context,下面是cpuinfo
ldr rd, =(~(STACK_SIZE - 1))
and rd, r13, rd
ldr rd, [rd]
.endm
*/
/*
* Send event to guest domain
* 操作的都是vcpu->arch.guest_context.内容
* 但是把domain_guest的信息全部保存在了vcpu->arch.guest_context.sysusrregs的vksp中
*/
ENTRY(do_upcall)
vcpu r10
ldr r11, [r10, #OFFSET_VCPU_INFO] @r11指向的是vcpu_info
add r10, r10, #(OFFSET_ARCH_VCPU + OFFSET_GUEST_CONTEXT) @r10指向了guest_context
@--------lr指向event_callback
ldr lr, [r10, #OFFSET_HYPERVISOR_CALLBACK] @ lr event_callback--
cmp lr, #0 @ 如果没有设置call back,那么就restore
beq restore
@--upcall_mask, 屏蔽掉evtchn
mov r9, #0x01
strb r9, [r11, #OFFSET_EVTCHN_UPCALL_MASK] @r11指向的是vcpu_info
@----------------------------------
mov r4, #PSR_MODE_SVC
str r4, [r10, #(OFFSET_SYS_REGS + OFFSET_VPSR)] @r10指向的是guest_context svc
@--将domain_context保存在vksp的下面
@ Load virtual kernel stack pointer
ldr r11, [r10, #(OFFSET_SYS_REGS + OFFSET_VKSP)] @r11指向guest_context指定的stack pointer--domain_stack ?
@ Align VKSP in 8-byte boundary
sub r12, r11, #S_FRAME_SIZE @ r12指向domain_context
tst r12, #4
bicne r12, r12, #4
tst r12, #4
1:
bne 1b
@ Update effective virtual kernel stack pointer.更新的vksp r12指向了新的stack top--这样便于保存信息
str r12, [r10, #(OFFSET_SYS_REGS + OFFSET_VKSP)]@改变stack了,stack top 距离原来的stack 有1个user regs
@ Create bounce frame in guest stack
@ 将domain_context的信息都保存在vksp下面的一个S_FRAME_SIZE区间中
ldmia sp!, {r0-r8}
stmia r12!, {r0-r8}
ldmia sp!, {r0-r8}
stmia r12!, {r0-r8}
@---------------------------------------------
sub r12, r12, #S_FRAME_SIZE @ r12重新指向vksp下面的位置,因为上面的4条指令,已经更改了它的位置
ldr r0, =.LCupcall
stmia r0, {r12,lr}
ldmia r0, {sp, lr}^ //lr = event_upcall 和sp=vksp
ldr r0, [r12, #S_CONTEXT] @ r0 context
ldr r1, [r12, #S_PSR] @ r1 psr
ldr r2, [r10, #(OFFSET_SYS_REGS + OFFSET_VFAR)] @r2 far
ldr r3, [r10, #(OFFSET_SYS_REGS + OFFSET_VFSR)] @r3 fsr
mov r7, #PSR_MODE_USR @user_mod -> r7
msr spsr, r7 @r7->spsr
ldr r5, =DOMAIN_KERNEL_VALUE
mcr p15, 0, r5, c3, c0, 0 @ Load DAC
movs pc, lr
ENTRY(restore)
@与swi放在一起看,会更清楚一些
@进入到guest的环境中
@将sp内容保存在数据结构vcpu context中,设置进入guest的一些寄存器c3 cpsr r0~r15.(原来的
guest信息全部保存在此?莫非是)
@将sp内容全部弹出
vcpu r4
add r5, r4, #(OFFSET_ARCH_VCPU + OFFSET_GUEST_CONTEXT)//r5保存了guest_context
ldr r1, [sp, #S_PSR] //r1 保存了psr 是 13 svc
and r3, r1, #PSR_MODE_MASK
str r3, [r5, #(OFFSET_SYS_REGS + OFFSET_VPS)]//保存spr到guest_context.sys_regs中
bic r1, r1, #PSR_MODE_MASK //位清除指令
orr r1, r1, #PSR_MODE_USR //0x10
cmp r3, #PSR_MODE_USR
ldreq r7, =DOMAIN_HYPERVISOR_VALUE
ldrne r7, =DOMAIN_KERNEL_VALUE
mcr p15, 0, r7, c3, c0, 0 @改变域控制
mrc p15, 0, r3, c2, c0, 0 @ arbitrary read of cp15
mov r3, r3 @ wait for completion
sub pc, pc, #4 @ flush instruction pipeline
@下面的操作sp指向的栈地址把原来存储的寄存器全部弹出了
ldr lr, [sp, #S_PC]! @ Get PC ?1
msr spsr, r1 @ save in spsr_svc user模式 ?2
ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr LDM DB 传送前地址-4 ^的作用是用户模式寄存器
mov r0, r0
add sp, sp, #S_FRAME_SIZE - S_PC @这里sp指针指向framesize后部
movs pc, lr @ return & move spsr_svc into cpsr ?4
评论
发表评论