Add new IPI for saving CPU state explicitly, share high-level part of

ACPI wakeup code and teach it how to start the APs again. As a side
effect the CPU_START interface allows choosing between different
bootstrap codes more easily now.
This commit is contained in:
joerg 2007-12-18 07:17:08 +00:00
parent 49a3869ae1
commit 870cffb0ab
19 changed files with 450 additions and 630 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakecode.S,v 1.2 2007/12/09 20:27:42 jmcneill Exp $ */
/* $NetBSD: acpi_wakecode.S,v 1.3 2007/12/18 07:17:08 joerg Exp $ */
/*-
* Copyright (c) 2007 Joerg Sonnenberger <joerg@netbsd.org>
@ -73,8 +73,8 @@
#define _LOCORE
#include <machine/psl.h>
#include <machine/specialreg.h>
#include <machine/segments.h>
#include <machine/specialreg.h>
#define ACPI_WAKEUP_ADDR 0x3000
@ -175,8 +175,7 @@ wakeup_32:
/* Enable SYSCALL extension and Long Mode */
movl $MSR_EFER,%ecx
rdmsr
xorl %eax,%eax
orl $(EFER_LME|EFER_SCE),%eax
movl WAKEUP_msr_efer + ACPI_WAKEUP_ADDR,%eax
wrmsr
/* Load temporary PML4, code will switch to full PML4 later */
@ -199,12 +198,11 @@ wakeup_32:
.code64
wakeup_64:
/* Reload normal segment registers with correct values */
/* Reload data segment with default value */
movw $GSEL(GDATA_SEL, SEL_KPL),%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
movq WAKEUP_curcpu + ACPI_WAKEUP_ADDR,%r8
movq WAKEUP_restorecpu + ACPI_WAKEUP_ADDR,%rbx
/* Continue with wakeup in the high-level wakeup code */
@ -247,3 +245,8 @@ WAKEUP_restorecpu: .quad 0
WAKEUP_vbios_reset: .byte 0
.global WAKEUP_beep_on_reset
WAKEUP_beep_on_reset: .byte 0
.global WAKEUP_curcpu
WAKEUP_curcpu: .quad 0
.global WAKEUP_msr_efer
WAKEUP_msr_efer: .long 0

View File

