From: Xu Zhang <xzhang@cs.uic.edu>
To: Samuel Thibault <samuel.thibault@ens-lyon.org>,
"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>,
gm281@cam.ac.uk
Subject: Re: Nested events in 64bit mini-OS
Date: Mon, 05 Nov 2012 23:56:04 -0600 [thread overview]
Message-ID: <5098A674.5090203@cs.uic.edu> (raw)
In-Reply-To: <20121025205653.GW5925@type.chello.at>
[-- Attachment #1: Type: text/plain, Size: 1337 bytes --]
Dear all,
I haven't seen any updates on this matter, so I try to come up with a
fix. Generally speaking, I want to mimic 32-bit mini-OS behaviour, adding:
1) a 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.
2) a fixup routine: obtain number of restored registers by quickly
looking up the fixup table and coalesce the current stack frame with the
just-interrupted one.
3) checks against re-entrance in hypervisor_callback
The "git diff" output is attached to this email. I only did some naive
"tests" by running it inside gdb. I am wondering is there a test suite
for mini-OS? A follow-up question is that given this fix, do you still
need hypercall iret?
Thank you very much.
Regards,
Xu Zhang
On 10/25/2012 03:56 PM, Samuel Thibault wrote:
> Xu Zhang, le Tue 23 Oct 2012 17:43:28 -0500, a écrit :
>> 64-bit mini-OS seems to adopt a mixed use of both (in HYPERVISOR_IRET).
>> mini-OS doesn't have an userspace, so unless an NMI happened, it always
>> perform interrupt/exception return with machine instruction iret, without
>> checking against nested events. This is wrong to me. Am I missing something
>> here?
> I don't think you are missing anything. Cc-ing Grzegorz, who actually
> wrote the code.
>
> Samuel
[-- Attachment #2: fixup.diff --]
[-- Type: text/x-patch, Size: 5515 bytes --]
diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index a65e5d5..b4f351c 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -42,8 +42,10 @@ hypercall_page:
NMI_MASK = 0x80000000
+#define RBX 40
#define RDI 112
#define ORIG_RAX 120 /* + error_code */
+#define RIP 128
#define EFLAGS 144
.macro RESTORE_ALL
@@ -147,7 +149,43 @@ error_call_handler:
ENTRY(hypervisor_callback)
- zeroentry hypervisor_callback2
+ movq (%rsp),%rcx
+ movq 8(%rsp),%r11
+ addq $0x10,%rsp /* skip rcx and r11 */
+ pushq $0 /* push error code/oldrax */
+ pushq %rax /* push real oldrax to the rdi slot */
+ leaq hypervisor_callback2(%rip), %rax
+
+ /* rdi slot contains rax, oldrax contains error code */
+ cld
+ subq $14*8,%rsp
+ movq %rsi,13*8(%rsp)
+ movq 14*8(%rsp),%rsi /* load rax from rdi slot */
+ movq %rdx,12*8(%rsp)
+ movq %rcx,11*8(%rsp)
+ movq %rsi,10*8(%rsp) /* store rax */
+ movq %r8, 9*8(%rsp)
+ movq %r9, 8*8(%rsp)
+ movq %r10,7*8(%rsp)
+ movq %r11,6*8(%rsp)
+ movq %rbx,5*8(%rsp)
+ movq %rbp,4*8(%rsp)
+ movq %r12,3*8(%rsp)
+ movq %r13,2*8(%rsp)
+ movq %r14,1*8(%rsp)
+ movq %r15,(%rsp)
+ movq %rdi, RDI(%rsp)
+
+ # check against re-entrance
+ movq RIP(%rsp),%rbx
+ cmpq $scrit,%rbx
+ jb 10f
+ cmpq $ecrit,%rbx
+ jb critical_region_fixup
+
+10: movq RBX(%rsp),%rbx # restore rbx
+ movq %rsp,%rdi
+ call *%rax
ENTRY(hypervisor_callback2)
movq %rdi, %rsp
@@ -172,17 +210,40 @@ scrit: /**** START OF CRITICAL REGION ****/
14: XEN_LOCKED_BLOCK_EVENTS(%rsi)
XEN_PUT_VCPU_INFO(%rsi)
- subq $6*8,%rsp
- movq %rbx,5*8(%rsp)
- movq %rbp,4*8(%rsp)
- movq %r12,3*8(%rsp)
- movq %r13,2*8(%rsp)
- movq %r14,1*8(%rsp)
- movq %r15,(%rsp)
- movq %rsp,%rdi # set the argument again
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rsp,%rdi # set the argument again
jmp 11b
ecrit: /**** END OF CRITICAL REGION ****/
+# [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.
+critical_region_fixup:
+ addq $critical_fixup_table - scrit, %rbx
+ movzbq (%rbx),%rbx # %rbx contains num bytes popped
+ mov %rsp,%rsi
+ add %rbx,%rsi # %esi points at end of src region
+ mov %rsp,%rdi
+ add $0xa8,%rdi # %edi points at end of dst region
+ mov %rbx,%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),%rbx
+ movq %rbx,(%rdi)
+ loop 15b
+16: movq %rdi,%rsp # final %rdi is top of merged stack
+ jmp 10b
retint_kernel:
retint_restore_args:
@@ -210,6 +271,42 @@ error_exit:
jmp retint_kernel
+critical_fixup_table:
+ .byte 0x30,0x30,0x30 # testb $0xff,(%rsi)
+ .byte 0x30,0x30 # jne 14f
+ .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 # jne 2f
+ .byte 0x80,0x80,0x80,0x80 # testb $1,(xen_features+XENFEAT_supervisor_mode_kernel)
+ .byte 0x80,0x80,0x80,0x80
+ .byte 0x80,0x80 # jne 1f
+ .byte 0x80,0x80,0x80,0x80,0x80 # orb $0x3,0x8(%rsp)
+ .byte 0x80,0x80,0x80,0x80,0x80 # orb $0x3,0x20(%rsp)
+ .byte 0x80,0x80 # iretq
+ .byte 0x80,0x80,0x80,0x80 # andl $~NMI_MASK,0x10(%rsp)
+ .byte 0x80,0x80,0x80,0x80
+ .byte 0x80,0x80 # pushq $0x0
+ .byte 0x78,0x78,0x78,0x78,0x78 # jmp hypercall_page + (__HYPERVISOR_iret * 32)
+ .byte 0x30,0x30,0x30,0x30 # movb $0x1,0x1(%rsi)
+ .byte 0x30 # push %rbx
+ .byte 0x28 # push %rbp
+ .byte 0x20,0x20 # push %r12
+ .byte 0x18,0x18 # push %r13
+ .byte 0x10,0x10 # push %r14
+ .byte 0x08,0x08 # push %r15
+ .byte 0x00,0x00,0x00 # mov %rsp,%rdi
+ .byte 0x00,0x00,0x00,0x00,0x00 # jmpq 11b
+
ENTRY(failsafe_callback)
popq %rcx
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2012-11-06 5:56 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-23 22:43 Nested events in 64bit mini-OS Xu Zhang
2012-10-25 20:56 ` Samuel Thibault
2012-11-06 5:56 ` Xu Zhang [this message]
2012-11-10 13:52 ` Samuel Thibault
2012-11-11 15:36 ` Xu Zhang
2012-11-14 1:49 ` Xu Zhang
2012-11-18 17:43 ` Samuel Thibault
2012-11-19 10:22 ` Ian Campbell
2012-11-19 10:21 ` Ian Campbell
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=5098A674.5090203@cs.uic.edu \
--to=xzhang@cs.uic.edu \
--cc=gm281@cam.ac.uk \
--cc=samuel.thibault@ens-lyon.org \
--cc=xen-devel@lists.xen.org \
/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.