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:
parent
49a3869ae1
commit
870cffb0ab
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue