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

评论

此博客中的热门博文

Linux/ARM Page Table Entry 属性设置分析

提交了30次才AC ---【附】POJ 2488解题报告

笔记