svn commit: r249855 - in projects/amd64_xen_pv/sys/amd64: amd64 xen
Cherry G. Mathew
cherry at FreeBSD.org
Wed Apr 24 19:47:00 UTC 2013
Author: cherry
Date: Wed Apr 24 19:47:00 2013
New Revision: 249855
URL: http://svnweb.freebsd.org/changeset/base/249855
Log:
Context switch now merges current userland VA into kernel context.
fpu context is handled during context switch.
ldt related assembler cruft removed - this is already implemented via call to xen_set_ldt()
userland tls register context is conditionally fixed up during context switch.
Approved by: gibbs(implicit)
Modified:
projects/amd64_xen_pv/sys/amd64/amd64/cpu_switch.S
projects/amd64_xen_pv/sys/amd64/xen/machdep.c
Modified: projects/amd64_xen_pv/sys/amd64/amd64/cpu_switch.S
==============================================================================
--- projects/amd64_xen_pv/sys/amd64/amd64/cpu_switch.S Wed Apr 24 19:41:21 2013 (r249854)
+++ projects/amd64_xen_pv/sys/amd64/amd64/cpu_switch.S Wed Apr 24 19:47:00 2013 (r249855)
@@ -77,8 +77,33 @@ ENTRY(cpu_throw)
LK btrl %eax,PM_ACTIVE(%rdx) /* clear old */
1:
movq TD_PCB(%rsi),%r8 /* newtd->td_pcb */
+#ifndef XEN
movq PCB_CR3(%r8),%rdx
movq %rdx,%cr3 /* new address space */
+#else
+ pushq %rsi
+ pushq %r8
+
+ /*
+ * On xen, the hypervisor loads %cr3 for us on return to
+ * userland. We use a separate "kernel space" for kernel mode,
+ * which is setup at boot time (see: pmap.c:pmap_bootstrap)
+ *
+ * We need to tell the hypervisor via xen_pt_user_switch()
+ * about the new user pmap. Additionally, we modify the kernel VA
+ * space by copying in the userland bits of the new pmap, in
+ * case the kernel needs to access them.
+ */
+
+ movq TD_PROC(%rsi), %rdx /* newproc */
+ movq P_VMSPACE(%rdx), %rdx
+ addq $VM_PMAP, %rdx
+ movq %rdx, %rdi
+ callq pmap_xen_userload
+
+ popq %r8
+ popq %rsi
+#endif
jmp swact
END(cpu_throw)
@@ -129,9 +154,25 @@ ctx_switch_xsave:
/* This is patched to xsaveopt if supported, see fpuinit_bsp1() */
xsave (%r8)
movq %rcx,%rdx
-2: smsw %ax
+2:
+#ifndef XEN
+ smsw %ax
orb $CR0_TS,%al
lmsw %ax
+#else
+ pushq %rdi
+ pushq %rsi
+ pushq %rdx
+ pushq %rax
+ pushq %r8
+ movq $1, %rdi
+ callq fpu_taskswitch
+ popq %r8
+ popq %rax
+ popq %rdx
+ popq %rsi
+ popq %rdi
+#endif
xorl %eax,%eax
movq %rax,PCPU(FPCURTHREAD)
3:
@@ -237,77 +278,12 @@ ld_ldt:
shrl $8,%eax
movb %al,7(%rdx)
#else
-#ifdef notyet_xenldt
- pushq %rdi
- pushq %rsi
- pushq %rdx
- pushq %r8
-
- /* Restore fs base in GDT */
- movl PCB_FSBASE(%r8), %eax
- movq %rsp, %rdx /* register_t tmp, %rdx == &tmp */
- subq $8, %rsp /* allocate tmp */
-
- /* Reconstruct the_segment_descriptor */
- movq $0, (%rdx) /* Zero it first */
- movw %ax, 2(%rdx) /* .base = %eax */
- shrl $16,%eax
- movb %al, 4(%rdx)
- shrl $8,%eax
- movb %al, 7(%rdx)
- movw $0xffff, (%rdx) /* limit = 0xfffff */
- movb $1, 6(%rdx)
- movb $1, %al /* p = 1 */
- shlb $2, %al
- orb $SEL_UPL, %al /* dpl = SEL_UPL */
- shlb $5, %al
- orb $SDT_MEMRWA, %al/* type = SDT_MEMRWA */
- movb %al, 5(%rdx)
- movb $0xc, %al
- orb %al, 6(%rdx) /* def32 = 1, gran = 1 */
-
- movq PCPU(FS32P), %rdi /* dte_ma */
- movq %rdx, %rsi /* dte_ptr */
- callq xen_set_descriptor
+ /* ldt is already loaded - see do_ldt: below */
- movq 16(%rsp), %r8 /* Restore caller saved %r8 */
-
- /* Restore gs base in GDT */
- movl PCB_GSBASE(%r8),%eax
- movq %rsp, %rdx /* register_t tmp, %rdx == &tmp */
- addq $8, %rdx /* allocate tmp */
-
- /* Reconstruct the_segment_descriptor */
- movq $0, (%rdx) /* Zero it first */
- movw %ax, 2(%rdx) /* .base = %eax */
- shrl $16,%eax
- movb %al, 4(%rdx)
- shrl $8,%eax
- movb %al, 7(%rdx)
- movw $0xffff, (%rdx) /* limit = 0xfffff */
- movb $1, 6(%rdx)
- movb $1, %al /* p = 1 */
- shlb $2, %al
- orb $SEL_UPL, %al /* dpl = SEL_UPL */
- shlb $5, %al
- orb $SDT_MEMRWA, %al/* type = SDT_MEMRWA */
- movb %al, 5(%rdx)
- movb $0xc, %al
- orb %al, 6(%rdx) /* def32 = 1, gran = 1 */
-
- movq PCPU(GS32P), %rdi /* dte_ma */
- movq %rdx, %rsi /* dte_ptr */
- callq xen_set_descriptor
-
- addq $8, %rsp /* De-allocate temp "variable" stackspace */
- /* XXX: Do hypervisor GS/FS update ? */
-
- popq %r8
- popq %rdx
- popq %rsi
- popq %rdi
-
-#endif
+ /*
+ * We setup user tls in xen_set_proc()
+ * as part of the context switch
+ */
#endif /* !XEN */
do_kthread:
/* Do we need to reload tss ? */
Modified: projects/amd64_xen_pv/sys/amd64/xen/machdep.c
==============================================================================
--- projects/amd64_xen_pv/sys/amd64/xen/machdep.c Wed Apr 24 19:41:21 2013 (r249854)
+++ projects/amd64_xen_pv/sys/amd64/xen/machdep.c Wed Apr 24 19:47:00 2013 (r249855)
@@ -176,7 +176,7 @@ setup_gdt(struct user_segment_descriptor
#endif /* 0 */
case GUFS32_SEL:
case GUGS32_SEL:
- case GUDATA_SEL: /* XXX: why def32 ? */
+ case GUDATA_SEL:
limit = 0xfffff;
type = SDT_MEMRWA;
dpl = SEL_UPL;
@@ -1364,6 +1364,31 @@ xen_set_proc(struct pcb *newpcb)
{
HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL),
(unsigned long) newpcb & ~0xFul);
+
+ if (!(curthread->td_pflags & TDP_KTHREAD)) { /* Only for user proc */
+ /* XXX: compat32 */
+ if (newpcb->pcb_flags & (PCB_32BIT | PCB_GS32BIT)) {
+ struct user_segment_descriptor gsd;
+ gsd = gdt[GUGS32_SEL];
+ USD_SETBASE(&gsd, newpcb->pcb_gsbase);
+ xen_set_descriptor((vm_paddr_t)PCPU_GET(gs32p), (void *)&gsd);
+
+ if (newpcb->pcb_flags & PCB_32BIT) {
+ gsd = gdt[GUFS32_SEL];
+ USD_SETBASE(&gsd, newpcb->pcb_fsbase);
+ xen_set_descriptor((vm_paddr_t)PCPU_GET(fs32p), (void *)&gsd);
+ }
+
+ } else {
+
+ HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL,
+ _ugssel);
+ HYPERVISOR_set_segment_base(SEGBASE_FS,
+ newpcb->pcb_fsbase);
+ HYPERVISOR_set_segment_base(SEGBASE_GS_USER,
+ newpcb->pcb_gsbase);
+ }
+ }
}
char *console_page;
More information about the svn-src-projects
mailing list