Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Aug 2006 15:32:27 GMT
From:      tkuik <tkuik@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 105332 for review
Message-ID:  <200608301532.k7UFWRjZ085220@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=105332

Change 105332 by tkuik@tkuik_freebsd on 2006/08/30 15:31:50

	Fixed problem where the fs & gs descriptors were not being updated
	during a thread context switch.  This problem caused the pthread
	library to not work properly under XEN.

Affected files ...

.. //depot/projects/xen3/src/sys/i386-xen/i386-xen/machdep.c#14 edit
.. //depot/projects/xen3/src/sys/i386-xen/i386-xen/xen_machdep.c#16 edit
.. //depot/projects/xen3/src/sys/i386/i386/swtch.s#4 edit
.. //depot/projects/xen3/src/sys/i386/i386/sys_machdep.c#5 edit
.. //depot/projects/xen3/src/sys/i386/i386/vm_machdep.c#6 edit

Differences ...

==== //depot/projects/xen3/src/sys/i386-xen/i386-xen/machdep.c#14 (text+ko) ====

@@ -2501,6 +2501,10 @@
 #endif
 	thread0.td_pcb->pcb_ext = 0;
 	thread0.td_frame = &proc0_tf;
+#ifdef XEN
+        thread0.td_pcb->pcb_fsd = PCPU_GET(fsgs_gdt)[0];
+        thread0.td_pcb->pcb_gsd = PCPU_GET(fsgs_gdt)[1];
+#endif
 }
 
 void

==== //depot/projects/xen3/src/sys/i386-xen/i386-xen/xen_machdep.c#16 (text+ko) ====

@@ -44,6 +44,7 @@
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
+#include <machine/pcb.h>
 #include <machine/stdarg.h>
 #include <machine/xenvar.h>
 #include <machine/xenfunc.h>
@@ -78,6 +79,7 @@
 void ni_cli(void);
 void ni_sti(void);
 
+
 void
 ni_cli(void)
 {
@@ -156,14 +158,14 @@
 printk(const char *fmt, ...)
 {
         __va_list ap;
-        int ret;
+        int retval;
         static char buf[PRINTK_BUFSIZE];
 
         va_start(ap, fmt);
-        ret = vsnprintf(buf, PRINTK_BUFSIZE - 1, fmt, ap);
+        retval = vsnprintf(buf, PRINTK_BUFSIZE - 1, fmt, ap);
         va_end(ap);
-        buf[ret] = 0;
-        (void)HYPERVISOR_console_write(buf, ret);
+        buf[retval] = 0;
+        (void)HYPERVISOR_console_write(buf, retval);
 }
 
 
@@ -1038,3 +1040,41 @@
 
 	panic("xen_failsafe_handler called!\n");
 }
+
+void xen_handle_thread_switch(struct pcb *pcb);
+
+/* This is called by cpu_switch() when switching threads. */
+/* The pcb arg refers to the process control block of the */
+/* next thread which is to run */
+void
+xen_handle_thread_switch(struct pcb *pcb)
+{
+    uint32_t *a = (uint32_t *)&PCPU_GET(fsgs_gdt)[0];
+    uint32_t *b = (uint32_t *)&pcb->pcb_fsd;
+    multicall_entry_t mcl[3];
+    int i = 0;
+
+    /* Notify Xen of task switch */
+    mcl[i].op = __HYPERVISOR_stack_switch;
+    mcl[i].args[0] = GSEL(GDATA_SEL, SEL_KPL);
+    mcl[i++].args[1] = (unsigned long)pcb;
+
+    /* Check for update of fsd */
+    if (*a != *b || *(a+1) != *(b+1)) {
+        mcl[i].op = __HYPERVISOR_update_descriptor;
+        *(uint64_t *)&mcl[i].args[0] = vtomach((vm_offset_t)a);
+        *(uint64_t *)&mcl[i++].args[2] = *(uint64_t *)b;
+    }    
+
+    a += 2;
+    b += 2;
+
+    /* Check for update of gsd */
+    if (*a != *b || *(a+1) != *(b+1)) {
+        mcl[i].op = __HYPERVISOR_update_descriptor;
+        *(uint64_t *)&mcl[i].args[0] = vtomach((vm_offset_t)a);
+        *(uint64_t *)&mcl[i++].args[2] = *(uint64_t *)b;
+    }    
+
+    (void)HYPERVISOR_multicall(mcl, i);
+}

==== //depot/projects/xen3/src/sys/i386/i386/swtch.s#4 (text+ko) ====

