Author: jhb
Date: Sat Sep  6 15:23:28 2014
New Revision: 271192
URL: http://svnweb.freebsd.org/changeset/base/271192

Log:
  Create a separate structure for per-CPU state saved across suspend and
  resume that is a superset of a pcb.  Move the FPU state out of the pcb and
  into this new structure.  As part of this, move the FPU resume code on
  amd64 into a C function.  This allows resumectx() to still operate only on
  a pcb and more closely mirrors the i386 code.
  
  Reviewed by:  kib (earlier version)

Modified:
  head/sys/amd64/amd64/cpu_switch.S
  head/sys/amd64/amd64/fpu.c
  head/sys/amd64/amd64/genassym.c
  head/sys/amd64/amd64/mp_machdep.c
  head/sys/amd64/include/fpu.h
  head/sys/amd64/include/pcb.h
  head/sys/dev/acpica/acpi.c
  head/sys/i386/i386/mp_machdep.c
  head/sys/i386/include/pcb.h
  head/sys/sparc64/pci/psycho.c
  head/sys/x86/acpica/acpi_wakeup.c

Modified: head/sys/amd64/amd64/cpu_switch.S
==============================================================================
--- head/sys/amd64/amd64/cpu_switch.S   Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/amd64/amd64/cpu_switch.S   Sat Sep  6 15:23:28 2014        
(r271192)
@@ -399,10 +399,6 @@ ENTRY(savectx)
        rdmsr
        movl    %eax,PCB_SFMASK(%rdi)
        movl    %edx,PCB_SFMASK+4(%rdi)
-       movl    xsave_mask,%eax
-       movl    %eax,PCB_XSMASK(%rdi)
-       movl    xsave_mask+4,%eax
-       movl    %eax,PCB_XSMASK+4(%rdi)
 
        sgdt    PCB_GDT(%rdi)
        sidt    PCB_IDT(%rdi)
@@ -467,12 +463,9 @@ ENTRY(resumectx)
        movl    PCB_SFMASK(%rdi),%eax
        wrmsr
 
-       /* Restore CR0 except for FPU mode. */
+       /* Restore CR0, CR2, CR4 and CR3. */
        movq    PCB_CR0(%rdi),%rax
-       andq    $~(CR0_EM | CR0_TS),%rax
        movq    %rax,%cr0
-
-       /* Restore CR2, CR4 and CR3. */
        movq    PCB_CR2(%rdi),%rax
        movq    %rax,%cr2
        movq    PCB_CR4(%rdi),%rax
@@ -510,26 +503,6 @@ ENTRY(resumectx)
        movq    PCB_DR7(%rdi),%rax
        movq    %rax,%dr7
 
-       /* Restore FPU state. */
-       fninit
-       movq    PCB_FPUSUSPEND(%rdi),%rbx
-       movq    PCB_XSMASK(%rdi),%rax
-       testq   %rax,%rax
-       jz      1f
-       movq    %rax,%rdx
-       shrq    $32,%rdx
-       movl    $XCR0,%ecx
-       xsetbv
-       xrstor  (%rbx)
-       jmp     2f
-1:
-       fxrstor (%rbx)
-2:
-
-       /* Reload CR0. */
-       movq    PCB_CR0(%rdi),%rax
-       movq    %rax,%cr0
-
        /* Restore other callee saved registers. */
        movq    PCB_R15(%rdi),%r15
        movq    PCB_R14(%rdi),%r14

Modified: head/sys/amd64/amd64/fpu.c
==============================================================================
--- head/sys/amd64/amd64/fpu.c  Sat Sep  6 15:15:06 2014        (r271191)
+++ head/sys/amd64/amd64/fpu.c  Sat Sep  6 15:23:28 2014        (r271192)
@@ -173,6 +173,20 @@ fpususpend(void *addr)
        load_cr0(cr0);
 }
 