@ -1,305 +0,0 @@
/* $NetBSD: acpi_wakeup.c,v 1.6 2007/12/15 11:26:40 joerg Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Takuya SHIOZAKI.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.6 2007/12/15 11:26:40 joerg Exp $");
/*-
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* FreeBSD: src/sys/i386/acpica/acpi_wakeup.c,v 1.9 2002/01/10 03:26:46 wes Exp
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <machine/bus.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <uvm/uvm_extern.h>
#include <uvm/uvm_page.h>
#include "ioapic.h"
#include "lapic.h"
#if NLAPIC > 0
#include <machine/i82489var.h>
#endif
#if NIOAPIC > 0
#include <machine/i82093var.h>
#endif
#include <machine/i8259.h>
#include "acpi.h"
#include <dev/ic/i8253reg.h>
#include <dev/acpi/acpica.h>
#include <dev/acpi/acpivar.h>
#define ACPI_MACHDEP_PRIVATE
#include <machine/acpi_machdep.h>
#include <machine/cpu.h>
#include <machine/fpu.h>
#include <machine/mtrr.h>
#include <x86/cpuvar.h>
#include "acpi_wakecode.h"
static paddr_t acpi_wakeup_paddr = 3 * PAGE_SIZE;
static vaddr_t acpi_wakeup_vaddr;
static int acpi_md_node = CTL_EOL;
static int acpi_md_vbios_reset = 1;
static int acpi_md_beep_on_reset = 1;
static int sysctl_md_acpi_vbios_reset(SYSCTLFN_ARGS);
static int sysctl_md_acpi_beep_on_reset(SYSCTLFN_ARGS);
/* XXX shut gcc up */
extern int acpi_md_sleep_prepare(int);
extern int acpi_md_sleep_exit(int);
void acpi_md_sleep_enter(int);
void
acpi_md_sleep_enter(int state)
{
#define WAKECODE_FIXUP(offset, type, val) do { \
type *addr; \
addr = (type *)(acpi_wakeup_vaddr + offset); \
*addr = val; \
} while (0)
#define WAKECODE_BCOPY(offset, type, val) do { \
void **addr; \
addr = (void **)(acpi_wakeup_vaddr + offset); \
bcopy(&(val), addr, sizeof(type)); \
} while (0)
ACPI_STATUS status;
paddr_t tmp_pdir;
tmp_pdir = pmap_init_tmp_pgtbl(acpi_wakeup_paddr);
/* Execute Sleep */
bcopy(wakecode, (void *)acpi_wakeup_vaddr, sizeof(wakecode));
WAKECODE_FIXUP(WAKEUP_vbios_reset, uint8_t, acpi_md_vbios_reset);
WAKECODE_FIXUP(WAKEUP_beep_on_reset, uint8_t, acpi_md_beep_on_reset);
WAKECODE_FIXUP(WAKEUP_r_cr3, uint64_t, tmp_pdir);
WAKECODE_FIXUP(WAKEUP_restorecpu, void *, acpi_md_sleep_exit);
ACPI_FLUSH_CPU_CACHE();
status = AcpiEnterSleepState(state);
if (ACPI_FAILURE(status)) {
printf("acpi: AcpiEnterSleepState failed: %s\n",
AcpiFormatException(status));
return;
}
for (;;) ;
#undef WAKECODE_FIXUP
#undef WAKECODE_BCOPY
}
int
acpi_md_sleep(int state)
{
int s, ret = 0;
KASSERT(acpi_wakeup_paddr != 0);
KASSERT(sizeof(wakecode) <= PAGE_SIZE);
if (ncpu > 1) {
printf("acpi: sleep is not supported on MP.\n");
return -1;
}
if (!CPU_IS_PRIMARY(curcpu())) {
printf("acpi0: WARNING: ignoring sleep from secondary CPU\n");
return -1;
}
AcpiSetFirmwareWakingVector(acpi_wakeup_paddr);
#ifdef MULTIPROCESSOR
/* Shutdown all other CPUs */
x86_broadcast_ipi(X86_IPI_HALT);
#endif
s = splipi();
fpusave_cpu(curcpu(), 1);
splx(s);
s = splhigh();
x86_disable_intr();
if (acpi_md_sleep_prepare(state))
goto out;
/* Execute Wakeup */
cpu_init_msrs(&cpu_info_primary, false);
fpuinit(&cpu_info_primary);
i8259_reinit();
#if NLAPIC > 0
lapic_enable();
lapic_set_lvt();
lapic_initclocks();
#endif
#if NIOAPIC > 0
ioapic_reenable();
#endif
initrtclock(TIMER_FREQ);
inittodr(time_second);
AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
out:
x86_enable_intr();
splx(s);
if (mtrr_funcs != NULL)
mtrr_commit();
return (ret);
}
void
acpi_md_sleep_init(void)
{
/* Map ACPI wakecode */
acpi_wakeup_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
UVM_KMF_VAONLY);
if (acpi_wakeup_vaddr == 0)
panic("acpi: can't allocate address for wakecode.\n");
pmap_kenter_pa(acpi_wakeup_vaddr, acpi_wakeup_paddr,
VM_PROT_READ | VM_PROT_WRITE);
pmap_update(pmap_kernel());
}
SYSCTL_SETUP(sysctl_md_acpi_setup, "acpi amd64 sysctl setup")
{
const struct sysctlnode *node;
const struct sysctlnode *ssnode;
if (sysctl_createv(NULL, 0, NULL, &node, CTLFLAG_PERMANENT,
CTLTYPE_NODE, "machdep", NULL, NULL, 0, NULL, 0, CTL_MACHDEP,
CTL_EOL) != 0)
return;
if (sysctl_createv(NULL, 0, &node, &ssnode, CTLFLAG_READWRITE,
CTLTYPE_INT, "acpi_vbios_reset", NULL, sysctl_md_acpi_vbios_reset,
0, NULL, 0, CTL_CREATE, CTL_EOL) != 0)
return;
if (sysctl_createv(NULL, 0, &node, &ssnode, CTLFLAG_READWRITE,
CTLTYPE_INT, "acpi_beep_on_reset", NULL, sysctl_md_acpi_beep_on_reset,
0, NULL, 0, CTL_CREATE, CTL_EOL) != 0)
return;
acpi_md_node = node->sysctl_num;
}
static int
sysctl_md_acpi_vbios_reset(SYSCTLFN_ARGS)
{
int error, t;
struct sysctlnode node;
node = *rnode;
t = acpi_md_vbios_reset;
node.sysctl_data = &t;
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
if (t < 0 || t > 1)
return EINVAL;
acpi_md_vbios_reset = t;
return 0;
}
static int
sysctl_md_acpi_beep_on_reset(SYSCTLFN_ARGS)
{
int error, t;
struct sysctlnode node;
node = *rnode;
t = acpi_md_beep_on_reset;
node.sysctl_data = &t;
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
if (t < 0 || t > 1)
return EINVAL;
acpi_md_beep_on_reset = t;
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakeup_low.S,v 1.2 2007/12/09 20:27:42 jmcneill Exp $ */
/* $NetBSD: acpi_wakeup_low.S,v 1.3 2007/12/18 07:17:09 joerg Exp $ */
/*-
* Copyright (c) 2007 Joerg Sonnenberger <joerg@netbsd.org>
@ -30,74 +30,79 @@
#include "assym.h"
#include <machine/asm.h>
#include <machine/segments.h>
#include <machine/specialreg.h>
.text
.p2align 2, 0x90
.globl acpi_md_sleep_exit
acpi_md_sleep_exit:
lgdt r_gdt
lgdt ACPI_SUSPEND_GDT(%r8)
/* Reload fixed descriptors for new GDT */
movw $GSEL(GDATA_SEL, SEL_KPL),%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
/* FS and GS are driven by MSRs, so use NULL for them */
xorw %ax,%ax
movw %ax,%fs
movw %ax,%gs
movl $MSR_EFER,%ecx
movl r_msr_efer,%eax
movl ACPI_SUSPEND_MSR_EFER(%r8),%eax
wrmsr
movl $MSR_FSBASE,%ecx
movl r_fs_base_l,%eax
movl r_fs_base_h,%edx
movl ACPI_SUSPEND_FS_BASE_L(%r8),%eax
movl ACPI_SUSPEND_FS_BASE_H(%r8),%edx
wrmsr
movl $MSR_GSBASE,%ecx
movl r_gs_base_l,%eax
movl r_gs_base_h,%edx
movl ACPI_SUSPEND_GS_BASE_L(%r8),%eax
movl ACPI_SUSPEND_GS_BASE_H(%r8),%edx
wrmsr
movl $MSR_KERNELGSBASE,%ecx
movl r_gs_kernelbase_l,%eax
movl r_gs_kernelbase_h,%edx
movl ACPI_SUSPEND_GS_KERNELBASE_L(%r8),%eax
movl ACPI_SUSPEND_GS_KERNELBASE_H(%r8),%edx
wrmsr
movq r_cr8,%rax
movq ACPI_SUSPEND_CR8(%r8),%rax
movq %rax,%cr8
movq r_cr4,%rax
movq ACPI_SUSPEND_CR4(%r8),%rax
movq %rax,%cr4
movq r_cr3,%rax
movq ACPI_SUSPEND_CR3(%r8),%rax
movq %rax,%cr3
movq r_cr2,%rax
movq ACPI_SUSPEND_CR2(%r8),%rax
movq %rax,%cr2
movq r_cr0,%rax
movq ACPI_SUSPEND_CR0(%r8),%rax
movq %rax,%cr0
jmp 1f
1:
movq CPUVAR(GDT),%rax
movq %rax, r_save_gdt
movzwq r_tr,%rdx
movzwq ACPI_SUSPEND_TR(%r8),%rdx
andq $~0x0200,4(%rax,%rdx, 1)
ltr %dx
lldt r_ldt
lidt r_idt
lldt ACPI_SUSPEND_LDT(%r8)
lidt ACPI_SUSPEND_IDT(%r8)
movq r_rsp,%rsp
movq ACPI_SUSPEND_RSP(%r8),%rsp
movq r_rbx,%rbx
movq r_rbp,%rbp
movq r_r12,%r12
movq r_r13,%r13
movq r_r14,%r14
movq r_r15,%r15
movq ACPI_SUSPEND_RBX(%r8),%rbx
movq ACPI_SUSPEND_RBP(%r8),%rbp
movq ACPI_SUSPEND_R12(%r8),%r12
movq ACPI_SUSPEND_R13(%r8),%r13
movq ACPI_SUSPEND_R14(%r8),%r14
movq ACPI_SUSPEND_R15(%r8),%r15
movq ret_addr,%rax
movq %rax,(%rsp)
xorq %rax,%rax
pushq r_rfl
pushq ACPI_SUSPEND_RFL(%r8)
popfq
ret
@ -105,100 +110,55 @@ acpi_md_sleep_exit:
.type acpi_md_sleep_prepare, @function
.globl acpi_md_sleep_prepare
acpi_md_sleep_prepare:
movq %rbx,r_rbx
movq %rbp,r_rbp
movq %r12,r_r12
movq %r13,r_r13
movq %r14,r_r14
movq %r15,r_r15
movq CPUVAR(SELF),%r8
movq %rbx,ACPI_SUSPEND_RBX(%r8)
movq %rbp,ACPI_SUSPEND_RBP(%r8)
movq %r12,ACPI_SUSPEND_R12(%r8)
movq %r13,ACPI_SUSPEND_R13(%r8)
movq %r14,ACPI_SUSPEND_R14(%r8)
movq %r15,ACPI_SUSPEND_R15(%r8)
movq %cr0,%rax
movq %rax,r_cr0
movq %rax,ACPI_SUSPEND_CR0(%r8)
movq %cr2,%rax
movq %rax,r_cr2
movq %rax,ACPI_SUSPEND_CR2(%r8)
movq %cr3,%rax
movq %rax,r_cr3
movq %rax,ACPI_SUSPEND_CR3(%r8)
movq %cr4,%rax
movq %rax,r_cr4
movq %rax,ACPI_SUSPEND_CR4(%r8)
movq %cr8,%rax
movq %rax,r_cr8
movq %rax,ACPI_SUSPEND_CR8(%r8)
pushfq
popq r_rfl
popq ACPI_SUSPEND_RFL(%r8)
movq %rsp,r_rsp
movq %rsp,ACPI_SUSPEND_RSP(%r8)
movl $MSR_FSBASE,%ecx
rdmsr
movl %eax,r_fs_base_l
movl %edx,r_fs_base_h
movl %eax,ACPI_SUSPEND_FS_BASE_L(%r8)
movl %edx,ACPI_SUSPEND_FS_BASE_H(%r8)
movl $MSR_GSBASE,%ecx
rdmsr
movl %eax,r_gs_base_l
movl %edx,r_gs_base_h
movl %eax,ACPI_SUSPEND_GS_BASE_L(%r8)
movl %edx,ACPI_SUSPEND_GS_BASE_H(%r8)
movl $MSR_KERNELGSBASE,%ecx
rdmsr
movl %eax,r_gs_kernelbase_l
movl %edx,r_gs_kernelbase_h
movl %eax,ACPI_SUSPEND_GS_KERNELBASE_L(%r8)
movl %edx,ACPI_SUSPEND_GS_KERNELBASE_H(%r8)
movl $MSR_EFER,%ecx
rdmsr
movl %eax,r_msr_efer
movl %eax,ACPI_SUSPEND_MSR_EFER(%r8)
sgdt r_gdt
sidt r_idt
sldt r_ldt
str r_tr
movq (%rsp),%rax
movq %rax,ret_addr
sgdt ACPI_SUSPEND_GDT(%r8)
sidt ACPI_SUSPEND_IDT(%r8)
sldt ACPI_SUSPEND_LDT(%r8)
str ACPI_SUSPEND_TR(%r8)
call acpi_md_sleep_enter
/* acpi_md_sleep_enter only returns on failure. */
movl $-1,%eax
ret
.data
.align 16
r_tr: .word 0
r_ldt: .word 0
r_fs_base_l:
.long 0
r_fs_base_h:
.long 0
r_gs_base_l:
.long 0
r_gs_base_h:
.long 0
r_gs_kernelbase_l:
.long 0
r_gs_kernelbase_h:
.long 0
r_msr_efer:
.long 0
r_rbx: .quad 0
r_rbp: .quad 0
r_rsp: .quad 0
r_r12: .quad 0
r_r13: .quad 0
r_r14: .quad 0
r_r15: .quad 0
r_rfl: .quad 0
r_cr0: .quad 0
r_cr2: .quad 0
r_cr3: .quad 0
r_cr4: .quad 0
r_cr8: .quad 0
r_gdt: .word 0
.quad 0
r_idt: .word 0
.quad 0
ret_addr: .quad 0
r_save_gdt: .quad 0

View File

@ -1,4 +1,4 @@
# $NetBSD: genassym.cf,v 1.19 2007/12/03 15:33:09 ad Exp $
# $NetBSD: genassym.cf,v 1.20 2007/12/18 07:17:10 joerg Exp $
#
# Copyright (c) 1998, 2006, 2007 The NetBSD Foundation, Inc.
@ -260,6 +260,31 @@ define CPU_INFO_MTX_OLDSPL offsetof(struct cpu_info, ci_mtx_oldspl)
define CPU_INFO_CPUID offsetof(struct cpu_info, ci_cpuid)
define CPU_INFO_ISTATE offsetof(struct cpu_info, ci_istate)
define ACPI_SUSPEND_GDT offsetof(struct cpu_info, ci_suspend_gdt)
define ACPI_SUSPEND_IDT offsetof(struct cpu_info, ci_suspend_idt)
define ACPI_SUSPEND_TR offsetof(struct cpu_info, ci_suspend_tr)
define ACPI_SUSPEND_LDT offsetof(struct cpu_info, ci_suspend_ldt)
define ACPI_SUSPEND_FS_BASE_L offsetof(struct cpu_info, ci_suspend_fs_base_l)
define ACPI_SUSPEND_FS_BASE_H offsetof(struct cpu_info, ci_suspend_fs_base_h)
define ACPI_SUSPEND_GS_BASE_L offsetof(struct cpu_info, ci_suspend_gs_base_l)
define ACPI_SUSPEND_GS_BASE_H offsetof(struct cpu_info, ci_suspend_gs_base_h)
define ACPI_SUSPEND_GS_KERNELBASE_L offsetof(struct cpu_info, ci_suspend_gs_kernelbase_l)
define ACPI_SUSPEND_GS_KERNELBASE_H offsetof(struct cpu_info, ci_suspend_gs_kernelbase_h)
define ACPI_SUSPEND_MSR_EFER offsetof(struct cpu_info, ci_suspend_msr_efer)
define ACPI_SUSPEND_RBX offsetof(struct cpu_info, ci_suspend_rbx)
define ACPI_SUSPEND_RBP offsetof(struct cpu_info, ci_suspend_rbp)
define ACPI_SUSPEND_RSP offsetof(struct cpu_info, ci_suspend_rsp)
define ACPI_SUSPEND_R12 offsetof(struct cpu_info, ci_suspend_r12)
define ACPI_SUSPEND_R13 offsetof(struct cpu_info, ci_suspend_r13)
define ACPI_SUSPEND_R14 offsetof(struct cpu_info, ci_suspend_r14)
define ACPI_SUSPEND_R15 offsetof(struct cpu_info, ci_suspend_r15)
define ACPI_SUSPEND_RFL offsetof(struct cpu_info, ci_suspend_rfl)
define ACPI_SUSPEND_CR0 offsetof(struct cpu_info, ci_suspend_cr0)
define ACPI_SUSPEND_CR2 offsetof(struct cpu_info, ci_suspend_cr2)
define ACPI_SUSPEND_CR3 offsetof(struct cpu_info, ci_suspend_cr3)
define ACPI_SUSPEND_CR4 offsetof(struct cpu_info, ci_suspend_cr4)
define ACPI_SUSPEND_CR8 offsetof(struct cpu_info, ci_suspend_cr8)
if NIOAPIC > 0
define IOAPIC_SC_REG offsetof(struct ioapic_softc, sc_reg)
define IOAPIC_SC_DATA offsetof(struct ioapic_softc, sc_data)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipifuncs.c,v 1.12 2007/10/17 19:53:00 garbled Exp $ */
/* $NetBSD: ipifuncs.c,v 1.13 2007/12/18 07:17:10 joerg Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -40,7 +40,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.12 2007/10/17 19:53:00 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.13 2007/12/18 07:17:10 joerg Exp $");
/*
* Interprocessor interrupt handlers.
@ -69,6 +69,8 @@ __KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.12 2007/10/17 19:53:00 garbled Exp $"
#include <ddb/db_output.h>
#include "acpi.h"
void x86_64_ipi_halt(struct cpu_info *);
void x86_64_ipi_synch_fpu(struct cpu_info *);
@ -80,6 +82,12 @@ void x86_64_reload_mtrr(struct cpu_info *);
#define x86_64_reload_mtrr NULL
#endif
#if NACPI > 0
void acpi_cpu_sleep(struct cpu_info *);
#else
#define acpu_cpu_sleep NULL
#endif
void (*ipifunc[X86_NIPI])(struct cpu_info *) =
{
x86_64_ipi_halt,
@ -88,7 +96,8 @@ void (*ipifunc[X86_NIPI])(struct cpu_info *) =
x86_64_ipi_synch_fpu,
x86_64_reload_mtrr,
gdt_reload_cpu,
msr_write_ipi
msr_write_ipi,
acpi_cpu_sleep,
};
void

View File

@ -1,4 +1,4 @@
# $NetBSD: files.amd64,v 1.50 2007/12/09 20:27:43 jmcneill Exp $
# $NetBSD: files.amd64,v 1.51 2007/12/18 07:17:10 joerg Exp $
#
# new style config file for amd64 architecture
#
@ -187,7 +187,6 @@ include "dev/bluetooth/files.bluetooth"
include "dev/ieee1394/files.ieee1394"
include "dev/apm/files.apm"
include "dev/acpi/files.acpi"
file arch/amd64/acpi/acpi_wakeup.c acpi
file arch/amd64/acpi/acpi_wakeup_low.S acpi
include "arch/amd64/conf/majors.amd64"

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.35 2007/12/09 20:27:44 jmcneill Exp $ */
/* $NetBSD: cpu.h,v 1.36 2007/12/18 07:17:11 joerg Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -140,6 +140,38 @@ struct cpu_info {
char *ci_ddbipi_stack;
struct evcnt ci_ipi_events[X86_NIPI];
/*
* The following two are actually region_descriptors,
* but that would pollute the namespace.
*/
uint64_t ci_suspend_gdt;
uint16_t ci_suspend_gdt_padding;
uint64_t ci_suspend_idt;
uint16_t ci_suspend_idt_padding;
uint16_t ci_suspend_tr;
uint16_t ci_suspend_ldt;
uint32_t ci_suspend_fs_base_l;
uint32_t ci_suspend_fs_base_h;
uint32_t ci_suspend_gs_base_l;
uint32_t ci_suspend_gs_base_h;
uint32_t ci_suspend_gs_kernelbase_l;
uint32_t ci_suspend_gs_kernelbase_h;
uint32_t ci_suspend_msr_efer;
uint64_t ci_suspend_rbx;
uint64_t ci_suspend_rbp;
uint64_t ci_suspend_rsp;
uint64_t ci_suspend_r12;
uint64_t ci_suspend_r13;
uint64_t ci_suspend_r14;
uint64_t ci_suspend_r15;
uint64_t ci_suspend_rfl;
uint64_t ci_suspend_cr0;
uint64_t ci_suspend_cr2;
uint64_t ci_suspend_cr3;
uint64_t ci_suspend_cr4;
uint64_t ci_suspend_cr8;
};
#define CPUF_BSP 0x0001 /* CPU is the original BSP */
@ -162,9 +194,9 @@ extern struct cpu_info *cpu_info_list;
#define X86_MAXPROCS 32 /* bitmask; can be bumped to 64 */
#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci))
#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci))
#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci))
#define CPU_STARTUP(_ci, _target) ((_ci)->ci_func->start(_ci, _target))
#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci))
#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci))
#if defined(__GNUC__) && defined(_KERNEL)
static struct cpu_info *x86_curcpu(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakecode.S,v 1.10 2007/12/09 20:27:44 jmcneill Exp $ */
/* $NetBSD: acpi_wakecode.S,v 1.11 2007/12/18 07:17:11 joerg Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -122,7 +122,7 @@ wakeup_16:
/* Disable beep again if machdep.acpi_beep_on_reset=1 */
cmpb $1,WAKEUP_beep_on_reset
jne 1
jne 1f
inb $0x61,%al
andb $0xfc,%al
outb %al,$0x61
@ -159,7 +159,8 @@ wakeup_32:
/* Enable paging (assumes identical mapping) */
movl WAKEUP_r_cr3 + ACPI_WAKEUP_ADDR,%eax
movl %eax,%cr3
movl WAKEUP_r_cr0 + ACPI_WAKEUP_ADDR,%eax
movl %cr0,%eax
orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_EM|CR0_MP|CR0_WP),%eax
movl %eax,%cr0
/* Flush the prefetch queue */
@ -170,11 +171,9 @@ wakeup_32:
nop
/* Restore registers */
lgdt WAKEUP_r_gdt + ACPI_WAKEUP_ADDR
movl WAKEUP_curcpu + ACPI_WAKEUP_ADDR,%edx
movl WAKEUP_restorecpu + ACPI_WAKEUP_ADDR,%ebx
movw WAKEUP_r_ds + ACPI_WAKEUP_ADDR,%ax
movw %ax,%ds
jmp *%ebx
.align 8
@ -195,18 +194,13 @@ tmp_gdtable:
.byte 0, 0x93, 0xcf, 0
.align 16, 0
.global WAKEUP_r_cr0
WAKEUP_r_cr0: .long 0
.global WAKEUP_r_cr3
WAKEUP_r_cr3: .long 0
.global WAKEUP_r_cr4
WAKEUP_r_cr4: .long 0
.global WAKEUP_r_gdt
WAKEUP_r_gdt: .word 0
.long 0
.global WAKEUP_r_ds
WAKEUP_r_ds: .word 0
.global WAKEUP_curcpu
WAKEUP_curcpu: .long 0
.global WAKEUP_restorecpu
WAKEUP_restorecpu: .long 0

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakeup_low.S,v 1.3 2007/12/11 23:06:11 lukem Exp $ */
/* $NetBSD: acpi_wakeup_low.S,v 1.4 2007/12/18 07:17:13 joerg Exp $ */
/*-
* Copyright (c) 2007 Joerg Sonnenberger <joerg@netbsd.org>
@ -29,55 +29,56 @@
*/
#include <machine/asm.h>
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup_low.S,v 1.3 2007/12/11 23:06:11 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup_low.S,v 1.4 2007/12/18 07:17:13 joerg Exp $");
#include "assym.h"
#include <machine/segments.h>
.text
.p2align 2, 0x90
.globl acpi_md_sleep_exit
acpi_md_sleep_exit:
movw r_es,%ax
lgdt ACPI_SUSPEND_GDT(%edx)
/* Reload fixed descriptors for new GDT */
movw $GSEL(GDATA_SEL, SEL_KPL),%ax
movw %ax,%ds
movw %ax,%es
movw r_fs,%ax
movw %ax,%fs
movw r_gs,%ax
movw %ax,%gs
movw r_ss,%ax
movw %ax,%ss
movl r_cr2,%eax
movw ACPI_SUSPEND_FS(%edx),%ax
movw %ax,%fs
movw ACPI_SUSPEND_GS(%edx),%ax
movw %ax,%gs
movl ACPI_SUSPEND_CR2(%edx),%eax
movl %eax,%cr2
movl r_cr4,%eax
movl ACPI_SUSPEND_CR4(%edx),%eax
movl %eax,%cr4
movl r_cr3,%eax
movl ACPI_SUSPEND_CR3(%edx),%eax
movl %eax,%cr3
jmp 1f
1:
lidt r_idt
lldt r_ldt
lidt ACPI_SUSPEND_IDT(%edx)
lldt ACPI_SUSPEND_LDT(%edx)
movl CPUVAR(GDT),%eax
movzwl r_tr,%edx
andl $~0x0200,4(%eax,%edx, 1)
ltr %dx
movzwl ACPI_SUSPEND_TR(%edx),%ecx
andl $~0x0200,4(%eax,%ecx, 1)
ltr %cx
movl r_esp,%esp
movl ACPI_SUSPEND_EBX(%edx),%ebx
movl ACPI_SUSPEND_ESI(%edx),%esi
movl ACPI_SUSPEND_EDI(%edx),%edi
movl ACPI_SUSPEND_EBP(%edx),%ebp
movl ACPI_SUSPEND_ESP(%edx),%esp
movl r_ebx,%ebx
movl r_ecx,%ecx
movl r_edx,%edx
movl r_ebp,%ebp
movl r_esi,%esi
movl r_edi,%edi
pushl r_efl
pushl ACPI_SUSPEND_EFL(%edx)
popfl
movl ret_addr,%eax
movl %eax,(%esp)
xorl %eax,%eax
ret
@ -86,40 +87,33 @@ acpi_md_sleep_exit:
.type acpi_md_sleep_prepare, @function
.globl acpi_md_sleep_prepare
acpi_md_sleep_prepare:
movw %ds,r_ds
movw %es,r_es
movw %fs,r_fs
movw %gs,r_gs
movw %ss,r_ss
movl CPUVAR(SELF),%edx
movw %fs,ACPI_SUSPEND_FS(%edx)
movw %gs,ACPI_SUSPEND_GS(%edx)
movl %ebx,r_ebx
movl %ecx,r_ecx
movl %edx,r_edx
movl %ebp,r_ebp
movl %esi,r_esi
movl %edi,r_edi
movl %ebx,ACPI_SUSPEND_EBX(%edx)
movl %esi,ACPI_SUSPEND_ESI(%edx)
movl %edi,ACPI_SUSPEND_EDI(%edx)
movl %ebp,ACPI_SUSPEND_EBP(%edx)
movl %esp,ACPI_SUSPEND_ESP(%edx)
movl %cr0,%eax
movl %eax,r_cr0
movl %eax,ACPI_SUSPEND_CR0(%edx)
movl %cr2,%eax
movl %eax,r_cr2
movl %eax,ACPI_SUSPEND_CR2(%edx)
movl %cr3,%eax
movl %eax,r_cr3
movl %eax,ACPI_SUSPEND_CR3(%edx)
movl %cr4,%eax
movl %eax,r_cr4
movl %eax,ACPI_SUSPEND_CR4(%edx)
pushfl
popl r_efl
popl ACPI_SUSPEND_EFL(%edx)
movl %esp,r_esp
sgdt ACPI_SUSPEND_GDT(%edx)
sidt ACPI_SUSPEND_IDT(%edx)
sldt ACPI_SUSPEND_LDT(%edx)
str ACPI_SUSPEND_TR(%edx)
sgdt r_gdt
sidt r_idt
sldt r_ldt
str r_tr
movl (%esp),%eax
movl %eax,ret_addr
movl 4(%esp),%eax
pushl %eax
call acpi_md_sleep_enter
@ -127,42 +121,3 @@ acpi_md_sleep_prepare:
popl %eax
movl $-1,%eax
ret
.data
.align 16
.globl acpi_wakeup_ds
acpi_wakeup_ds:
r_ds: .word 0
r_es: .word 0
r_fs: .word 0
r_gs: .word 0
r_ss: .word 0
r_tr: .word 0
r_ldt: .word 0
r_ebx: .long 0
r_ecx: .long 0
r_edx: .long 0
r_ebp: .long 0
r_esi: .long 0
r_edi: .long 0
r_esp: .long 0
r_efl: .long 0
.globl acpi_wakeup_cr0
acpi_wakeup_cr0:
r_cr0: .long 0
r_cr2: .long 0
r_cr3: .long 0
.globl acpi_wakeup_cr4
acpi_wakeup_cr4:
r_cr4: .long 0
.globl acpi_wakeup_gdt
acpi_wakeup_gdt:
r_gdt: .word 0
.long 0
r_idt: .word 0
.long 0
ret_addr: .long 0

