summaryrefslogtreecommitdiffstats
path: root/sys/amd64/acpica
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2010-08-02 17:35:00 +0000
committerjkim <jkim@FreeBSD.org>2010-08-02 17:35:00 +0000
commit79a57d111a564cdef116d6cf2c34b1842377129d (patch)
treeac5b6c35aff67637e32c04209fa5f534aa1806b7 /sys/amd64/acpica
parent0a86131c629fc0f57598850ae76df2002f261b3e (diff)
downloadFreeBSD-src-79a57d111a564cdef116d6cf2c34b1842377129d.zip
FreeBSD-src-79a57d111a564cdef116d6cf2c34b1842377129d.tar.gz
- Merge savectx2() with savectx() and struct xpcb with struct pcb. [1]
savectx() is only used for panic dump (dumppcb) and kdb (stoppcbs). Thus, saving additional information does not hurt and it may be even beneficial. Unfortunately, struct pcb has grown larger to accommodate more data. Move 512-byte long pcb_user_save to the end of struct pcb while I am here. - savectx() now saves FPU state unconditionally and copy it to the PCB of FPU thread if necessary. This gives panic dump and kdb a chance to take a look at the current FPU state even if the FPU is "supposedly" not used. - Resuming CPU now unconditionally reinitializes FPU. If the saved FPU state was irrelevant, it could be in an unknown state. Suggested by: bde [1]
Diffstat (limited to 'sys/amd64/acpica')
-rw-r--r--sys/amd64/acpica/acpi_switch.S95
-rw-r--r--sys/amd64/acpica/acpi_wakecode.S4
-rw-r--r--sys/amd64/acpica/acpi_wakeup.c27
3 files changed, 59 insertions, 67 deletions
diff --git a/sys/amd64/acpica/acpi_switch.S b/sys/amd64/acpica/acpi_switch.S
index 2ce5c02..d98df85 100644
--- a/sys/amd64/acpica/acpi_switch.S
+++ b/sys/amd64/acpica/acpi_switch.S
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
- * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
+ * Copyright (c) 2008-2010 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,6 @@
#include "assym.s"
#define WAKEUP_CTX(member) wakeup_ ## member - wakeup_ctx(%rdi)
-#define WAKEUP_PCB(member) PCB_ ## member(%r11)
-#define WAKEUP_XPCB(member) XPCB_ ## member(%r11)
ENTRY(acpi_restorecpu)
/* Switch to KPML4phys. */
@@ -49,7 +47,7 @@ ENTRY(acpi_restorecpu)
1:
/* Fetch PCB. */
- movq WAKEUP_CTX(xpcb), %r11
+ movq WAKEUP_CTX(pcb), %rsi
/* Force kernel segment registers. */
movl $KDSEL, %eax
@@ -62,16 +60,16 @@ ENTRY(acpi_restorecpu)
movw %ax, %gs
movl $MSR_FSBASE, %ecx
- movl WAKEUP_PCB(FSBASE), %eax
- movl 4 + WAKEUP_PCB(FSBASE), %edx
+ movl PCB_FSBASE(%rsi), %eax
+ movl 4 + PCB_FSBASE(%rsi), %edx
wrmsr
movl $MSR_GSBASE, %ecx
- movl WAKEUP_PCB(GSBASE), %eax
- movl 4 + WAKEUP_PCB(GSBASE), %edx
+ movl PCB_GSBASE(%rsi), %eax
+ movl 4 + PCB_GSBASE(%rsi), %edx
wrmsr
movl $MSR_KGSBASE, %ecx
- movl WAKEUP_XPCB(KGSBASE), %eax
- movl 4 + WAKEUP_XPCB(KGSBASE), %edx
+ movl PCB_KGSBASE(%rsi), %eax
+ movl 4 + PCB_KGSBASE(%rsi), %edx
wrmsr
/* Restore EFER. */
@@ -103,19 +101,20 @@ ENTRY(acpi_restorecpu)
wrmsr
/* Restore CR0 except for FPU mode. */
- movq WAKEUP_XPCB(CR0), %rax
+ movq PCB_CR0(%rsi), %rax
+ movq %rax, %rcx
andq $~(CR0_EM | CR0_TS), %rax
movq %rax, %cr0
/* Restore CR2 and CR4. */
- movq WAKEUP_XPCB(CR2), %rax
+ movq PCB_CR2(%rsi), %rax
movq %rax, %cr2
- movq WAKEUP_XPCB(CR4), %rax
+ movq PCB_CR4(%rsi), %rax
movq %rax, %cr4
/* Restore descriptor tables. */
- lidt WAKEUP_XPCB(IDT)
- lldt WAKEUP_XPCB(LDT)
+ lidt PCB_IDT(%rsi)
+ lldt PCB_LDT(%rsi)
#define SDT_SYSTSS 9
#define SDT_SYSBSY 11
@@ -123,48 +122,58 @@ ENTRY(acpi_restorecpu)
/* Clear "task busy" bit and reload TR. */
movq PCPU(TSS), %rax
andb $(~SDT_SYSBSY | SDT_SYSTSS), 5(%rax)
- movw WAKEUP_XPCB(TR), %ax
+ movw PCB_TR(%rsi), %ax
ltr %ax
#undef SDT_SYSTSS
#undef SDT_SYSBSY
/* Restore other callee saved registers. */
- movq WAKEUP_PCB(R15), %r15
- movq WAKEUP_PCB(R14), %r14
- movq WAKEUP_PCB(R13), %r13
- movq WAKEUP_PCB(R12), %r12
- movq WAKEUP_PCB(RBP), %rbp
- movq WAKEUP_PCB(RSP), %rsp
- movq WAKEUP_PCB(RBX), %rbx
+ movq PCB_R15(%rsi), %r15
+ movq PCB_R14(%rsi), %r14
+ movq PCB_R13(%rsi), %r13
+ movq PCB_R12(%rsi), %r12
+ movq PCB_RBP(%rsi), %rbp
+ movq PCB_RSP(%rsi), %rsp
+ movq PCB_RBX(%rsi), %rbx
/* Restore debug registers. */
- movq WAKEUP_PCB(DR0), %rax
+ movq PCB_DR0(%rsi), %rax
movq %rax, %dr0
- movq WAKEUP_PCB(DR1), %rax
+ movq PCB_DR1(%rsi), %rax
movq %rax, %dr1
- movq WAKEUP_PCB(DR2), %rax
+ movq PCB_DR2(%rsi), %rax
movq %rax, %dr2
- movq WAKEUP_PCB(DR3), %rax
+ movq PCB_DR3(%rsi), %rax
movq %rax, %dr3
- movq WAKEUP_PCB(DR6), %rax
+ movq PCB_DR6(%rsi), %rax
movq %rax, %dr6
- movq WAKEUP_PCB(DR7), %rax
+ movq PCB_DR7(%rsi), %rax
movq %rax, %dr7
- /* Restore FPU state. */
+#define __INITIAL_FPUCW__ 0x037f
+#define __INITIAL_MXCSR__ 0x1f80
+
+ /* Initialize FPU and restore state if necessary. */
+ fninit
+ movw $__INITIAL_FPUCW__, -2(%rsp)
+ fldcw -2(%rsp)
+ movl $__INITIAL_MXCSR__, -4(%rsp)
+ ldmxcsr -4(%rsp)
movq PCPU(FPCURTHREAD), %rax
testq %rax, %rax
je 1f
- fxrstor WAKEUP_PCB(USERFPU)
+ fxrstor PCB_USERFPU(%rsi)
1:
- /* Restore CR0 with FPU mode. */
- movq WAKEUP_XPCB(CR0), %rax
- movq %rax, %cr0
+#undef __INITIAL_FPUCW__
+#undef __INITIAL_MXCSR__
+
+ /* Reload CR0. */
+ movq %rcx, %cr0
/* Restore return address. */
- movq WAKEUP_PCB(RIP), %rax
+ movq PCB_RIP(%rsi), %rax
movq %rax, (%rsp)
/* Indicate the CPU is resumed. */
@@ -173,19 +182,3 @@ ENTRY(acpi_restorecpu)
ret
END(acpi_restorecpu)
-
-ENTRY(acpi_savecpu)
- /* Fetch XPCB and save CPU context. */
- movq %rdi, %r10
- call savectx2
- movq %r10, %r11
-
- /* Patch caller's return address and stack pointer. */
- movq (%rsp), %rax
- movq %rax, WAKEUP_PCB(RIP)
- movq %rsp, %rax
- movq %rax, WAKEUP_PCB(RSP)
-
- movl $1, %eax
- ret
-END(acpi_savecpu)
diff --git a/sys/amd64/acpica/acpi_wakecode.S b/sys/amd64/acpica/acpi_wakecode.S
index c8dfc38..6d55149 100644
--- a/sys/amd64/acpica/acpi_wakecode.S
+++ b/sys/amd64/acpica/acpi_wakecode.S
@@ -2,7 +2,7 @@
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
* Copyright (c) 2003 Peter Wemm
- * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
+ * Copyright (c) 2008-2010 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -265,7 +265,7 @@ wakeup_kpml4:
wakeup_ctx:
.quad 0
-wakeup_xpcb:
+wakeup_pcb:
.quad 0
wakeup_gdt:
.word 0
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c
index 982809b..6bdf658 100644
--- a/sys/amd64/acpica/acpi_wakeup.c
+++ b/sys/amd64/acpica/acpi_wakeup.c
@@ -2,7 +2,7 @@
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
* Copyright (c) 2003 Peter Wemm
- * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
+ * Copyright (c) 2008-2010 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,13 +66,12 @@ extern int acpi_resume_beep;
extern int acpi_reset_video;
#ifdef SMP
-extern struct xpcb **stopxpcbs;
+extern struct pcb **susppcbs;
#else
-static struct xpcb **stopxpcbs;
+static struct pcb **susppcbs;
#endif
-int acpi_restorecpu(struct xpcb *, vm_offset_t);
-int acpi_savecpu(struct xpcb *);
+int acpi_restorecpu(struct pcb *, vm_offset_t);
static void *acpi_alloc_wakeup_handler(void);
static void acpi_stop_beep(void *);
@@ -105,10 +104,10 @@ acpi_wakeup_ap(struct acpi_softc *sc, int cpu)
int apic_id = cpu_apic_ids[cpu];
int ms;
- WAKECODE_FIXUP(wakeup_xpcb, struct xpcb *, stopxpcbs[cpu]);
- WAKECODE_FIXUP(wakeup_gdt, uint16_t, stopxpcbs[cpu]->xpcb_gdt.rd_limit);
+ 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,
- stopxpcbs[cpu]->xpcb_gdt.rd_base);
+ susppcbs[cpu]->pcb_gdt.rd_base);
WAKECODE_FIXUP(wakeup_cpu, int, cpu);
/* do an INIT IPI: assert RESET */
@@ -245,7 +244,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
cr3 = rcr3();
load_cr3(KPML4phys);
- if (acpi_savecpu(stopxpcbs[0])) {
+ if (savectx(susppcbs[0])) {
#ifdef SMP
if (wakeup_cpus != 0 && suspend_cpus(wakeup_cpus) == 0) {
device_printf(sc->acpi_dev,
@@ -258,11 +257,11 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
- WAKECODE_FIXUP(wakeup_xpcb, struct xpcb *, stopxpcbs[0]);
+ WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
WAKECODE_FIXUP(wakeup_gdt, uint16_t,
- stopxpcbs[0]->xpcb_gdt.rd_limit);
+ susppcbs[0]->pcb_gdt.rd_limit);
WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
- stopxpcbs[0]->xpcb_gdt.rd_base);
+ susppcbs[0]->pcb_gdt.rd_base);
WAKECODE_FIXUP(wakeup_cpu, int, 0);
/* Call ACPICA to enter the desired sleep state */
@@ -332,9 +331,9 @@ acpi_alloc_wakeup_handler(void)
printf("%s: can't alloc wake memory\n", __func__);
return (NULL);
}
- stopxpcbs = malloc(mp_ncpus * sizeof(*stopxpcbs), M_DEVBUF, M_WAITOK);
+ susppcbs = malloc(mp_ncpus * sizeof(*susppcbs), M_DEVBUF, M_WAITOK);
for (i = 0; i < mp_ncpus; i++)
- stopxpcbs[i] = malloc(sizeof(**stopxpcbs), M_DEVBUF, M_WAITOK);
+ susppcbs[i] = malloc(sizeof(**susppcbs), M_DEVBUF, M_WAITOK);
return (wakeaddr);
}
OpenPOWER on IntegriCloud