+void
+fpuresume(void *addr)
+{
+       u_long cr0;
+
+       cr0 = rcr0();
+       stop_emulating();
+       fninit();
+       if (use_xsave)
+               load_xcr(XCR0, xsave_mask);
+       fpurestore(addr);
+       load_cr0(cr0);
+}
+
 /*
  * Enable XSAVE if supported and allowed by user.
  * Calculate the xsave_mask.

Modified: head/sys/amd64/amd64/genassym.c
==============================================================================
--- head/sys/amd64/amd64/genassym.c     Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/amd64/amd64/genassym.c     Sat Sep  6 15:23:28 2014        
(r271192)
@@ -163,8 +163,6 @@ ASSYM(PCB_STAR, offsetof(struct pcb, pcb
 ASSYM(PCB_LSTAR, offsetof(struct pcb, pcb_lstar));
 ASSYM(PCB_CSTAR, offsetof(struct pcb, pcb_cstar));
 ASSYM(PCB_SFMASK, offsetof(struct pcb, pcb_sfmask));
-ASSYM(PCB_XSMASK, offsetof(struct pcb, pcb_xsmask));
-ASSYM(PCB_FPUSUSPEND, offsetof(struct pcb, pcb_fpususpend));
 ASSYM(PCB_SIZE, sizeof(struct pcb));
 ASSYM(PCB_FULL_IRET, PCB_FULL_IRET);
 ASSYM(PCB_DBREGS, PCB_DBREGS);

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c   Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/amd64/amd64/mp_machdep.c   Sat Sep  6 15:23:28 2014        
(r271192)
@@ -102,7 +102,7 @@ char *nmi_stack;
 void *dpcpu;
 
 struct pcb stoppcbs[MAXCPU];
-struct pcb **susppcbs;
+struct susppcb **susppcbs;
 
 /* Variables needed for SMP tlb shootdown. */
 vm_offset_t smp_tlb_addr2;
@@ -1461,11 +1461,12 @@ cpususpend_handler(void)
        mtx_assert(&smp_ipi_mtx, MA_NOTOWNED);
 
        cpu = PCPU_GET(cpuid);
