1/* 2 * Copyright (c) 2023 Intel Corporation 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 .equ PMU_BASE, 0x4200000 8 .equ PMU_STATUS_REG, (PMU_BASE + 0xF00) 9 .equ PMU_SCRATCHPAD0, (PMU_BASE + 0xF04) 10 .equ PMU_SCRATCHPAD1, (PMU_BASE + 0xF08) 11 .equ PMU_PG_EN_REG, (PMU_BASE + 0xF10) 12 13 .equ PMU_STATUS_PG, (1 << 4) 14 .equ PMU_STATUS_PG_AON, (1 << 5) 15 16 .equ PMU_PG_EN, (1 << 0) 17 .equ PMU_PG_EXIT_COMPLETE, (1 << 8) 18 19 .equ FWST_AON_STATE_MASK, (0x7 << 24) 20 .equ FWST_AON_STATE_HALT, (0x2 << 24) 21 22 .equ EFLAGS_NT, (1 << 14) 23 24 .equ TSS_ESP0_OFFSET, 0x4 25 .equ TSS_LDT_SEG_SEL_OFFSET, 0x60 26 27 .equ AON_CS, 0x4 28 .equ AON_DS, 0xc 29 30 31 .global ipapg 32ipapg: 33 push %ebp 34 push %edi 35 push %esi 36 push %ebx 37 mov %cr0, %eax 38 push %eax 39 mov %cr4, %eax 40 push %eax 41 42 clts 43 44 #write down return address for ROM 45 movl $(PMU_STATUS_PG|PMU_STATUS_PG_AON), PMU_STATUS_REG 46 movl $out_of_pg, %eax 47 movl %eax, PMU_SCRATCHPAD0 48 movl (%eax), %eax 49 movl %eax, PMU_SCRATCHPAD1 50 51 #enable IPAPG, we will actually enter PG on the next halt 52 movl $(PMU_PG_EN|PMU_PG_EXIT_COMPLETE), PMU_PG_EN_REG 53 54 #save esp so we can restore stack after returning from ROM 55 lea aon_tss, %eax 56 movl %esp, TSS_ESP0_OFFSET(%eax) 57 58 sti 59 hlt 60 61 #unreachable 62 63 64 #got out of IPAPG, jumped here from ROM if there was no abort condition 65out_of_pg: 66 cli 67 68 #restore stack 69 lea aon_tss, %eax 70 movl TSS_ESP0_OFFSET(%eax), %esp 71 72 #set the nested task bit in eflags 73 pushfl 74 orl $EFLAGS_NT, (%esp) 75 popfl 76 77 clts 78 fninit 79 80 #restore non-volatile registers and CR0 & CR4 81 pop %eax 82 mov %eax, %cr4 83 pop %eax 84 mov %eax, %cr0 85 pop %ebx 86 pop %esi 87 pop %edi 88 pop %ebp 89 90 #check if we're indeed after IPAPG exit 91 testl $PMU_STATUS_PG, PMU_STATUS_REG 92 jz after_pg 93 94 #we didn't go through ROM, clear PG_EN bit and return an abort condition to AON 95 movl $0, PMU_PG_EN_REG 96 movl $0, %eax 97 jmp return_to_aon 98 99after_pg: 100 #return to caller that we got ouf of PG 101 movl $1, %eax 102 103return_to_aon: 104 movl $0, PMU_STATUS_REG 105 106 #return to AON task (still with ROM GDT and segments in case of PG exit) 107 ret 108 109 .global pg_exit_save_ctx 110pg_exit_save_ctx: 111 sgdtl mainfw_gdt 112 str tr 113 ret 114 115 .global pg_exit_restore_ctx 116pg_exit_restore_ctx: 117 118 #load RTOS GDT and AON task 119 lgdtl mainfw_gdt 120 ltr tr 121 122 #load AON LDT and segments 123 lea aon_tss, %eax 124 lldt TSS_LDT_SEG_SEL_OFFSET(%eax) 125 mov $AON_DS, %ax 126 mov %ax, %ds 127 mov %ax, %es 128 mov %ax, %fs 129 mov %ax, %gs 130 mov %ax, %ss 131 ljmpl $AON_CS, $cont 132 133cont: 134 nop 135 ret 136