All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Xu Zhang <xzhang54@uic.edu>
Cc: samuel.thibault@ens-lyon.org, stefano.stabellini@eu.citrix.com,
	Xu Zhang <xzhang@cs.uic.edu>,
	gm281@cam.ac.uk, xen-devel@lists.xen.org
Subject: Re: [PATCH 6/6] mini-os/x86-64 entry: check against nested events and try to fix up
Date: Wed, 13 Mar 2013 18:09:31 -0700	[thread overview]
Message-ID: <5141234B.9000801@goop.org> (raw)
In-Reply-To: <513FE798.7040409@uic.edu>

On 03/12/2013 07:42 PM, Xu Zhang wrote:
> On 03/09/2013 04:44 PM, Jeremy Fitzhardinge wrote:
>> On 03/08/2013 01:30 PM, Xu Zhang wrote:
>>> +# [How we do the fixup]. We want to merge the current stack frame
>>> with the
>>> +# just-interrupted frame. How we do this depends on where in the
>>> critical
>>> +# region the interrupted handler was executing, and so how many saved
>>> +# registers are in each frame. We do this quickly using the lookup
>>> table
>>> +# 'critical_fixup_table'. For each byte offset in the critical
>>> region, it
>>> +# provides the number of bytes which have already been popped from the
>>> +# interrupted stack frame. This is the number of bytes from the
>>> current stack
>>> +# that we need to copy at the end of the previous activation frame
>>> so that
>>> +# we can continue as if we've never even reached 11 running in the old
>>> +# activation frame.
>>> +critical_region_fixup:
>>> +        addq $critical_fixup_table - scrit, %rax
>>> +        movzbq (%rax),%rax    # %rax contains num bytes popped
>>> +        mov  %rsp,%rsi
>>> +        add  %rax,%rsi        # %esi points at end of src region
>>> +
>>> +        movq RSP(%rsp),%rdi   # acquire interrupted %rsp from
>>> current stack frame
>>> +                              # %edi points at end of dst region
>>> +        mov  %rax,%rcx
>>> +        shr  $3,%rcx          # convert bytes into count of 64-bit
>>> entities
>>> +        je   16f              # skip loop if nothing to copy
>>> +15:        subq $8,%rsi          # pre-decrementing copy loop
>>> +        subq $8,%rdi
>>> +        movq (%rsi),%rax
>>> +        movq %rax,(%rdi)
>>> +        loop 15b
>>> +16:        movq %rdi,%rsp        # final %rdi is top of merged stack
>>> +        andb $KERNEL_CS_MASK,CS(%rsp)      # CS on stack might have
>>> changed
>>> +        jmp  11b
>>> +
>>> +
>>> +/* Nested event fixup look-up table*/
>>> +critical_fixup_table:
>>> +    .byte 0x00,0x00,0x00                    # XEN_TEST_PENDING(%rsi)
>>> +    .byte 0x00,0x00,0x00,0x00,0x00,0x00     # jnz    14f
>>> +    .byte 0x00,0x00,0x00,0x00               # mov    (%rsp),%r15
>>> +    .byte 0x00,0x00,0x00,0x00,0x00          # mov    0x8(%rsp),%r14
>>> +    .byte 0x00,0x00,0x00,0x00,0x00          # mov    0x10(%rsp),%r13
>>> +    .byte 0x00,0x00,0x00,0x00,0x00          # mov    0x18(%rsp),%r12
>>> +    .byte 0x00,0x00,0x00,0x00,0x00          # mov    0x20(%rsp),%rbp
>>> +    .byte 0x00,0x00,0x00,0x00,0x00          # mov    0x28(%rsp),%rbx
>>> +    .byte 0x00,0x00,0x00,0x00               # add    $0x30,%rsp
>>> +    .byte 0x30,0x30,0x30,0x30               # mov    (%rsp),%r11
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x8(%rsp),%r10
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x10(%rsp),%r9
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x18(%rsp),%r8
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x20(%rsp),%rax
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x28(%rsp),%rcx
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x30(%rsp),%rdx
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x38(%rsp),%rsi
>>> +    .byte 0x30,0x30,0x30,0x30,0x30          # mov    0x40(%rsp),%rdi
>>> +    .byte 0x30,0x30,0x30,0x30               # add    $0x50,%rsp
>>> +    .byte 0x80,0x80,0x80,0x80               # testl 
>>> $NMI_MASK,2*8(%rsp)
>>> +    .byte 0x80,0x80,0x80,0x80
>>> +    .byte 0x80,0x80                         # jnz    2f
>>> +    .byte 0x80,0x80,0x80,0x80               # testb 
>>> $1,(xen_features+XENFEAT_supervisor_mode_kernel)
>>> +    .byte 0x80,0x80,0x80,0x80
>>> +    .byte 0x80,0x80                         # jnz    1f
>>> +    .byte 0x80,0x80,0x80,0x80,0x80          # orb    $3,1*8(%rsp)
>>> +    .byte 0x80,0x80,0x80,0x80,0x80          # orb    $3,4*8(%rsp)
>>> +    .byte 0x80,0x80                         # iretq
>>> +    .byte 0x80,0x80,0x80,0x80               # andl   $~NMI_MASK,
>>> 16(%rsp)
>>> +    .byte 0x80,0x80,0x80,0x80
>>> +    .byte 0x80,0x80                         # pushq  $\flag
>>> +    .byte 0x78,0x78,0x78,0x78,0x78          # jmp    hypercall_page
>>> + (__HYPERVISOR_iret * 32)
>>> +    .byte 0x00,0x00,0x00,0x00               #
>>> XEN_LOCKED_BLOCK_EVENTS(%rsi)
>>> +    .byte 0x00,0x00,0x00                    # mov    %rsp,%rdi
>>> +    .byte 0x00,0x00,0x00,0x00,0x00          # jmp    11b
>> This looks super-fragile.  The original Xen-linux kernel code had a
>> similar kind of fixup table, but I went to some lengths to make it as
>> simple and robust as possible in the pvops kernels.  See the comment in
>> xen-asm_32.S:
>>
>>   * Because the nested interrupt handler needs to deal with the current
>>   * stack state in whatever form its in, we keep things simple by only
>>   * using a single register which is pushed/popped on the stack.
>>
>> 64-bit pvops Linux always uses the iret hypercall, so the issue is moot
>> there.  (In principle a nested kernel interrupt could avoid the iret,
>> but it wasn't obvious that the extra complexity was worth it.)
>>
>>      J
>>
>
> Thanks very much for you feedbacks.
>
> I guess the concern is that using a chunky look-up table like this is
> somewhat complicated and would be less easier to maintain? Samuel made
> some suggestions, making it less "fragile" to some extent:
>
> Also, it would be good to check against critical section size change, in
> case somebody e.g. changes a value, or a macro like XEN_PUT_VCPU_INFO.
> For instance, stuff right after the table:
>
>     .if (ecrit-scrit) != (critical_fixup_table_end -
> critical_fixup_table)
>     .error "The critical has changed, the fixup table needs updating"
>     .endif

That would catch some problems, but not all.  I worry that the whole
construction is too error-prone, and its too easy for some later
unsuspecting developer to come in and introduce a subtle bug that only
occurs under very particular timing conditions.

> I read through Xen-Linux 32bit implementation for this issue. If I
> understand it right, the use of look-up table is avoided by leaving
> RESTORE_ALL/REST out of the critical section. So when a nested event
> came, you always certain about the stack frame layout and how many
> bytes to copy over when fixing up (in Xen-Linux 32bit, PT_EIP/4 - 1).
> And the register that would be clobbered in order to read and write
> event mask (%eax in Xen-Linux 32bit case) shall be saved on stack.
> This time we only need to worry about this one register instead of
> many when fixing up the stack frame.

Right.

> Basically both approaches are correct to me and do the same job.
> Xen-Linux 32bit is definitely a more neat solution. However, one thing
> to notice is that mini-os x86 32bit also uses a fixup table.

I don't have mini-os in front of me at the moment, but I wouldn't be
surprised if the original Xen-Linux and mini-os share heritage in this area.

> I guess we could apply these patches as a temporary solution to make
> sure everything is correct and consistent, and having following
> patches to do the refinement.

That makes sense to me if the refinement is a large amount of new work
on top of what you've already done, but I don't think that's obviously
true.  Given that you're familiar with the code and the problem domain,
I expect you could knock out a clean solution pretty quickly.

I guess you're interested in this path for 64-bit as well, because a
same ring-ring interrupt return is much more likely in minios.

    J

      parent reply	other threads:[~2013-03-14  1:09 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-08 21:30 [PATCH 0/6] mini-os: check and fix up against nested events in x86-64 kernel entry Xu Zhang
2013-03-08 21:30 ` [PATCH 1/6] mini-os/x86-64 entry: code clean-ups Xu Zhang
2013-03-09 20:57   ` Samuel Thibault
2013-03-08 21:30 ` [PATCH 2/6] mini-os/x86-64 entry: define macros for registers partial save and restore Xu Zhang
2013-03-09 20:55   ` Samuel Thibault
2013-03-08 21:30 ` [PATCH 3/6] mini-os/x86-64 entry: code refactoring; no functional changes Xu Zhang
2013-03-09 21:03   ` Samuel Thibault
2013-04-11  4:40     ` Xu Zhang
2013-03-08 21:30 ` [PATCH 4/6] mini-os/x86-64 entry: remove unnecessary event blocking Xu Zhang
2013-03-09 21:07   ` Samuel Thibault
2013-03-15 20:16   ` Konrad Rzeszutek Wilk
2013-04-11  4:40     ` Xu Zhang
2013-03-08 21:30 ` [PATCH 5/6] mini-os/x86-64 entry: defer RESTORE_REST until return Xu Zhang
2013-03-09 21:15   ` Samuel Thibault
2013-03-08 21:30 ` [PATCH 6/6] mini-os/x86-64 entry: check against nested events and try to fix up Xu Zhang
2013-03-09 21:19   ` Samuel Thibault
2013-03-13  2:42     ` Xu Zhang
2013-03-09 22:44   ` Jeremy Fitzhardinge
2013-03-13  2:42     ` Xu Zhang
2013-03-13  5:53       ` Xu Zhang
2013-03-14  1:09       ` Jeremy Fitzhardinge [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5141234B.9000801@goop.org \
    --to=jeremy@goop.org \
    --cc=gm281@cam.ac.uk \
    --cc=samuel.thibault@ens-lyon.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xen.org \
    --cc=xzhang54@uic.edu \
    --cc=xzhang@cs.uic.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.