1bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner/*
2bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner *  x86 SMM helpers
3bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner *
4bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner *  Copyright (c) 2003 Fabrice Bellard
5bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner *
6bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * This library is free software; you can redistribute it and/or
7bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * modify it under the terms of the GNU Lesser General Public
8bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * License as published by the Free Software Foundation; either
9bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * version 2 of the License, or (at your option) any later version.
10bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner *
11bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * This library is distributed in the hope that it will be useful,
12bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of
13bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * Lesser General Public License for more details.
15bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner *
16bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * You should have received a copy of the GNU Lesser General Public
17bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner */
19bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
20bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#include "cpu.h"
21bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#include "helper.h"
22bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
23bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner/* SMM support */
24bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
25bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#if defined(CONFIG_USER_ONLY)
26bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
27bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turnervoid do_smm_enter(CPUArchState *env1)
28bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner{
29bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner}
30bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
31bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turnervoid helper_rsm(CPUX86State *env)
32bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner{
33bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner}
34bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
35bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#else
36bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
37bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#ifdef TARGET_X86_64
38bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#define SMM_REVISION_ID 0x00020064
39bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#else
40bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#define SMM_REVISION_ID 0x00020000
41bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#endif
42bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
43bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turnervoid do_smm_enter(CPUArchState *env)
44bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner{
45bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    target_ulong sm_state;
46bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    SegmentCache *dt;
47bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    int i, offset;
48bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
49bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
50bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    log_cpu_state_mask(CPU_LOG_INT, ENV_GET_CPU(env), X86_DUMP_CCOP);
51bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
52bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->hflags |= HF_SMM_MASK;
53bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_smm_update(env);
54bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
55bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    sm_state = env->smbase + 0x8000;
56bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
57bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#ifdef TARGET_X86_64
58bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    for(i = 0; i < 6; i++) {
59bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        dt = &env->segs[i];
60bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        offset = 0x7e00 + i * 16;
61bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stw_phys(sm_state + offset, dt->selector);
62bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
63bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stl_phys(sm_state + offset + 4, dt->limit);
64bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stq_phys(sm_state + offset + 8, dt->base);
65bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    }
66bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
67bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7e68, env->gdt.base);
68bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7e64, env->gdt.limit);
69bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
70bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stw_phys(sm_state + 0x7e70, env->ldt.selector);
71bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7e78, env->ldt.base);
72bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7e74, env->ldt.limit);
73bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
74bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
75bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7e88, env->idt.base);
76bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7e84, env->idt.limit);
77bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
78bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stw_phys(sm_state + 0x7e90, env->tr.selector);
79bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7e98, env->tr.base);
80bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7e94, env->tr.limit);
81bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
82bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
83bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7ed0, env->efer);
84bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
85bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7ff8, EAX);
86bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7ff0, ECX);
87bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7fe8, EDX);
88bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7fe0, EBX);
89bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7fd8, ESP);
90bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7fd0, EBP);
91bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7fc8, ESI);
92bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7fc0, EDI);
93bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    for(i = 8; i < 16; i++)
94bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
95bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stq_phys(sm_state + 0x7f78, env->eip);
96bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f70, cpu_compute_eflags(env));
97bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f68, env->dr[6]);
98bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f60, env->dr[7]);
99bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
100bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f48, env->cr[4]);
101bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f50, env->cr[3]);
102bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f58, env->cr[0]);
103bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
104bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
105bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f00, env->smbase);
106bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#else
107bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7ffc, env->cr[0]);
108bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7ff8, env->cr[3]);
109bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7ff4, cpu_compute_eflags(env));
110bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7ff0, env->eip);
111bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fec, EDI);
112bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fe8, ESI);
113bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fe4, EBP);
114bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fe0, ESP);
115bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fdc, EBX);
116bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fd8, EDX);
117bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fd4, ECX);
118bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fd0, EAX);
119bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fcc, env->dr[6]);
120bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fc8, env->dr[7]);
121bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
122bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fc4, env->tr.selector);
123bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f64, env->tr.base);
124bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f60, env->tr.limit);
125bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
126bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
127bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
128bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f80, env->ldt.base);
129bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
130bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
131bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
132bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f74, env->gdt.base);
133bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f70, env->gdt.limit);
134bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
135bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f58, env->idt.base);
136bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f54, env->idt.limit);
137bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
138bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    for(i = 0; i < 6; i++) {
139bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        dt = &env->segs[i];
140bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        if (i < 3)
141bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner            offset = 0x7f84 + i * 12;
142bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        else
143bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner            offset = 0x7f2c + (i - 3) * 12;
144bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
145bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stl_phys(sm_state + offset + 8, dt->base);
146bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stl_phys(sm_state + offset + 4, dt->limit);
147bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
148bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    }
149bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7f14, env->cr[4]);
150bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
151bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
152bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    stl_phys(sm_state + 0x7ef8, env->smbase);
153bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#endif
154bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    /* init SMM cpu state */
155bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
156bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#ifdef TARGET_X86_64
157bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_load_efer(env, 0);
158bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#endif
159bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_load_eflags(env, 0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
160bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->eip = 0x00008000;
161bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
162bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                           0xffffffff, 0);
163bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
164bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
165bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
166bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
167bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
168bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
169bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr0(env,
170bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
171bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr4(env, 0);
172bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->dr[7] = 0x00000400;
173bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    CC_OP = CC_OP_EFLAGS;
174bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner}
175bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
176bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turnervoid helper_rsm(CPUX86State *env)
177bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner{
178bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    target_ulong sm_state;
179bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    int i, offset;
180bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    uint32_t val;
181bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
182bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    sm_state = env->smbase + 0x8000;
183bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#ifdef TARGET_X86_64
184bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
185bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
186bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    for(i = 0; i < 6; i++) {
187bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        offset = 0x7e00 + i * 16;
188bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        cpu_x86_load_seg_cache(env, i,
189bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               lduw_phys(sm_state + offset),
190bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               ldq_phys(sm_state + offset + 8),
191bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               ldl_phys(sm_state + offset + 4),
192bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
193bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    }
194bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
195bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->gdt.base = ldq_phys(sm_state + 0x7e68);
196bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
197bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
198bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
199bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.base = ldq_phys(sm_state + 0x7e78);
200bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
201bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
202bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
203bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->idt.base = ldq_phys(sm_state + 0x7e88);
204bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->idt.limit = ldl_phys(sm_state + 0x7e84);
205bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
206bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.selector = lduw_phys(sm_state + 0x7e90);
207bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.base = ldq_phys(sm_state + 0x7e98);
208bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.limit = ldl_phys(sm_state + 0x7e94);
209bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
210bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
211bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EAX = ldq_phys(sm_state + 0x7ff8);
212bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    ECX = ldq_phys(sm_state + 0x7ff0);
213bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EDX = ldq_phys(sm_state + 0x7fe8);
214bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EBX = ldq_phys(sm_state + 0x7fe0);
215bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    ESP = ldq_phys(sm_state + 0x7fd8);
216bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EBP = ldq_phys(sm_state + 0x7fd0);
217bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    ESI = ldq_phys(sm_state + 0x7fc8);
218bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EDI = ldq_phys(sm_state + 0x7fc0);
219bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    for(i = 8; i < 16; i++)
220bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
221bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->eip = ldq_phys(sm_state + 0x7f78);
222bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_load_eflags(env, ldl_phys(sm_state + 0x7f70),
223bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
224bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->dr[6] = ldl_phys(sm_state + 0x7f68);
225bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->dr[7] = ldl_phys(sm_state + 0x7f60);
226bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
227bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
228bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
229bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
230bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
231bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
232bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    if (val & 0x20000) {
233bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
234bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    }
235bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#else
236bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
237bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
238bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_load_eflags(env, ldl_phys(sm_state + 0x7ff4),
239bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
240bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->eip = ldl_phys(sm_state + 0x7ff0);
241bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EDI = ldl_phys(sm_state + 0x7fec);
242bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    ESI = ldl_phys(sm_state + 0x7fe8);
243bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EBP = ldl_phys(sm_state + 0x7fe4);
244bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    ESP = ldl_phys(sm_state + 0x7fe0);
245bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EBX = ldl_phys(sm_state + 0x7fdc);
246bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EDX = ldl_phys(sm_state + 0x7fd8);
247bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    ECX = ldl_phys(sm_state + 0x7fd4);
248bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    EAX = ldl_phys(sm_state + 0x7fd0);
249bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
250bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
251bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
252bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
253bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.base = ldl_phys(sm_state + 0x7f64);
254bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.limit = ldl_phys(sm_state + 0x7f60);
255bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
256bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
257bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
258bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.base = ldl_phys(sm_state + 0x7f80);
259bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
260bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
261bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
262bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->gdt.base = ldl_phys(sm_state + 0x7f74);
263bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
264bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
265bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->idt.base = ldl_phys(sm_state + 0x7f58);
266bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->idt.limit = ldl_phys(sm_state + 0x7f54);
267bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
268bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    for(i = 0; i < 6; i++) {
269bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        if (i < 3)
270bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner            offset = 0x7f84 + i * 12;
271bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        else
272bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner            offset = 0x7f2c + (i - 3) * 12;
273bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        cpu_x86_load_seg_cache(env, i,
274bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
275bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               ldl_phys(sm_state + offset + 8),
276bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               ldl_phys(sm_state + offset + 4),
277bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
278bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    }
279bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
280bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
281bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
282bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    if (val & 0x20000) {
283bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
284bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    }
285bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#endif
286bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    CC_OP = CC_OP_EFLAGS;
287bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    env->hflags &= ~HF_SMM_MASK;
288bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    cpu_smm_update(env);
289bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
290bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
291bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner    log_cpu_state_mask(CPU_LOG_INT, ENV_GET_CPU(env), X86_DUMP_CCOP);
292bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner}
293bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner
294bacb7c93a173b210f2be1f5ef4243b9b35d0b22bDavid 'Digit' Turner#endif /* !CONFIG_USER_ONLY */
295