diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index 7c37a41054ec..eb0ee8b5fdd5 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -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 diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 0f4b2b52aeef..fef47a09a134 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -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. diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index ff1f28287b88..c4b1c2878497 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -163,8 +163,6 @@ ASSYM(PCB_STAR, offsetof(struct pcb, pcb_star)); 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); diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 9b12449ef196..15d3a7b7895c 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -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); diff --git a/sys/amd64/include/fpu.h b/sys/amd64/include/fpu.h index be1bdc6c5d7f..78d2fee2714d 100644 --- a/sys/amd64/include/fpu.h +++ b/sys/amd64/include/fpu.h @@ -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); diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index 80aff86eb685..153393ffc15b 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -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 diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index b37e252f2138..47ab4c63da18 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -1211,6 +1211,11 @@ acpi_set_resource(device_t dev, device_t child, int type, int rid, 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); } diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 1ea8f9572d6a..51e8f4948fbb 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -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); diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h index a654ad3e6c39..01ace723e501 100644 --- a/sys/i386/include/pcb.h +++ b/sys/i386/include/pcb.h @@ -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 diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index 57e0f4817b5a..cd04f2899735 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -447,25 +447,31 @@ psycho_attach(device_t dev) panic("%s: failed to set up memory rman", __func__); 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. */ diff --git a/sys/x86/acpica/acpi_wakeup.c b/sys/x86/acpica/acpi_wakeup.c index fb4698396db8..3d5e1fe37a77 100644 --- a/sys/x86/acpica/acpi_wakeup.c +++ b/sys/x86/acpica/acpi_wakeup.c @@ -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, int state) 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, int state) 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, int state) 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 }