--
On Wed, 8 Aug 2007, Andi Kleen wrote:

> > If you were talking about the general iretq => INTERRUPT_RETURN, then the
> > answer is "Yes, they are sufficient". The first version of lguest ran the
> > guest kernel in ring 3 (using dual page tables for guest kernel and guest
> > user).  The current version I'm pushing runs lguest in ring 1, and the
> > entry.S code  worked for both.
>
> How do you implement system calls then?

/me working very hard to get lguest64 ready for public display

Here's a snippet from my version of core.c.  I've been thinking of ways to
optimize it, but for now it works fine. This was done for both ring 3 and
ring 1 lguest versions (this is the host running):


        /*
         * Update the LSTAR to point to the HV syscall handler.
         * Also update the fsbase if the guest uses one.
         */
        wrmsrl(MSR_LSTAR, (unsigned long)HV_OFFSET(&lguest_syscall_trampoline));

[...]
        asm volatile ("pushq %2; pushq %%rsp; pushfq; pushq %3; call *%6;"
                      /* The stack we pushed is off by 8, due to the
previous pushq */
                      "addq $8, %%rsp"
                      : "=D"(foo), "=a"(bar)
                      : "i" (__KERNEL_DS), "i" (__KERNEL_CS), "0"
(vcpu->vcpu),
                        "1"(get_idt_table()),
                        "r" (sw_guest)
                      : "memory", "cc");

[...]
        /* restore old LSTAR */
        wrmsrl(MSR_LSTAR, vcpu->host_syscall);



Also in the switcher.S (The Hypervisor):

.global lguest_syscall_trampoline
        .type lguest_syscall_trampoline, @function
lguest_syscall_trampoline:
        /*
         * Tricky, we don't have much to choose from here.
         * The only way to get to our stack is with swapgs.
         * but we need to save the stack too, so we have to play
         * very carefully.
         */
        swapgs
        /* now gs points to our VCPU Guest Data */

        /* first save the stack! */
        movq    %rsp, %gs:LGUEST_GUEST_DATA_regs_rsp

        /*
         * x86 arch doesn't have an easy way to find out where
         * gs is located. So we need to read the MSR. But first
         * we need to save off the rcx, rax and rdx.
         */
        movq    %rax, %gs:LGUEST_GUEST_DATA_regs_rax
        movq    %rdx, %gs:LGUEST_GUEST_DATA_regs_rdx
        movq    %rcx, %gs:LGUEST_GUEST_DATA_regs_rcx

        /* Need to read manual, does rdmsr clear
         * the top 32 bits of rax? */
        xor     %rax, %rax

        movl    $MSR_GS_BASE,%ecx
        rdmsr
        shl     $32, %rdx
        orq     %rax, %rdx

        movq    %rdx, %rsp

        /* see if we need to disable interrupts */
        testq   $(1<<9),  %gs:LGUEST_GUEST_DATA_SFMASK
        jz      1f
        movq    $0, %gs:LGUEST_GUEST_DATA_irq_enabled
        jmp     2f
1:
        /* Still need to clear bit 10 (just in case) */
        /*  (see lguest_iretq)                       */
        movq    $(1<<10), %rax
        not     %rax
        andq    %rax, %gs:LGUEST_GUEST_DATA_irq_enabled
2:
        /* put back the generic regs */
        movq    %gs:LGUEST_GUEST_DATA_regs_rdx, %rdx
        movq    %gs:LGUEST_GUEST_DATA_regs_rcx, %rcx
        movq    %gs:LGUEST_GUEST_DATA_regs_rax, %rax

        /* Is this a hypercall? */
        testq   $1, %gs:LGUEST_GUEST_DATA_is_hc
        jnz     handle_hcall

        /* We have 64 bytes to play with */
        addq    $LGUEST_GUEST_DATA_regs, %rsp

        /* do the swapgs if possible */
        testq   $1, %gs:LGUEST_GUEST_DATA_do_swapgs
        je      1f

        /* We now have a stack to use */
        /* go back to the guest's gs */
        swapgs
        DO_SWAPGS_USE_STACK
        /* and then back to HV gs */
        swapgs
1:
        /*
         * The stack has 64 bytes of playing room.
         * Which is enough to do a jump to the guest kernel.
         * We store the guest LSTAR register in the scatch pad
         * because we don't care if the guest messes with it.
         * If it is a bad address, we fault from the guest side
         * and we kill the guest. No harm done to the host.
         */
        pushq   $(__KERNEL_DS | 1)
        pushq   %gs:LGUEST_GUEST_DATA_regs_rsp
        pushfq
        /* Make sure we have actual interrupts on */
        orq     $(1<<9), 0(%rsp)
        pushq   $(__KERNEL_CS | 1)
        pushq   %gs:LGUEST_GUEST_DATA_LSTAR

        swapgs
        iretq



NOTE: This is still under development, since I'm going with a new design
change to try to stay more in sync with lguest32.

-- Steve

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization

Reply via email to