acpi_wakeup.c revision 236772
1236772Siwasaki/*-
2236772Siwasaki * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
3236772Siwasaki * Copyright (c) 2001-2012 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4236772Siwasaki * Copyright (c) 2003 Peter Wemm
5236772Siwasaki * Copyright (c) 2008-2012 Jung-uk Kim <jkim@FreeBSD.org>
6236772Siwasaki * All rights reserved.
7236772Siwasaki *
8236772Siwasaki * Redistribution and use in source and binary forms, with or without
9236772Siwasaki * modification, are permitted provided that the following conditions
10236772Siwasaki * are met:
11236772Siwasaki * 1. Redistributions of source code must retain the above copyright
12236772Siwasaki *    notice, this list of conditions and the following disclaimer.
13236772Siwasaki * 2. Redistributions in binary form must reproduce the above copyright
14236772Siwasaki *    notice, this list of conditions and the following disclaimer in the
15236772Siwasaki *    documentation and/or other materials provided with the distribution.
16236772Siwasaki *
17236772Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18236772Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19236772Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20236772Siwasaki * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21236772Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22236772Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23236772Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24236772Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25236772Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26236772Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27236772Siwasaki * SUCH DAMAGE.
28236772Siwasaki */
29236772Siwasaki
30236772Siwasaki#include <sys/cdefs.h>
31236772Siwasaki__FBSDID("$FreeBSD: head/sys/x86/acpica/acpi_wakeup.c 236772 2012-06-09 00:37:26Z iwasaki $");
32236772Siwasaki
33236772Siwasaki#include <sys/param.h>
34236772Siwasaki#include <sys/bus.h>
35236772Siwasaki#include <sys/eventhandler.h>
36236772Siwasaki#include <sys/kernel.h>
37236772Siwasaki#include <sys/malloc.h>
38236772Siwasaki#include <sys/memrange.h>
39236772Siwasaki#include <sys/smp.h>
40236772Siwasaki
41236772Siwasaki#include <vm/vm.h>
42236772Siwasaki#include <vm/pmap.h>
43236772Siwasaki
44236772Siwasaki#include <machine/clock.h>
45236772Siwasaki#include <machine/intr_machdep.h>
46236772Siwasaki#include <x86/mca.h>
47236772Siwasaki#include <machine/pcb.h>
48236772Siwasaki#include <machine/pmap.h>
49236772Siwasaki#include <machine/specialreg.h>
50236772Siwasaki#include <machine/md_var.h>
51236772Siwasaki
52236772Siwasaki#ifdef SMP
53236772Siwasaki#include <x86/apicreg.h>
54236772Siwasaki#include <machine/smp.h>
55236772Siwasaki#include <machine/vmparam.h>
56236772Siwasaki#endif
57236772Siwasaki
58236772Siwasaki#include <contrib/dev/acpica/include/acpi.h>
59236772Siwasaki
60236772Siwasaki#include <dev/acpica/acpivar.h>
61236772Siwasaki
62236772Siwasaki#include "acpi_wakecode.h"
63236772Siwasaki#include "acpi_wakedata.h"
64236772Siwasaki
65236772Siwasaki/* Make sure the code is less than a page and leave room for the stack. */
66236772SiwasakiCTASSERT(sizeof(wakecode) < PAGE_SIZE - 1024);
67236772Siwasaki
68236772Siwasakiextern int		acpi_resume_beep;
69236772Siwasakiextern int		acpi_reset_video;
70236772Siwasaki
71236772Siwasaki#ifdef SMP
72236772Siwasakiextern struct pcb	**susppcbs;
73236772Siwasakistatic cpuset_t		suspcpus;
74236772Siwasaki#else
75236772Siwasakistatic struct pcb	**susppcbs;
76236772Siwasaki#endif
77236772Siwasaki
78236772Siwasakistatic void		*acpi_alloc_wakeup_handler(void);
79236772Siwasakistatic void		acpi_stop_beep(void *);
80236772Siwasaki
81236772Siwasaki#ifdef SMP
82236772Siwasakistatic int		acpi_wakeup_ap(struct acpi_softc *, int);
83236772Siwasakistatic void		acpi_wakeup_cpus(struct acpi_softc *);
84236772Siwasaki#endif
85236772Siwasaki
86236772Siwasaki#ifdef __amd64__
87236772Siwasaki#define ACPI_PAGETABLES	3
88236772Siwasaki#else
89236772Siwasaki#define ACPI_PAGETABLES	0
90236772Siwasaki#endif
91236772Siwasaki
92236772Siwasaki#define	WAKECODE_VADDR(sc)	((sc)->acpi_wakeaddr + (ACPI_PAGETABLES * PAGE_SIZE))
93236772Siwasaki#define	WAKECODE_PADDR(sc)	((sc)->acpi_wakephys + (ACPI_PAGETABLES * PAGE_SIZE))
94236772Siwasaki#define	WAKECODE_FIXUP(offset, type, val) do	{	\
95236772Siwasaki	type	*addr;					\
96236772Siwasaki	addr = (type *)(WAKECODE_VADDR(sc) + offset);	\
97236772Siwasaki	*addr = val;					\
98236772Siwasaki} while (0)
99236772Siwasaki
100236772Siwasakistatic void
101236772Siwasakiacpi_stop_beep(void *arg)
102236772Siwasaki{
103236772Siwasaki
104236772Siwasaki	if (acpi_resume_beep != 0)
105236772Siwasaki		timer_spkr_release();
106236772Siwasaki}
107236772Siwasaki
108236772Siwasaki#ifdef SMP
109236772Siwasakistatic int
110236772Siwasakiacpi_wakeup_ap(struct acpi_softc *sc, int cpu)
111236772Siwasaki{
112236772Siwasaki	int		vector = (WAKECODE_PADDR(sc) >> 12) & 0xff;
113236772Siwasaki	int		apic_id = cpu_apic_ids[cpu];
114236772Siwasaki	int		ms;
115236772Siwasaki
116236772Siwasaki	WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[cpu]);
117236772Siwasaki	WAKECODE_FIXUP(wakeup_gdt, uint16_t, susppcbs[cpu]->pcb_gdt.rd_limit);
118236772Siwasaki	WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
119236772Siwasaki	    susppcbs[cpu]->pcb_gdt.rd_base);
120236772Siwasaki
121236772Siwasaki	/* do an INIT IPI: assert RESET */
122236772Siwasaki	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
123236772Siwasaki	    APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
124236772Siwasaki
125236772Siwasaki	/* wait for pending status end */
126236772Siwasaki	lapic_ipi_wait(-1);
127236772Siwasaki
128236772Siwasaki	/* do an INIT IPI: deassert RESET */
129236772Siwasaki	lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
130236772Siwasaki	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
131236772Siwasaki
132236772Siwasaki	/* wait for pending status end */
133236772Siwasaki	DELAY(10000);		/* wait ~10mS */
134236772Siwasaki	lapic_ipi_wait(-1);
135236772Siwasaki
136236772Siwasaki	/*
137236772Siwasaki	 * next we do a STARTUP IPI: the previous INIT IPI might still be
138236772Siwasaki	 * latched, (P5 bug) this 1st STARTUP would then terminate
139236772Siwasaki	 * immediately, and the previously started INIT IPI would continue. OR
140236772Siwasaki	 * the previous INIT IPI has already run. and this STARTUP IPI will
141236772Siwasaki	 * run. OR the previous INIT IPI was ignored. and this STARTUP IPI
142236772Siwasaki	 * will run.
143236772Siwasaki	 */
144236772Siwasaki
145236772Siwasaki	/* do a STARTUP IPI */
146236772Siwasaki	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
147236772Siwasaki	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
148236772Siwasaki	    vector, apic_id);
149236772Siwasaki	lapic_ipi_wait(-1);
150236772Siwasaki	DELAY(200);		/* wait ~200uS */
151236772Siwasaki
152236772Siwasaki	/*
153236772Siwasaki	 * finally we do a 2nd STARTUP IPI: this 2nd STARTUP IPI should run IF
154236772Siwasaki	 * the previous STARTUP IPI was cancelled by a latched INIT IPI. OR
155236772Siwasaki	 * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
156236772Siwasaki	 * recognized after hardware RESET or INIT IPI.
157236772Siwasaki	 */
158236772Siwasaki
159236772Siwasaki	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
160236772Siwasaki	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
161236772Siwasaki	    vector, apic_id);
162236772Siwasaki	lapic_ipi_wait(-1);
163236772Siwasaki	DELAY(200);		/* wait ~200uS */
164236772Siwasaki
165236772Siwasaki	/* Wait up to 5 seconds for it to resume. */
166236772Siwasaki	for (ms = 0; ms < 5000; ms++) {
167236772Siwasaki		if (!CPU_ISSET(cpu, &suspended_cpus))
168236772Siwasaki			return (1);	/* return SUCCESS */
169236772Siwasaki		DELAY(1000);
170236772Siwasaki	}
171236772Siwasaki	return (0);		/* return FAILURE */
172236772Siwasaki}
173236772Siwasaki
174236772Siwasaki#define	WARMBOOT_TARGET		0
175236772Siwasaki#define	WARMBOOT_OFF		(KERNBASE + 0x0467)
176236772Siwasaki#define	WARMBOOT_SEG		(KERNBASE + 0x0469)
177236772Siwasaki
178236772Siwasaki#define	CMOS_REG		(0x70)
179236772Siwasaki#define	CMOS_DATA		(0x71)
180236772Siwasaki#define	BIOS_RESET		(0x0f)
181236772Siwasaki#define	BIOS_WARM		(0x0a)
182236772Siwasaki
183236772Siwasakistatic void
184236772Siwasakiacpi_wakeup_cpus(struct acpi_softc *sc)
185236772Siwasaki{
186236772Siwasaki	uint32_t	mpbioswarmvec;
187236772Siwasaki	int		cpu;
188236772Siwasaki	u_char		mpbiosreason;
189236772Siwasaki
190236772Siwasaki	/* save the current value of the warm-start vector */
191236772Siwasaki	mpbioswarmvec = *((uint32_t *)WARMBOOT_OFF);
192236772Siwasaki	outb(CMOS_REG, BIOS_RESET);
193236772Siwasaki	mpbiosreason = inb(CMOS_DATA);
194236772Siwasaki
195236772Siwasaki	/* setup a vector to our boot code */
196236772Siwasaki	*((volatile u_short *)WARMBOOT_OFF) = WARMBOOT_TARGET;
197236772Siwasaki	*((volatile u_short *)WARMBOOT_SEG) = WAKECODE_PADDR(sc) >> 4;
198236772Siwasaki	outb(CMOS_REG, BIOS_RESET);
199236772Siwasaki	outb(CMOS_DATA, BIOS_WARM);	/* 'warm-start' */
200236772Siwasaki
201236772Siwasaki	/* Wake up each AP. */
202236772Siwasaki	for (cpu = 1; cpu < mp_ncpus; cpu++) {
203236772Siwasaki		if (!CPU_ISSET(cpu, &suspcpus))
204236772Siwasaki			continue;
205236772Siwasaki		if (acpi_wakeup_ap(sc, cpu) == 0) {
206236772Siwasaki			/* restore the warmstart vector */
207236772Siwasaki			*(uint32_t *)WARMBOOT_OFF = mpbioswarmvec;
208236772Siwasaki			panic("acpi_wakeup: failed to resume AP #%d (PHY #%d)",
209236772Siwasaki			    cpu, cpu_apic_ids[cpu]);
210236772Siwasaki		}
211236772Siwasaki	}
212236772Siwasaki
213236772Siwasaki	/* restore the warmstart vector */
214236772Siwasaki	*(uint32_t *)WARMBOOT_OFF = mpbioswarmvec;
215236772Siwasaki
216236772Siwasaki	outb(CMOS_REG, BIOS_RESET);
217236772Siwasaki	outb(CMOS_DATA, mpbiosreason);
218236772Siwasaki}
219236772Siwasaki#endif
220236772Siwasaki
221236772Siwasakiint
222236772Siwasakiacpi_sleep_machdep(struct acpi_softc *sc, int state)
223236772Siwasaki{
224236772Siwasaki	ACPI_STATUS	status;
225236772Siwasaki
226236772Siwasaki	if (sc->acpi_wakeaddr == 0ul)
227236772Siwasaki		return (-1);	/* couldn't alloc wake memory */
228236772Siwasaki
229236772Siwasaki#ifdef SMP
230236772Siwasaki	suspcpus = all_cpus;
231236772Siwasaki	CPU_CLR(PCPU_GET(cpuid), &suspcpus);
232236772Siwasaki#endif
233236772Siwasaki
234236772Siwasaki	if (acpi_resume_beep != 0)
235236772Siwasaki		timer_spkr_acquire();
236236772Siwasaki
237236772Siwasaki	AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));
238236772Siwasaki
239236772Siwasaki	intr_suspend();
240236772Siwasaki
241236772Siwasaki	if (savectx(susppcbs[0])) {
242236772Siwasaki#ifdef __amd64__
243236772Siwasaki		ctx_fpusave(susppcbs[0]->pcb_fpususpend);
244236772Siwasaki#endif
245236772Siwasaki#ifdef SMP
246236772Siwasaki		if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) {
247236772Siwasaki			device_printf(sc->acpi_dev, "Failed to suspend APs\n");
248236772Siwasaki			return (0);	/* couldn't sleep */
249236772Siwasaki		}
250236772Siwasaki#endif
251236772Siwasaki
252236772Siwasaki		WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
253236772Siwasaki		WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
254236772Siwasaki
255236772Siwasaki		WAKECODE_FIXUP(wakeup_cr4, register_t, susppcbs[0]->pcb_cr4);
256236772Siwasaki		WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
257236772Siwasaki		WAKECODE_FIXUP(wakeup_gdt, uint16_t,
258236772Siwasaki		    susppcbs[0]->pcb_gdt.rd_limit);
259236772Siwasaki		WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
260236772Siwasaki		    susppcbs[0]->pcb_gdt.rd_base);
261236772Siwasaki
262236772Siwasaki		/* Call ACPICA to enter the desired sleep state */
263236772Siwasaki		if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
264236772Siwasaki			status = AcpiEnterSleepStateS4bios();
265236772Siwasaki		else
266236772Siwasaki			status = AcpiEnterSleepState(state, acpi_sleep_flags);
267236772Siwasaki		if (ACPI_FAILURE(status)) {
268236772Siwasaki			device_printf(sc->acpi_dev,
269236772Siwasaki			    "AcpiEnterSleepState failed - %s\n",
270236772Siwasaki			    AcpiFormatException(status));
271236772Siwasaki			return (0);	/* couldn't sleep */
272236772Siwasaki		}
273236772Siwasaki
274236772Siwasaki		for (;;)
275236772Siwasaki			ia32_pause();
276236772Siwasaki	}
277236772Siwasaki
278236772Siwasaki	return (1);	/* wakeup successfully */
279236772Siwasaki}
280236772Siwasaki
281236772Siwasakiint
282236772Siwasakiacpi_wakeup_machdep(struct acpi_softc *sc, int state, int sleep_result,
283236772Siwasaki    int intr_enabled)
284236772Siwasaki{
285236772Siwasaki
286236772Siwasaki	if (sleep_result == -1)
287236772Siwasaki		return (sleep_result);
288236772Siwasaki
289236772Siwasaki	if (!intr_enabled) {
290236772Siwasaki		/* Wakeup MD procedures in interrupt disabled context */
291236772Siwasaki		if (sleep_result == 1) {
292236772Siwasaki			pmap_init_pat();
293236772Siwasaki#if 0
294236772Siwasaki			load_cr3(susppcbs[0]->pcb_cr3);
295236772Siwasaki#endif
296236772Siwasaki			initializecpu();
297236772Siwasaki			PCPU_SET(switchtime, 0);
298236772Siwasaki			PCPU_SET(switchticks, ticks);
299236772Siwasaki#ifdef SMP
300236772Siwasaki			if (!CPU_EMPTY(&suspcpus))
301236772Siwasaki				acpi_wakeup_cpus(sc);
302236772Siwasaki#endif
303236772Siwasaki		}
304236772Siwasaki
305236772Siwasaki#ifdef SMP
306236772Siwasaki		if (!CPU_EMPTY(&suspcpus))
307236772Siwasaki			restart_cpus(suspcpus);
308236772Siwasaki#endif
309236772Siwasaki		mca_resume();
310236772Siwasaki		intr_resume();
311236772Siwasaki
312236772Siwasaki		AcpiSetFirmwareWakingVector(0);
313236772Siwasaki	} else {
314236772Siwasaki		/* Wakeup MD procedures in interrupt enabled context */
315236772Siwasaki		if (sleep_result == 1 && mem_range_softc.mr_op != NULL &&
316236772Siwasaki		    mem_range_softc.mr_op->reinit != NULL)
317236772Siwasaki			mem_range_softc.mr_op->reinit(&mem_range_softc);
318236772Siwasaki	}
319236772Siwasaki
320236772Siwasaki	return (sleep_result);
321236772Siwasaki}
322236772Siwasaki
323236772Siwasakistatic void *
324236772Siwasakiacpi_alloc_wakeup_handler(void)
325236772Siwasaki{
326236772Siwasaki	void		*wakeaddr;
327236772Siwasaki	int		i;
328236772Siwasaki
329236772Siwasaki	/*
330236772Siwasaki	 * Specify the region for our wakeup code.  We want it in the low 1 MB
331236772Siwasaki	 * region, excluding real mode IVT (0-0x3ff), BDA (0x400-0x4ff), EBDA
332236772Siwasaki	 * (less than 128KB, below 0xa0000, must be excluded by SMAP and DSDT),
333236772Siwasaki	 * and ROM area (0xa0000 and above).  The temporary page tables must be
334236772Siwasaki	 * page-aligned.
335236772Siwasaki	 */
336236772Siwasaki	wakeaddr = contigmalloc((ACPI_PAGETABLES + 1) * PAGE_SIZE, M_DEVBUF,
337236772Siwasaki	    M_WAITOK, 0x500, 0xa0000, PAGE_SIZE, 0ul);
338236772Siwasaki	if (wakeaddr == NULL) {
339236772Siwasaki		printf("%s: can't alloc wake memory\n", __func__);
340236772Siwasaki		return (NULL);
341236772Siwasaki	}
342236772Siwasaki	if (EVENTHANDLER_REGISTER(power_resume, acpi_stop_beep, NULL,
343236772Siwasaki	    EVENTHANDLER_PRI_LAST) == NULL) {
344236772Siwasaki		printf("%s: can't register event handler\n", __func__);
345236772Siwasaki		contigfree(wakeaddr, (ACPI_PAGETABLES + 1) * PAGE_SIZE, M_DEVBUF);
346236772Siwasaki		return (NULL);
347236772Siwasaki	}
348236772Siwasaki	susppcbs = malloc(mp_ncpus * sizeof(*susppcbs), M_DEVBUF, M_WAITOK);
349236772Siwasaki	for (i = 0; i < mp_ncpus; i++) {
350236772Siwasaki		susppcbs[i] = malloc(sizeof(**susppcbs), M_DEVBUF, M_WAITOK);
351236772Siwasaki#ifdef __amd64__
352236772Siwasaki		susppcbs[i]->pcb_fpususpend = alloc_fpusave(M_WAITOK);
353236772Siwasaki#endif
354236772Siwasaki	}
355236772Siwasaki
356236772Siwasaki	return (wakeaddr);
357236772Siwasaki}
358236772Siwasaki
359236772Siwasakivoid
360236772Siwasakiacpi_install_wakeup_handler(struct acpi_softc *sc)
361236772Siwasaki{
362236772Siwasaki	static void	*wakeaddr = NULL;
363236772Siwasaki#ifdef __amd64__
364236772Siwasaki	uint64_t	*pt4, *pt3, *pt2;
365236772Siwasaki	int		i;
366236772Siwasaki#endif
367236772Siwasaki
368236772Siwasaki	if (wakeaddr != NULL)
369236772Siwasaki		return;
370236772Siwasaki
371236772Siwasaki	wakeaddr = acpi_alloc_wakeup_handler();
372236772Siwasaki	if (wakeaddr == NULL)
373236772Siwasaki		return;
374236772Siwasaki
375236772Siwasaki	sc->acpi_wakeaddr = (vm_offset_t)wakeaddr;
376236772Siwasaki	sc->acpi_wakephys = vtophys(wakeaddr);
377236772Siwasaki
378236772Siwasaki	bcopy(wakecode, (void *)WAKECODE_VADDR(sc), sizeof(wakecode));
379236772Siwasaki
380236772Siwasaki	/* Patch GDT base address, ljmp targets. */
381236772Siwasaki	WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t,
382236772Siwasaki	    WAKECODE_PADDR(sc) + bootgdt);
383236772Siwasaki	WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t,
384236772Siwasaki	    WAKECODE_PADDR(sc) + wakeup_32);
385236772Siwasaki#ifdef __amd64__
386236772Siwasaki	WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
387236772Siwasaki	    WAKECODE_PADDR(sc) + wakeup_64);
388236772Siwasaki	WAKECODE_FIXUP(wakeup_pagetables, uint32_t, sc->acpi_wakephys);
389236772Siwasaki#endif
390236772Siwasaki
391236772Siwasaki	/* Save pointers to some global data. */
392236772Siwasaki	WAKECODE_FIXUP(wakeup_ret, void *, resumectx);
393236772Siwasaki#ifdef __amd64__
394236772Siwasaki	WAKECODE_FIXUP(wakeup_cr3, uint64_t, KPML4phys);
395236772Siwasaki#else
396236772Siwasaki#ifdef PAE
397236772Siwasaki	WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdpt));
398236772Siwasaki#else
399236772Siwasaki	WAKECODE_FIXUP(wakeup_cr3, register_t, vtophys(kernel_pmap->pm_pdir));
400236772Siwasaki#endif
401236772Siwasaki#endif
402236772Siwasaki
403236772Siwasaki#ifdef __amd64__
404236772Siwasaki	/* Build temporary page tables below realmode code. */
405236772Siwasaki	pt4 = wakeaddr;
406236772Siwasaki	pt3 = pt4 + (PAGE_SIZE) / sizeof(uint64_t);
407236772Siwasaki	pt2 = pt3 + (PAGE_SIZE) / sizeof(uint64_t);
408236772Siwasaki
409236772Siwasaki	/* Create the initial 1GB replicated page tables */
410236772Siwasaki	for (i = 0; i < 512; i++) {
411236772Siwasaki		/*
412236772Siwasaki		 * Each slot of the level 4 pages points
413236772Siwasaki		 * to the same level 3 page
414236772Siwasaki		 */
415236772Siwasaki		pt4[i] = (uint64_t)(sc->acpi_wakephys + PAGE_SIZE);
416236772Siwasaki		pt4[i] |= PG_V | PG_RW | PG_U;
417236772Siwasaki
418236772Siwasaki		/*
419236772Siwasaki		 * Each slot of the level 3 pages points
420236772Siwasaki		 * to the same level 2 page
421236772Siwasaki		 */
422236772Siwasaki		pt3[i] = (uint64_t)(sc->acpi_wakephys + (2 * PAGE_SIZE));
423236772Siwasaki		pt3[i] |= PG_V | PG_RW | PG_U;
424236772Siwasaki
425236772Siwasaki		/* The level 2 page slots are mapped with 2MB pages for 1GB. */
426236772Siwasaki		pt2[i] = i * (2 * 1024 * 1024);
427236772Siwasaki		pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
428236772Siwasaki	}
429236772Siwasaki#endif
430236772Siwasaki
431236772Siwasaki	if (bootverbose)
432236772Siwasaki		device_printf(sc->acpi_dev, "wakeup code va %#jx pa %#jx\n",
433236772Siwasaki		    (uintmax_t)sc->acpi_wakeaddr, (uintmax_t)sc->acpi_wakephys);
434236772Siwasaki}
435