@@ -221,23 +221,7 @@
 	movl	%esi, 4(%ebx)
 	movl	$GPROC0_SEL*8, %esi		/* GSEL(GPROC0_SEL, SEL_KPL) */
 	ltr	%si
-#else
-	/* notify Xen of task switch */
-	pushl	%edx 				/* &pcb is the new stack base */
-	pushl	$KDSEL	 
-	pushl	$HYPERVISOR_STACK_SWITCH
-	call	ni_queue_multicall2 
-	addl	$12,%esp
-	/* XXX handle DOM0 IOPL case here (KMM)		*/
-	/* we currently don't support running FreeBSD	*/
-        /* in DOM0 so we can skip for now		*/ 
-	
-	call	ni_execute_multicall_list
-	
-#endif /* XEN */
 3:
-
-#ifndef XEN /* XXX skip updating selectors for the moment */
 	/* Copy the %fs and %gs selectors into this pcpu gdt */
 	leal	PCB_FSD(%edx), %esi
 	movl	PCPU(FSGS_GDT), %edi
@@ -249,7 +233,22 @@
 	movl	12(%esi), %ebx
 	movl	%eax, 8(%edi)
 	movl	%ebx, 12(%edi)
-#endif
+#else
+	/* Notify Xen of task switch and update fs/gs descriptors */
+	pushl	%eax
+	pushl	%ecx
+	pushl	%edx
+	call	xen_handle_thread_switch
+	popl	%edx
+	popl	%ecx
+	popl	%eax
+
+	/* XXX handle DOM0 IOPL case here (KMM)		*/
+	/* we currently don't support running FreeBSD	*/
+        /* in DOM0 so we can skip for now		*/ 
+	
+#endif /* XEN */
+	
 	/* Restore context. */
 	movl	PCB_EBX(%edx),%ebx
 	movl	PCB_ESP(%edx),%esp

==== //depot/projects/xen3/src/sys/i386/i386/sys_machdep.c#5 (text+ko) ====

@@ -182,12 +182,13 @@
 			critical_enter();
 #ifndef XEN
 			PCPU_GET(fsgs_gdt)[0] = sd;
+			td->td_pcb->pcb_fsd = sd;
 #else
 			sd.sd_lolimit = 0xc3f0;	/* < 4GB limit */
-			HYPERVISOR_update_descriptor(vtomach(&PCPU_GET(fsgs_gdt)[1]), 
+			HYPERVISOR_update_descriptor(vtomach(&PCPU_GET(fsgs_gdt)[0]), 
 						     *(uint64_t *)&sd);
+			td->td_pcb->pcb_fsd = PCPU_GET(fsgs_gdt)[0];
 #endif
-			td->td_pcb->pcb_fsd = sd;
 			critical_exit();
 			td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL);
 		}
@@ -219,12 +220,13 @@
 			critical_enter();
 #ifndef XEN
 			PCPU_GET(fsgs_gdt)[1] = sd;
+			td->td_pcb->pcb_gsd = sd;
 #else
 			sd.sd_lolimit = 0xc3f0;	/* 4GB limit, wraps around */
 			HYPERVISOR_update_descriptor(vtomach(&PCPU_GET(fsgs_gdt)[1]), 
 						     *(uint64_t *)&sd);
+			td->td_pcb->pcb_gsd = PCPU_GET(fsgs_gdt)[1];
 #endif
-			td->td_pcb->pcb_gsd = sd;
 			critical_exit();
 			load_gs(GSEL(GUGS_SEL, SEL_UPL));
 		}

==== //depot/projects/xen3/src/sys/i386/i386/vm_machdep.c#6 (text+ko) ====

@@ -503,7 +503,14 @@
 	/* set %gs */
 	td->td_pcb->pcb_gsd = sd;
 	if (td == curthread) {
+#ifndef XEN
 		PCPU_GET(fsgs_gdt)[1] = sd;
+#else
+                sd.sd_lolimit = 0xc3f0;	/* 4GB limit, wraps around */
+                HYPERVISOR_update_descriptor(vtomach(&PCPU_GET(fsgs_gdt)[1]), 
+                                             *(uint64_t *)&sd);
+                td->td_pcb->pcb_gsd = PCPU_GET(fsgs_gdt)[1];
+#endif
 		load_gs(GSEL(GUGS_SEL, SEL_UPL));
 	}
 	critical_exit();



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608301532.k7UFWRjZ085220>