xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
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

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).