PERFORCE change 105332 for review
tkuik
tkuik at FreeBSD.org
Wed Aug 30 15:32:30 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=105332
Change 105332 by tkuik at 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();
More information about the p4-projects
mailing list