All of lore.kernel.org
 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 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.