Beispiel #1
0
void __trace_hypercall_entry(void)
{
    struct cpu_user_regs *regs = guest_cpu_user_regs();
    unsigned long args[6];

    if ( is_pv_32bit_vcpu(current) )
    {
        args[0] = regs->ebx;
        args[1] = regs->ecx;
        args[2] = regs->edx;
        args[3] = regs->esi;
        args[4] = regs->edi;
        args[5] = regs->ebp;
    }
    else
    {
        args[0] = regs->rdi;
        args[1] = regs->rsi;
        args[2] = regs->rdx;
        args[3] = regs->r10;
        args[4] = regs->r8;
        args[5] = regs->r9;
    }

    __trace_hypercall(TRC_PV_HYPERCALL_V2, regs->eax, args);
}
Beispiel #2
0
static void __trace_multicall_call(multicall_entry_t *call)
{
    unsigned long args[6];
    int i;

    for ( i = 0; i < ARRAY_SIZE(args); i++ )
        args[i] = call->args[i];

    __trace_hypercall(TRC_PV_HYPERCALL_SUBCALL, call->op, args);
}
Beispiel #3
0
void pv_hypercall(struct cpu_user_regs *regs)
{
    struct vcpu *curr = current;
    unsigned long eax;

    ASSERT(guest_kernel_mode(curr, regs));

    eax = is_pv_32bit_vcpu(curr) ? regs->eax : regs->rax;

    BUILD_BUG_ON(ARRAY_SIZE(pv_hypercall_table) >
                 ARRAY_SIZE(hypercall_args_table));

    if ( (eax >= ARRAY_SIZE(pv_hypercall_table)) ||
         !pv_hypercall_table[eax].native )
    {
        regs->rax = -ENOSYS;
        return;
    }

    curr->hcall_preempted = false;

    if ( !is_pv_32bit_vcpu(curr) )
    {
        unsigned long rdi = regs->rdi;
        unsigned long rsi = regs->rsi;
        unsigned long rdx = regs->rdx;
        unsigned long r10 = regs->r10;
        unsigned long r8 = regs->r8;
        unsigned long r9 = regs->r9;

#ifndef NDEBUG
        /* Deliberately corrupt parameter regs not used by this hypercall. */
        switch ( hypercall_args_table[eax].native )
        {
        case 0: rdi = 0xdeadbeefdeadf00dUL;
        case 1: rsi = 0xdeadbeefdeadf00dUL;
        case 2: rdx = 0xdeadbeefdeadf00dUL;
        case 3: r10 = 0xdeadbeefdeadf00dUL;
        case 4: r8 = 0xdeadbeefdeadf00dUL;
        case 5: r9 = 0xdeadbeefdeadf00dUL;
        }
#endif
        if ( unlikely(tb_init_done) )
        {
            unsigned long args[6] = { rdi, rsi, rdx, r10, r8, r9 };

            __trace_hypercall(TRC_PV_HYPERCALL_V2, eax, args);
        }

        regs->rax = pv_hypercall_table[eax].native(rdi, rsi, rdx, r10, r8, r9);

#ifndef NDEBUG
        if ( !curr->hcall_preempted )
        {
            /* Deliberately corrupt parameter regs used by this hypercall. */
            switch ( hypercall_args_table[eax].native )
            {
            case 6: regs->r9  = 0xdeadbeefdeadf00dUL;
            case 5: regs->r8  = 0xdeadbeefdeadf00dUL;
            case 4: regs->r10 = 0xdeadbeefdeadf00dUL;
            case 3: regs->rdx = 0xdeadbeefdeadf00dUL;
            case 2: regs->rsi = 0xdeadbeefdeadf00dUL;
            case 1: regs->rdi = 0xdeadbeefdeadf00dUL;
            }
        }
#endif
    }
    else
    {
        unsigned int ebx = regs->ebx;
        unsigned int ecx = regs->ecx;
        unsigned int edx = regs->edx;
        unsigned int esi = regs->esi;
        unsigned int edi = regs->edi;
        unsigned int ebp = regs->ebp;

#ifndef NDEBUG
        /* Deliberately corrupt parameter regs not used by this hypercall. */
        switch ( hypercall_args_table[eax].compat )
        {
        case 0: ebx = 0xdeadf00d;
        case 1: ecx = 0xdeadf00d;
        case 2: edx = 0xdeadf00d;
        case 3: esi = 0xdeadf00d;
        case 4: edi = 0xdeadf00d;
        case 5: ebp = 0xdeadf00d;
        }
#endif

        if ( unlikely(tb_init_done) )
        {
            unsigned long args[6] = { ebx, ecx, edx, esi, edi, ebp };

            __trace_hypercall(TRC_PV_HYPERCALL_V2, eax, args);
        }

        curr->hcall_compat = true;
        regs->eax = pv_hypercall_table[eax].compat(ebx, ecx, edx, esi, edi, ebp);
        curr->hcall_compat = false;

#ifndef NDEBUG
        if ( !curr->hcall_preempted )
        {
            /* Deliberately corrupt parameter regs used by this hypercall. */
            switch ( hypercall_args_table[eax].compat )
            {
            case 6: regs->ebp = 0xdeadf00d;
            case 5: regs->edi = 0xdeadf00d;
            case 4: regs->esi = 0xdeadf00d;
            case 3: regs->edx = 0xdeadf00d;
            case 2: regs->ecx = 0xdeadf00d;
            case 1: regs->ebx = 0xdeadf00d;
            }
        }
#endif
    }

    /*
     * PV guests use SYSCALL or INT $0x82 to make a hypercall, both of which
     * have trap semantics.  If the hypercall has been preempted, rewind the
     * instruction pointer to reexecute the instruction.
     */
    if ( curr->hcall_preempted )
        regs->rip -= 2;

    perfc_incr(hypercalls);
}
Beispiel #4
0
static void __trace_multicall_call(multicall_entry_t *call)
{
    __trace_hypercall(TRC_PV_HYPERCALL_SUBCALL, call->op, call->args);
}