svn commit: r210514 - in head/sys/amd64: acpica amd64

Jung-uk Kim jkim at FreeBSD.org
Mon Jul 26 19:53:10 UTC 2010


Author: jkim
Date: Mon Jul 26 19:53:09 2010
New Revision: 210514
URL: http://svn.freebsd.org/changeset/base/210514

Log:
  Re-implement FPU suspend/resume for amd64.  This removes superfluous uses
  of critical_enter(9) and critical_exit(9) by fpugetregs() and fpusetregs().
  Also, we do not touch PCB flags any more.
  
  MFC after:	1 month

Modified:
  head/sys/amd64/acpica/acpi_switch.S
  head/sys/amd64/acpica/acpi_wakeup.c
  head/sys/amd64/amd64/cpu_switch.S
  head/sys/amd64/amd64/genassym.c
  head/sys/amd64/amd64/mp_machdep.c

Modified: head/sys/amd64/acpica/acpi_switch.S
==============================================================================
--- head/sys/amd64/acpica/acpi_switch.S	Mon Jul 26 18:55:18 2010	(r210513)
+++ head/sys/amd64/acpica/acpi_switch.S	Mon Jul 26 19:53:09 2010	(r210514)
@@ -102,9 +102,12 @@ ENTRY(acpi_restorecpu)
 	movl	WAKEUP_CTX(sfmask), %eax
 	wrmsr
 
-	/* Restore CR0, CR2 and CR4. */
+	/* Restore CR0 except for FPU mode. */
 	movq	WAKEUP_XPCB(CR0), %rax
+	andq	$~(CR0_EM | CR0_TS), %rax
 	movq	%rax, %cr0
+
+	/* Restore CR2 and CR4. */
 	movq	WAKEUP_XPCB(CR2), %rax
 	movq	%rax, %cr2
 	movq	WAKEUP_XPCB(CR4), %rax
@@ -149,6 +152,17 @@ ENTRY(acpi_restorecpu)
 	movq	WAKEUP_PCB(DR7), %rax
 	movq	%rax, %dr7
 
+	/* Restore FPU state. */
+	movq	PCPU(FPCURTHREAD), %rax
+	testq	%rax, %rax
+	je	1f
+	fxrstor	WAKEUP_PCB(USER_FPU)
+1:
+
+	/* Restore CR0 with FPU mode. */
+	movq	WAKEUP_XPCB(CR0), %rax
+	movq	%rax, %cr0
+
 	/* Restore return address. */
 	movq	WAKEUP_PCB(RIP), %rax
 	movq	%rax, (%rsp)

Modified: head/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/amd64/acpica/acpi_wakeup.c	Mon Jul 26 18:55:18 2010	(r210513)
+++ head/sys/amd64/acpica/acpi_wakeup.c	Mon Jul 26 19:53:09 2010	(r210514)
@@ -216,7 +216,6 @@ acpi_wakeup_cpus(struct acpi_softc *sc, 
 int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
-	struct savefpu	*stopfpu;
 #ifdef SMP
 	cpumask_t	wakeup_cpus;
 #endif
@@ -246,10 +245,7 @@ acpi_sleep_machdep(struct acpi_softc *sc
 	cr3 = rcr3();
 	load_cr3(KPML4phys);
 
-	stopfpu = &stopxpcbs[0]->xpcb_pcb.pcb_user_save;
 	if (acpi_savecpu(stopxpcbs[0])) {
-		fpugetregs(curthread, stopfpu);
-
 #ifdef SMP
 		if (wakeup_cpus != 0 && suspend_cpus(wakeup_cpus) == 0) {
 			device_printf(sc->acpi_dev,
@@ -285,7 +281,6 @@ acpi_sleep_machdep(struct acpi_softc *sc
 		for (;;)
 			ia32_pause();
 	} else {
-		fpusetregs(curthread, stopfpu);
 #ifdef SMP
 		if (wakeup_cpus != 0)
 			acpi_wakeup_cpus(sc, wakeup_cpus);

Modified: head/sys/amd64/amd64/cpu_switch.S
==============================================================================
--- head/sys/amd64/amd64/cpu_switch.S	Mon Jul 26 18:55:18 2010	(r210513)
+++ head/sys/amd64/amd64/cpu_switch.S	Mon Jul 26 19:53:09 2010	(r210514)
@@ -417,6 +417,13 @@ ENTRY(savectx2)
 	leaq	(%rax,%rdx),%rax
 	movq	%rax,XPCB_KGSBASE(%r8)
 
+	movq	PCPU(FPCURTHREAD),%rax
+	testq	%rax,%rax
+	je	1f
+	clts
+	fxsave	PCB_USER_FPU(%r8)
+1:
+
 	movl	$1, %eax
 	ret
 END(savectx2)

Modified: head/sys/amd64/amd64/genassym.c
==============================================================================
--- head/sys/amd64/amd64/genassym.c	Mon Jul 26 18:55:18 2010	(r210513)
+++ head/sys/amd64/amd64/genassym.c	Mon Jul 26 19:53:09 2010	(r210514)
@@ -140,6 +140,7 @@ ASSYM(PCB_DR2, offsetof(struct pcb, pcb_
 ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
 ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
 ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
+ASSYM(PCB_USER_FPU, offsetof(struct pcb, pcb_user_save));
 ASSYM(PCB_TSSP, offsetof(struct pcb, pcb_tssp));
 ASSYM(PCB_FULL_IRET, offsetof(struct pcb, pcb_full_iret));
 ASSYM(PCB_DBREGS, PCB_DBREGS);

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c	Mon Jul 26 18:55:18 2010	(r210513)
+++ head/sys/amd64/amd64/mp_machdep.c	Mon Jul 26 19:53:09 2010	(r210514)
@@ -1329,20 +1329,17 @@ cpustop_handler(void)
 void
 cpususpend_handler(void)
 {
-	struct savefpu *stopfpu;
 	register_t cr3, rf;
 	int cpu = PCPU_GET(cpuid);
 	int cpumask = PCPU_GET(cpumask);
 
 	rf = intr_disable();
 	cr3 = rcr3();
-	stopfpu = &stopxpcbs[cpu]->xpcb_pcb.pcb_user_save;
+
 	if (savectx2(stopxpcbs[cpu])) {
-		fpugetregs(curthread, stopfpu);
 		wbinvd();
 		atomic_set_int(&stopped_cpus, cpumask);
-	} else
-		fpusetregs(curthread, stopfpu);
+	}
 
 	/* Wait for resume */
 	while (!(started_cpus & cpumask))


More information about the svn-src-all mailing list