-       if (savectx(susppcbs[cpu])) {
-               fpususpend(susppcbs[cpu]->pcb_fpususpend);
+       if (savectx(&susppcbs[cpu]->sp_pcb)) {
+               fpususpend(susppcbs[cpu]->sp_fpususpend);
                wbinvd();
                CPU_SET_ATOMIC(cpu, &suspended_cpus);
        } else {
+               fpuresume(susppcbs[cpu]->sp_fpususpend);
                pmap_init_pat();
                initializecpu();
                PCPU_SET(switchtime, 0);

Modified: head/sys/amd64/include/fpu.h
==============================================================================
--- head/sys/amd64/include/fpu.h        Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/amd64/include/fpu.h        Sat Sep  6 15:23:28 2014        
(r271192)
@@ -58,6 +58,7 @@ int   fpuformat(void);
 int    fpugetregs(struct thread *td);
 void   fpuinit(void);
 void   fpurestore(void *addr);
+void   fpuresume(void *addr);
 void   fpusave(void *addr);
 int    fpusetregs(struct thread *td, struct savefpu *addr,
            char *xfpustate, size_t xfpustate_size);

Modified: head/sys/amd64/include/pcb.h
==============================================================================
--- head/sys/amd64/include/pcb.h        Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/amd64/include/pcb.h        Sat Sep  6 15:23:28 2014        
(r271192)
@@ -97,14 +97,18 @@ struct pcb {
        register_t      pcb_lstar;
        register_t      pcb_cstar;
        register_t      pcb_sfmask;
-       register_t      pcb_xsmask;
-
-       /* fpu context for suspend/resume */
-       void            *pcb_fpususpend;
 
        struct savefpu  *pcb_save;
 
-       uint64_t        pcb_pad[3];
+       uint64_t        pcb_pad[5];
+};
+
+/* Per-CPU state saved during suspend and resume. */
+struct susppcb {
+       struct pcb      sp_pcb;
+
+       /* fpu context for suspend/resume */
+       void            *sp_fpususpend;
 };
 #endif
 

Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c  Sat Sep  6 15:15:06 2014        (r271191)
+++ head/sys/dev/acpica/acpi.c  Sat Sep  6 15:23:28 2014        (r271192)
@@ -1211,6 +1211,11 @@ acpi_set_resource(device_t dev, device_t
                if (!(type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT))
 #endif
                {
+                   if (bootverbose)
+                       device_printf(dev,
+                           "Ignoring %s range %#lx-%#lx for %s\n",
+                           type == SYS_RES_MEMORY ? "memory" : "I/O",
+                           start, start + count - 1, acpi_name(ad->ad_handle));
                    AcpiOsFree(devinfo);
                    return (0);
                }

Modified: head/sys/i386/i386/mp_machdep.c
==============================================================================
--- head/sys/i386/i386/mp_machdep.c     Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/i386/i386/mp_machdep.c     Sat Sep  6 15:23:28 2014        
(r271192)
@@ -147,7 +147,7 @@ void *bootstacks[MAXCPU];
 static void *dpcpu;
 
 struct pcb stoppcbs[MAXCPU];
-struct pcb **susppcbs = NULL;
+struct susppcb **susppcbs;
 
 /* Variables needed for SMP tlb shootdown. */
 vm_offset_t smp_tlb_addr1;
@@ -1521,12 +1521,12 @@ cpususpend_handler(void)
        mtx_assert(&smp_ipi_mtx, MA_NOTOWNED);
 
        cpu = PCPU_GET(cpuid);
-       if (savectx(susppcbs[cpu])) {
-               npxsuspend(&susppcbs[cpu]->pcb_fpususpend);
+       if (savectx(&susppcbs[cpu]->sp_pcb)) {
+               npxsuspend(&susppcbs[cpu]->sp_fpususpend);
                wbinvd();
                CPU_SET_ATOMIC(cpu, &suspended_cpus);
        } else {
-               npxresume(&susppcbs[cpu]->pcb_fpususpend);
+               npxresume(&susppcbs[cpu]->sp_fpususpend);
                pmap_init_pat();
                PCPU_SET(switchtime, 0);
                PCPU_SET(switchticks, ticks);

Modified: head/sys/i386/include/pcb.h
==============================================================================
--- head/sys/i386/include/pcb.h Sat Sep  6 15:15:06 2014        (r271191)
+++ head/sys/i386/include/pcb.h Sat Sep  6 15:23:28 2014        (r271192)
@@ -90,8 +90,11 @@ struct pcb {
        struct region_descriptor pcb_idt;
        uint16_t        pcb_ldt;
        uint16_t        pcb_tr;
+};
 
-       union   savefpu pcb_fpususpend;
+struct susppcb {
+       struct pcb      sp_pcb;
+       union savefpu   sp_fpususpend;
 };
 
 #ifdef _KERNEL

Modified: head/sys/sparc64/pci/psycho.c
==============================================================================
--- head/sys/sparc64/pci/psycho.c       Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/sparc64/pci/psycho.c       Sat Sep  6 15:23:28 2014        
(r271192)
@@ -448,24 +448,30 @@ psycho_attach(device_t dev)
 
        i = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
        /*
-        * Make sure that the expected ranges are present.  The
-        * OFW_PCI_CS_MEM64 one is not currently used though.
-        */
-       if (i != PSYCHO_NRANGE)
-               panic("%s: unsupported number of ranges", __func__);
-       /*
         * Find the addresses of the various bus spaces.
         * There should not be multiple ones of one kind.
         * The physical start addresses of the ranges are the configuration,
         * memory and I/O handles.
         */
-       for (i = 0; i < PSYCHO_NRANGE; i++) {
+       for (; i >= 0; i--) {
                j = OFW_PCI_RANGE_CS(&range[i]);
                if (sc->sc_pci_bh[j] != 0)
                        panic("%s: duplicate range for space %d",
                            __func__, j);
                sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]);
        }
+
+       /*
+        * Make sure that the expected ranges are present.  The
+        * OFW_PCI_CS_MEM64 one is not currently used.
+        */
+       if (sc->sc_pci_bh[OFW_PCI_CS_CONFIG] == 0)
+               panic("%s: missing CONFIG range", __func__);
+       if (sc->sc_pci_bh[OFW_PCI_CS_IO] == 0)
+               panic("%s: missing IO range", __func__);
+       if (sc->sc_pci_bh[OFW_PCI_CS_MEM32] == 0)
+               panic("%s: missing MEM32 range", __func__);
+       
        free(range, M_OFWPROP);
 
        /* Register the softc, this is needed for paired Psychos. */

Modified: head/sys/x86/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/x86/acpica/acpi_wakeup.c   Sat Sep  6 15:15:06 2014        
(r271191)
+++ head/sys/x86/acpica/acpi_wakeup.c   Sat Sep  6 15:23:28 2014        
(r271192)
@@ -75,10 +75,10 @@ extern int          acpi_resume_beep;
 extern int             acpi_reset_video;
 
 #ifdef SMP
-extern struct pcb      **susppcbs;
+extern struct susppcb  **susppcbs;
 static cpuset_t                suspcpus;
 #else
-static struct pcb      **susppcbs;
+static struct susppcb  **susppcbs;
 #endif
 
 static void            *acpi_alloc_wakeup_handler(void);
@@ -117,14 +117,15 @@ acpi_stop_beep(void *arg)
 static int
 acpi_wakeup_ap(struct acpi_softc *sc, int cpu)
 {
+       struct pcb *pcb;
        int             vector = (WAKECODE_PADDR(sc) >> 12) & 0xff;
        int             apic_id = cpu_apic_ids[cpu];
        int             ms;
 
-       WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[cpu]);
-       WAKECODE_FIXUP(wakeup_gdt, uint16_t, susppcbs[cpu]->pcb_gdt.rd_limit);
-       WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
-           susppcbs[cpu]->pcb_gdt.rd_base);
+       pcb = &susppcbs[cpu]->sp_pcb;
+       WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
+       WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
+       WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);
 
        ipi_startup(apic_id, vector);
 
@@ -188,6 +189,7 @@ int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
        ACPI_STATUS     status;
+       struct pcb      *pcb;
 
        if (sc->acpi_wakeaddr == 0ul)
                return (-1);    /* couldn't alloc wake memory */
@@ -204,11 +206,12 @@ acpi_sleep_machdep(struct acpi_softc *sc
 
        intr_suspend();
 
-       if (savectx(susppcbs[0])) {
+       pcb = &susppcbs[0]->sp_pcb;
+       if (savectx(pcb)) {
 #ifdef __amd64__
-               fpususpend(susppcbs[0]->pcb_fpususpend);
+               fpususpend(susppcbs[0]->sp_fpususpend);
 #elif defined(DEV_NPX)
-               npxsuspend(&susppcbs[0]->pcb_fpususpend);
+               npxsuspend(&susppcbs[0]->sp_fpususpend);
 #endif
 #ifdef SMP
                if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) {
@@ -221,13 +224,11 @@ acpi_sleep_machdep(struct acpi_softc *sc
                WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
 
 #ifndef __amd64__
-               WAKECODE_FIXUP(wakeup_cr4, register_t, susppcbs[0]->pcb_cr4);
+               WAKECODE_FIXUP(wakeup_cr4, register_t, pcb->pcb_cr4);
 #endif
-               WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
-               WAKECODE_FIXUP(wakeup_gdt, uint16_t,
-                   susppcbs[0]->pcb_gdt.rd_limit);
-               WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
-                   susppcbs[0]->pcb_gdt.rd_base);
+               WAKECODE_FIXUP(wakeup_pcb, struct pcb *, pcb);
+               WAKECODE_FIXUP(wakeup_gdt, uint16_t, pcb->pcb_gdt.rd_limit);
+               WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t, pcb->pcb_gdt.rd_base);
 
                /* Call ACPICA to enter the desired sleep state */
                if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
@@ -244,8 +245,10 @@ acpi_sleep_machdep(struct acpi_softc *sc
                for (;;)
                        ia32_pause();
        } else {
-#ifdef DEV_NPX
-               npxresume(&susppcbs[0]->pcb_fpususpend);
+#ifdef __amd64__
+               fpuresume(susppcbs[0]->sp_fpususpend);
+#elif defined(DEV_NPX)
+               npxresume(&susppcbs[0]->sp_fpususpend);
 #endif
        }
 
@@ -325,7 +328,7 @@ acpi_alloc_wakeup_handler(void)
        for (i = 0; i < mp_ncpus; i++) {
                susppcbs[i] = malloc(sizeof(**susppcbs), M_DEVBUF, M_WAITOK);
 #ifdef __amd64__
-               susppcbs[i]->pcb_fpususpend = alloc_fpusave(M_WAITOK);
+               susppcbs[i]->sp_fpususpend = alloc_fpusave(M_WAITOK);
 #endif
        }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to