View File

@ -1,4 +1,4 @@
# $NetBSD: files.i386,v 1.323 2007/12/09 20:27:46 jmcneill Exp $
# $NetBSD: files.i386,v 1.324 2007/12/18 07:17:13 joerg Exp $
#
# new style config file for i386 architecture
#
@ -472,7 +472,6 @@ include "dev/ieee1394/files.ieee1394"
include "arch/i386/pnpbios/files.pnpbios"
include "dev/acpi/files.acpi"
file arch/i386/acpi/acpi_wakeup.c acpi
file arch/i386/acpi/acpi_wakeup_low.S acpi
# Toshiba VALD

View File

@ -1,4 +1,4 @@
# $NetBSD: genassym.cf,v 1.58 2007/12/03 15:33:45 ad Exp $
# $NetBSD: genassym.cf,v 1.59 2007/12/18 07:17:14 joerg Exp $
#
# Copyright (c) 1998, 2006, 2007 The NetBSD Foundation, Inc.
@ -318,6 +318,24 @@ define CPU_INFO_MTX_OLDSPL offsetof(struct cpu_info, ci_mtx_oldspl)
define CPU_INFO_INTRSTACK offsetof(struct cpu_info, ci_intrstack)
define CPU_INFO_ISTATE offsetof(struct cpu_info, ci_istate)
define ACPI_SUSPEND_GDT offsetof(struct cpu_info, ci_suspend_gdt)
define ACPI_SUSPEND_IDT offsetof(struct cpu_info, ci_suspend_idt)
define ACPI_SUSPEND_TR offsetof(struct cpu_info, ci_suspend_tr)
define ACPI_SUSPEND_LDT offsetof(struct cpu_info, ci_suspend_ldt)
define ACPI_SUSPEND_FS offsetof(struct cpu_info, ci_suspend_fs)
define ACPI_SUSPEND_GS offsetof(struct cpu_info, ci_suspend_gs)
define ACPI_SUSPEND_EBX offsetof(struct cpu_info, ci_suspend_ebx)
define ACPI_SUSPEND_ESI offsetof(struct cpu_info, ci_suspend_esi)
define ACPI_SUSPEND_EDI offsetof(struct cpu_info, ci_suspend_edi)
define ACPI_SUSPEND_EBP offsetof(struct cpu_info, ci_suspend_ebp)
define ACPI_SUSPEND_ESP offsetof(struct cpu_info, ci_suspend_esp)
define ACPI_SUSPEND_EFL offsetof(struct cpu_info, ci_suspend_efl)
define ACPI_SUSPEND_CR0 offsetof(struct cpu_info, ci_suspend_cr0)
define ACPI_SUSPEND_CR2 offsetof(struct cpu_info, ci_suspend_cr2)
define ACPI_SUSPEND_CR3 offsetof(struct cpu_info, ci_suspend_cr3)
define ACPI_SUSPEND_CR4 offsetof(struct cpu_info, ci_suspend_cr4)
if NIOAPIC > 0
define IOAPIC_SC_REG offsetof(struct ioapic_softc, sc_reg)
define IOAPIC_SC_DATA offsetof(struct ioapic_softc, sc_data)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipifuncs.c,v 1.22 2007/11/28 16:28:44 ad Exp $ */
/* $NetBSD: ipifuncs.c,v 1.23 2007/12/18 07:17:14 joerg Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.22 2007/11/28 16:28:44 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.23 2007/12/18 07:17:14 joerg Exp $");
#include "opt_ddb.h"
#include "opt_mtrr.h"
@ -68,6 +68,8 @@ __KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.22 2007/11/28 16:28:44 ad Exp $");
#include <ddb/db_output.h>
#include "acpi.h"
void i386_ipi_halt(struct cpu_info *);
#if NNPX > 0
@ -84,6 +86,12 @@ void i386_reload_mtrr(struct cpu_info *);
#define i386_reload_mtrr NULL
#endif
#if NACPI > 0
void acpi_cpu_sleep(struct cpu_info *);
#else
#define acpi_cpu_sleep NULL
#endif
void (*ipifunc[X86_NIPI])(struct cpu_info *) =
{
i386_ipi_halt,
@ -92,7 +100,8 @@ void (*ipifunc[X86_NIPI])(struct cpu_info *) =
i386_ipi_synch_fpu,
i386_reload_mtrr,
gdt_reload_cpu,
msr_write_ipi
msr_write_ipi,
acpi_cpu_sleep,
};
void

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.151 2007/12/03 22:17:28 joerg Exp $ */
/* $NetBSD: cpu.h,v 1.152 2007/12/18 07:17:15 joerg Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -157,6 +157,30 @@ struct cpu_info {
struct evcnt ci_ipi_events[X86_NIPI];
struct via_padlock ci_vp; /* VIA PadLock private storage */
/*
* The following two are actually region_descriptors,
* but that would pollute the namespace.
*/
uint32_t ci_suspend_gdt;
uint16_t ci_suspend_gdt_padding;
uint32_t ci_suspend_idt;
uint16_t ci_suspend_idt_padding;
uint16_t ci_suspend_tr;
uint16_t ci_suspend_ldt;
uint16_t ci_suspend_fs;
uint16_t ci_suspend_gs;
uint32_t ci_suspend_ebx;
uint32_t ci_suspend_esi;
uint32_t ci_suspend_edi;
uint32_t ci_suspend_ebp;
uint32_t ci_suspend_esp;
uint32_t ci_suspend_efl;
uint32_t ci_suspend_cr0;
uint32_t ci_suspend_cr2;
uint32_t ci_suspend_cr3;
uint32_t ci_suspend_cr4;
};
/*
@ -193,9 +217,9 @@ extern struct cpu_info *cpu_info_list;
#define X86_MAXPROCS 32 /* because we use a bitmask */
#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci))
#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci))
#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci))
#define CPU_STARTUP(_ci, _target) ((_ci)->ci_func->start(_ci, _target))
#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci))
#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci))
#if defined(__GNUC__) && defined(_KERNEL)
static struct cpu_info *x86_curcpu(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakeup.c,v 1.44 2007/12/15 11:26:40 joerg Exp $ */
/* $NetBSD: acpi_wakeup.c,v 1.1 2007/12/18 07:17:16 joerg Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.44 2007/12/15 11:26:40 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.1 2007/12/18 07:17:16 joerg Exp $");
/*-
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
@ -78,8 +78,9 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.44 2007/12/15 11:26:40 joerg Exp $
#include <uvm/uvm_extern.h>
#include <uvm/uvm_page.h>
#ifdef __i386__
#include "opt_mtrr.h"
#endif
#include "ioapic.h"
#include "lapic.h"
@ -99,9 +100,15 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_wakeup.c,v 1.44 2007/12/15 11:26:40 joerg Exp $
#define ACPI_MACHDEP_PRIVATE
#include <machine/acpi_machdep.h>
#include <machine/cpu.h>
#include <machine/npx.h>
#ifdef __i386__
# include <machine/npx.h>
#else
# include <machine/fpu.h>
#endif
#include <machine/mtrr.h>
#include <x86/cpuvar.h>
#include "acpi_wakecode.h"
/* Address is also hard-coded in acpi_wakecode.S */
@ -115,6 +122,64 @@ static int acpi_md_beep_on_reset = 1;
static int sysctl_md_acpi_vbios_reset(SYSCTLFN_ARGS);
static int sysctl_md_acpi_beep_on_reset(SYSCTLFN_ARGS);
/* Implemented in acpi_wakeup_low.S. */
int acpi_md_sleep_prepare(int);
int acpi_md_sleep_exit(int);
/* Referenced by acpi_wakeup_low.S. */
void acpi_md_sleep_enter(int);
#ifdef MULTIPROCESSOR
/* Referenced in ipifuncs.c. */
void acpi_cpu_sleep(struct cpu_info *);
#endif
static void
acpi_md_sleep_patch(struct cpu_info *ci)
{
#define WAKECODE_FIXUP(offset, type, val) do { \
type *addr; \
addr = (type *)(acpi_wakeup_vaddr + offset); \
*addr = val; \
} while (0)
#define WAKECODE_BCOPY(offset, type, val) do { \
void **addr; \
addr = (void **)(acpi_wakeup_vaddr + offset); \
bcopy(&(val), addr, sizeof(type)); \
} while (0)
paddr_t tmp_pdir;
tmp_pdir = pmap_init_tmp_pgtbl(acpi_wakeup_paddr);
/* Execute Sleep */
bcopy(wakecode, (void *)acpi_wakeup_vaddr, sizeof(wakecode));
if (CPU_IS_PRIMARY(ci)) {
WAKECODE_FIXUP(WAKEUP_vbios_reset, uint8_t, acpi_md_vbios_reset);
WAKECODE_FIXUP(WAKEUP_beep_on_reset, uint8_t, acpi_md_beep_on_reset);
} else {
WAKECODE_FIXUP(WAKEUP_vbios_reset, uint8_t, 0);
WAKECODE_FIXUP(WAKEUP_beep_on_reset, uint8_t, 0);
}
#ifdef __i386__
WAKECODE_FIXUP(WAKEUP_r_cr4, uint32_t, ci->ci_suspend_cr4);
#else
WAKECODE_FIXUP(WAKEUP_msr_efer, uint32_t, ci->ci_suspend_msr_efer);
#endif
WAKECODE_FIXUP(WAKEUP_curcpu, void *, ci);
#ifdef __i386__
WAKECODE_FIXUP(WAKEUP_r_cr3, uint32_t, tmp_pdir);
#else
WAKECODE_FIXUP(WAKEUP_r_cr3, uint64_t, tmp_pdir);
#endif
WAKECODE_FIXUP(WAKEUP_restorecpu, void *, acpi_md_sleep_exit);
#undef WAKECODE_FIXUP
#undef WAKECODE_BCOPY
}
/*
* S4 sleep using S4BIOS support, from FreeBSD.
*
@ -126,7 +191,6 @@ enter_s4_with_bios(void)
{
ACPI_OBJECT_LIST ArgList;
ACPI_OBJECT Arg;
u_long ef;
UINT32 ret;
ACPI_STATUS status;
@ -147,9 +211,6 @@ enter_s4_with_bios(void)
AcpiSetRegister(ACPI_BITREG_WAKE_STATUS, 1);
ef = x86_read_psl();
x86_disable_intr();
AcpiHwDisableAllGpes();
AcpiHwEnableAllWakeupGpes();
@ -172,60 +233,35 @@ enter_s4_with_bios(void)
AcpiHwDisableAllGpes();
AcpiHwEnableAllRuntimeGpes();
x86_write_psl(ef);
return (AE_OK);
}
extern uint8_t acpi_wakeup_gdt[6];
extern uint32_t acpi_wakeup_ds;
extern uint32_t acpi_wakeup_cr0;
extern uint32_t acpi_wakeup_cr4;
/* XXX shut gcc up */
extern int acpi_md_sleep_prepare(int state);
extern int acpi_md_sleep_exit(void);
void acpi_md_sleep_enter(int);
void
acpi_md_sleep_enter(int state)
{
#define WAKECODE_FIXUP(offset, type, val) do { \
type *addr; \
addr = (type *)(acpi_wakeup_vaddr + offset); \
*addr = val; \
} while (0)
#define WAKECODE_BCOPY(offset, type, val) do { \
void **addr; \
addr = (void **)(acpi_wakeup_vaddr + offset); \
bcopy(&(val), addr, sizeof(type)); \
} while (0)
ACPI_STATUS status;
ACPI_TABLE_FACS *facs;
paddr_t tmp_pdir;
struct cpu_info *ci;
tmp_pdir = pmap_init_tmp_pgtbl(acpi_wakeup_paddr);
ci = curcpu();
/* Execute Sleep */
bcopy(wakecode, (void *)acpi_wakeup_vaddr, sizeof(wakecode));
WAKECODE_FIXUP(WAKEUP_vbios_reset, uint8_t, acpi_md_vbios_reset);
WAKECODE_FIXUP(WAKEUP_beep_on_reset, uint8_t, acpi_md_beep_on_reset);
#ifdef MULTIPROCESSOR
if (!CPU_IS_PRIMARY(ci)) {
atomic_and_32(&ci->ci_flags, ~CPUF_RUNNING);
atomic_and_32(&cpus_running, ~ci->ci_cpumask);
WAKECODE_FIXUP(WAKEUP_r_cr0, uint32_t, acpi_wakeup_cr0);
WAKECODE_FIXUP(WAKEUP_r_cr3, uint32_t, tmp_pdir);
WAKECODE_FIXUP(WAKEUP_r_cr4, uint32_t, acpi_wakeup_cr4);
ACPI_FLUSH_CPU_CACHE();
WAKECODE_BCOPY(WAKEUP_r_gdt, struct region_descriptor, acpi_wakeup_gdt);
for (;;)
x86_hlt();
}
#endif
WAKECODE_FIXUP(WAKEUP_restorecpu, void *, acpi_md_sleep_exit);
WAKECODE_FIXUP(WAKEUP_r_ds, uint16_t, acpi_wakeup_ds);
acpi_md_sleep_patch(ci);
ACPI_FLUSH_CPU_CACHE();
if (state == ACPI_STATE_S4) {
ACPI_TABLE_FACS *facs;
status = AcpiGetTable(ACPI_SIG_FACS, 0, (ACPI_TABLE_HEADER **)&facs);
if (ACPI_FAILURE(status)) {
printf("acpi: S4BIOS not supported: cannot load FACS\n");
@ -247,47 +283,89 @@ acpi_md_sleep_enter(int state)
return;
}
for (;;) ;
for (;;)
x86_hlt();
}
#ifdef MULTIPROCESSOR
void
acpi_cpu_sleep(struct cpu_info *ci)
{
KASSERT(!CPU_IS_PRIMARY(ci));
KASSERT(ci == curcpu());
x86_disable_intr();
if (acpi_md_sleep_prepare(-1))
return;
/* Execute Wakeup */
#ifdef __i386__
npxinit(ci);
#else
cpu_init_msrs(ci, false);
fpuinit(ci);
#endif
#if NLAPIC > 0
lapic_enable();
lapic_set_lvt();
lapic_initclocks();
#endif
atomic_or_32(&ci->ci_flags, CPUF_RUNNING);
atomic_or_32(&cpus_running, ci->ci_cpumask);
x86_enable_intr();
}
#endif
int
acpi_md_sleep(int state)
{
int s, ret = 0;
int s, ret = 0;
#ifdef MULTIPROCESSOR
struct cpu_info *ci;
CPU_INFO_ITERATOR cii;
#endif
KASSERT(acpi_wakeup_paddr != 0);
KASSERT(sizeof(wakecode) <= PAGE_SIZE);
if (ncpu > 1) {
printf("acpi: sleep is not supported on MP.\n");
return -1;
}
if (!CPU_IS_PRIMARY(curcpu())) {
printf("acpi: apci_md_sleep called from secondary CPU ignored\n");
printf("acpi0: WARNING: ignoring sleep from secondary CPU\n");
return -1;
}
AcpiSetFirmwareWakingVector(acpi_wakeup_paddr);
#ifdef MULTIPROCESSOR
/* Shutdown all other CPUs */
x86_broadcast_ipi(X86_IPI_HALT);
#endif
s = splipi();
#ifdef __i386__
npxsave_cpu(curcpu(), 1);
#else
fpusave_cpu(curcpu(), 1);
#endif
splx(s);
s = splhigh();
x86_disable_intr();
#ifdef MULTIPROCESSOR
/* Save and suspend Application Processors */
x86_broadcast_ipi(X86_IPI_ACPI_CPU_SLEEP);
while (cpus_running != curcpu()->ci_cpumask)
delay(1);
#endif
if (acpi_md_sleep_prepare(state))
goto out;
/* Execute Wakeup */
#ifdef __i386__
npxinit(&cpu_info_primary);
#else
cpu_init_msrs(&cpu_info_primary, false);
fpuinit(&cpu_info_primary);
#endif
i8259_reinit();
#if NLAPIC > 0
lapic_enable();
@ -304,6 +382,21 @@ acpi_md_sleep(int state)
AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
out:
#ifdef MULTIPROCESSOR
for (CPU_INFO_FOREACH(cii, ci)) {
if (CPU_IS_PRIMARY(ci))
continue;
acpi_md_sleep_patch(ci);
CPU_STARTUP(ci, acpi_wakeup_paddr);
CPU_START_CLEANUP(ci);
while ((ci->ci_flags & CPUF_RUNNING) == 0)
x86_pause();
}
#endif
x86_enable_intr();
splx(s);
@ -313,8 +406,6 @@ out:
#endif
return (ret);
#undef WAKECODE_FIXUP
#undef WAKECODE_BCOPY
}
void
@ -331,7 +422,7 @@ acpi_md_sleep_init(void)
pmap_update(pmap_kernel());
}
SYSCTL_SETUP(sysctl_md_acpi_setup, "acpi i386 sysctl setup")
SYSCTL_SETUP(sysctl_md_acpi_setup, "acpi x86 sysctl setup")
{
const struct sysctlnode *node;
const struct sysctlnode *ssnode;

View File

@ -1,4 +1,4 @@
# $NetBSD: files.x86,v 1.36 2007/12/09 20:27:48 jmcneill Exp $
# $NetBSD: files.x86,v 1.37 2007/12/18 07:17:16 joerg Exp $
# options for MP configuration through the MP spec
defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
@ -73,7 +73,8 @@ file arch/x86/x86/mpbios.c mpbios
# MP configuration using ACPI
file arch/x86/x86/mpacpi.c acpi
file arch/x86/x86/acpi_machdep.c acpi
file arch/x86/acpi/acpi_wakeup.c acpi
file arch/x86/x86/acpi_machdep.c acpi
file arch/x86/isa/isa_machdep.c isa

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpuvar.h,v 1.19 2007/11/15 19:46:44 ad Exp $ */
/* $NetBSD: cpuvar.h,v 1.20 2007/12/18 07:17:17 joerg Exp $ */
/*-
* Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
@ -74,7 +74,7 @@
#define _X86_CPUVAR_H_
struct cpu_functions {
int (*start)(struct cpu_info *);
int (*start)(struct cpu_info *, paddr_t);
int (*stop)(struct cpu_info *);
void (*cleanup)(struct cpu_info *);
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: intrdefs.h,v 1.11 2007/12/03 15:34:27 ad Exp $ */
/* $NetBSD: intrdefs.h,v 1.12 2007/12/18 07:17:17 joerg Exp $ */
#ifndef _X86_INTRDEFS_H_
#define _X86_INTRDEFS_H_
@ -61,12 +61,14 @@
#define X86_IPI_MTRR 0x00000010
#define X86_IPI_GDT 0x00000020
#define X86_IPI_WRITE_MSR 0x00000040
#define X86_IPI_ACPI_CPU_SLEEP 0x00000080
#define X86_NIPI 7
#define X86_NIPI 8
#define X86_IPI_NAMES { "halt IPI", "timeset IPI", "FPU flush IPI", \
"FPU synch IPI", "MTRR update IPI", \
"GDT update IPI", "MSR write IPI" }
"GDT update IPI", "MSR write IPI", \
"ACPI CPU sleep IPI" }
#define IREENT_MAGIC 0x18041969

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.13 2007/12/15 09:18:59 joerg Exp $ */
/* $NetBSD: cpu.c,v 1.14 2007/12/18 07:17:17 joerg Exp $ */
/*-
* Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc.
@ -69,7 +69,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.13 2007/12/15 09:18:59 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.14 2007/12/18 07:17:17 joerg Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@ -131,7 +131,7 @@ struct cpu_softc {
struct cpu_info *sc_info; /* pointer to CPU info */
};
int mp_cpu_start(struct cpu_info *);
int mp_cpu_start(struct cpu_info *, paddr_t);
void mp_cpu_start_cleanup(struct cpu_info *);
const struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,
mp_cpu_start_cleanup };
@ -178,6 +178,8 @@ extern char x86_64_doubleflt_stack[];
bool x86_mp_online;
paddr_t mp_trampoline_paddr = MP_TRAMPOLINE;
static vaddr_t cmos_data_mapping;
#ifdef MULTIPROCESSOR
/*
* Array of CPU info structures. Must be statically-allocated because
@ -208,6 +210,12 @@ cpu_init_first(void)
cpu_info_primary.ci_cpuid = cpunum;
cpu_copy_trampoline();
cmos_data_mapping = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY);
if (cmos_data_mapping == 0)
panic("No KVA for page 0");
pmap_kenter_pa(cmos_data_mapping, 0, VM_PROT_READ|VM_PROT_WRITE);
pmap_update(pmap_kernel());
}
#endif
@ -563,7 +571,7 @@ cpu_start_secondary(struct cpu_info *ci)
aprint_debug("%s: starting\n", ci->ci_dev->dv_xname);
ci->ci_curlwp = ci->ci_data.cpu_idlelwp;
CPU_STARTUP(ci);
CPU_STARTUP(ci, mp_trampoline_paddr);
/*
* wait for it to become ready
@ -793,15 +801,19 @@ cpu_set_tss_gates(struct cpu_info *ci)
}
#endif /* i386 */
int
mp_cpu_start(struct cpu_info *ci)
mp_cpu_start(struct cpu_info *ci, paddr_t target)
{
#if NLAPIC > 0
int error;
#endif
unsigned short dwordptr[2];
vaddr_t kva;
/*
* Bootstrap code must be addressable in real mode
* and it must be page aligned.
*/
KASSERT(target < 0x10000 && target % PAGE_SIZE == 0);
/*
* "The BSP must initialize CMOS shutdown code to 0Ah ..."
@ -816,17 +828,9 @@ mp_cpu_start(struct cpu_info *ci)
*/
dwordptr[0] = 0;
dwordptr[1] = mp_trampoline_paddr >> 4;
dwordptr[1] = target >> 4;
kva = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY);
if ((void *)kva == NULL)
return ENOMEM;
pmap_kenter_pa(kva, 0, VM_PROT_READ|VM_PROT_WRITE);
pmap_update(pmap_kernel());
memcpy((uint8_t *)(kva + 0x467), dwordptr, 4);
pmap_kremove(kva, PAGE_SIZE);
pmap_update(pmap_kernel());
uvm_km_free(kernel_map, kva, PAGE_SIZE, UVM_KMF_VAONLY);
memcpy((uint8_t *)(cmos_data_mapping + 0x467), dwordptr, 4);
#if NLAPIC > 0
/*
@ -841,13 +845,13 @@ mp_cpu_start(struct cpu_info *ci)
if (cpu_feature & CPUID_APIC) {
if ((error = x86_ipi(mp_trampoline_paddr / PAGE_SIZE,
if ((error = x86_ipi(target / PAGE_SIZE,
ci->ci_apicid,
LAPIC_DLMODE_STARTUP)) != 0)
return error;
i8254_delay(200);
if ((error = x86_ipi(mp_trampoline_paddr / PAGE_SIZE,
if ((error = x86_ipi(target / PAGE_SIZE,
ci->ci_apicid,
LAPIC_DLMODE_STARTUP)) != 0)
return error;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.4 2007/12/12 19:25:38 bouyer Exp $ */
/* $NetBSD: cpu.c,v 1.5 2007/12/18 07:17:18 joerg Exp $ */
/* NetBSD: cpu.c,v 1.18 2004/02/20 17:35:01 yamt Exp */
/*-
@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.4 2007/12/12 19:25:38 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.5 2007/12/18 07:17:18 joerg Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@ -135,7 +135,7 @@ struct cpu_softc {
struct cpu_info *sc_info; /* pointer to CPU info */
};
int mp_cpu_start(struct cpu_info *);
int mp_cpu_start(struct cpu_info *, paddr_t);
void mp_cpu_start_cleanup(struct cpu_info *);
const struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,
mp_cpu_start_cleanup };
@ -780,7 +780,7 @@ cpu_set_tss_gates(struct cpu_info *ci)
}
int
mp_cpu_start(struct cpu_info *ci)
mp_cpu_start(struct cpu_info *ci, paddr_t target)
{
#if 0
#if NLAPIC > 0
@ -801,7 +801,7 @@ mp_cpu_start(struct cpu_info *ci)
*/
dwordptr[0] = 0;
dwordptr[1] = MP_TRAMPOLINE >> 4;
dwordptr[1] = target >> 4;
pmap_kenter_pa (0, 0, VM_PROT_READ|VM_PROT_WRITE);
memcpy ((u_int8_t *) 0x467, dwordptr, 4);
@ -820,13 +820,13 @@ mp_cpu_start(struct cpu_info *ci)
if (cpu_feature & CPUID_APIC) {
if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
if ((error = x86_ipi(target/PAGE_SIZE,
ci->ci_apicid,
LAPIC_DLMODE_STARTUP)) != 0)
return error;
delay(200);
if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
if ((error = x86_ipi(target/PAGE_SIZE,
ci->ci_apicid,
LAPIC_DLMODE_STARTUP)) != 0)
return error;