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