Statistics
| Branch: | Revision:

root / hw / ppc.c @ 7bfe5777

History | View | Annotate | Download (40 kB)

1 a541f297 bellard
/*
2 e9df014c j_mayer
 * QEMU generic PowerPC hardware System Emulator
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 * Copyright (c) 2003-2007 Jocelyn Mayer
5 5fafdf24 ths
 *
6 a541f297 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 a541f297 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 a541f297 bellard
 * in the Software without restriction, including without limitation the rights
9 a541f297 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 a541f297 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 a541f297 bellard
 * furnished to do so, subject to the following conditions:
12 a541f297 bellard
 *
13 a541f297 bellard
 * The above copyright notice and this permission notice shall be included in
14 a541f297 bellard
 * all copies or substantial portions of the Software.
15 a541f297 bellard
 *
16 a541f297 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 a541f297 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 a541f297 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 a541f297 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 a541f297 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 a541f297 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 a541f297 bellard
 * THE SOFTWARE.
23 a541f297 bellard
 */
24 a541f297 bellard
#include "vl.h"
25 a541f297 bellard
26 e9df014c j_mayer
//#define PPC_DEBUG_IRQ
27 4b6d0a4c j_mayer
//#define PPC_DEBUG_TB
28 e9df014c j_mayer
29 47103572 j_mayer
extern FILE *logfile;
30 47103572 j_mayer
extern int loglevel;
31 47103572 j_mayer
32 dbdd2506 j_mayer
static void cpu_ppc_tb_stop (CPUState *env);
33 dbdd2506 j_mayer
static void cpu_ppc_tb_start (CPUState *env);
34 dbdd2506 j_mayer
35 00af685f j_mayer
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
36 47103572 j_mayer
{
37 47103572 j_mayer
    if (level) {
38 47103572 j_mayer
        env->pending_interrupts |= 1 << n_IRQ;
39 47103572 j_mayer
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
40 47103572 j_mayer
    } else {
41 47103572 j_mayer
        env->pending_interrupts &= ~(1 << n_IRQ);
42 47103572 j_mayer
        if (env->pending_interrupts == 0)
43 47103572 j_mayer
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
44 47103572 j_mayer
    }
45 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
46 a496775f j_mayer
    if (loglevel & CPU_LOG_INT) {
47 a496775f j_mayer
        fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
48 a496775f j_mayer
                __func__, env, n_IRQ, level,
49 a496775f j_mayer
                env->pending_interrupts, env->interrupt_request);
50 a496775f j_mayer
    }
51 47103572 j_mayer
#endif
52 47103572 j_mayer
}
53 47103572 j_mayer
54 e9df014c j_mayer
/* PowerPC 6xx / 7xx internal IRQ controller */
55 e9df014c j_mayer
static void ppc6xx_set_irq (void *opaque, int pin, int level)
56 d537cf6c pbrook
{
57 e9df014c j_mayer
    CPUState *env = opaque;
58 e9df014c j_mayer
    int cur_level;
59 d537cf6c pbrook
60 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
61 a496775f j_mayer
    if (loglevel & CPU_LOG_INT) {
62 a496775f j_mayer
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
63 a496775f j_mayer
                env, pin, level);
64 a496775f j_mayer
    }
65 e9df014c j_mayer
#endif
66 e9df014c j_mayer
    cur_level = (env->irq_input_state >> pin) & 1;
67 e9df014c j_mayer
    /* Don't generate spurious events */
68 24be5ae3 j_mayer
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
69 e9df014c j_mayer
        switch (pin) {
70 dbdd2506 j_mayer
        case PPC6xx_INPUT_TBEN:
71 dbdd2506 j_mayer
            /* Level sensitive - active high */
72 dbdd2506 j_mayer
#if defined(PPC_DEBUG_IRQ)
73 dbdd2506 j_mayer
            if (loglevel & CPU_LOG_INT) {
74 dbdd2506 j_mayer
                fprintf(logfile, "%s: %s the time base\n",
75 dbdd2506 j_mayer
                        __func__, level ? "start" : "stop");
76 dbdd2506 j_mayer
            }
77 dbdd2506 j_mayer
#endif
78 dbdd2506 j_mayer
            if (level) {
79 dbdd2506 j_mayer
                cpu_ppc_tb_start(env);
80 dbdd2506 j_mayer
            } else {
81 dbdd2506 j_mayer
                cpu_ppc_tb_stop(env);
82 dbdd2506 j_mayer
            }
83 24be5ae3 j_mayer
        case PPC6xx_INPUT_INT:
84 24be5ae3 j_mayer
            /* Level sensitive - active high */
85 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
86 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
87 a496775f j_mayer
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
88 a496775f j_mayer
                        __func__, level);
89 a496775f j_mayer
            }
90 e9df014c j_mayer
#endif
91 e9df014c j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
92 e9df014c j_mayer
            break;
93 24be5ae3 j_mayer
        case PPC6xx_INPUT_SMI:
94 e9df014c j_mayer
            /* Level sensitive - active high */
95 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
96 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
97 a496775f j_mayer
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
98 a496775f j_mayer
                        __func__, level);
99 a496775f j_mayer
            }
100 e9df014c j_mayer
#endif
101 e9df014c j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
102 e9df014c j_mayer
            break;
103 24be5ae3 j_mayer
        case PPC6xx_INPUT_MCP:
104 e9df014c j_mayer
            /* Negative edge sensitive */
105 e9df014c j_mayer
            /* XXX: TODO: actual reaction may depends on HID0 status
106 e9df014c j_mayer
             *            603/604/740/750: check HID0[EMCP]
107 e9df014c j_mayer
             */
108 e9df014c j_mayer
            if (cur_level == 1 && level == 0) {
109 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
110 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
111 a496775f j_mayer
                    fprintf(logfile, "%s: raise machine check state\n",
112 a496775f j_mayer
                            __func__);
113 a496775f j_mayer
                }
114 e9df014c j_mayer
#endif
115 e9df014c j_mayer
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
116 e9df014c j_mayer
            }
117 e9df014c j_mayer
            break;
118 24be5ae3 j_mayer
        case PPC6xx_INPUT_CKSTP_IN:
119 e9df014c j_mayer
            /* Level sensitive - active low */
120 e9df014c j_mayer
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
121 e63ecc6f j_mayer
            /* XXX: Note that the only way to restart the CPU is to reset it */
122 e9df014c j_mayer
            if (level) {
123 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
124 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
125 a496775f j_mayer
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
126 a496775f j_mayer
                }
127 e9df014c j_mayer
#endif
128 e9df014c j_mayer
                env->halted = 1;
129 e9df014c j_mayer
            }
130 e9df014c j_mayer
            break;
131 24be5ae3 j_mayer
        case PPC6xx_INPUT_HRESET:
132 e9df014c j_mayer
            /* Level sensitive - active low */
133 e9df014c j_mayer
            if (level) {
134 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
135 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
136 a496775f j_mayer
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
137 a496775f j_mayer
                }
138 e9df014c j_mayer
#endif
139 ef397e88 j_mayer
                env->interrupt_request |= CPU_INTERRUPT_EXITTB;
140 ef397e88 j_mayer
                /* XXX: TOFIX */
141 ef397e88 j_mayer
#if 0
142 ef397e88 j_mayer
                cpu_ppc_reset(env);
143 ef397e88 j_mayer
#else
144 ef397e88 j_mayer
                qemu_system_reset_request();
145 e9df014c j_mayer
#endif
146 e9df014c j_mayer
            }
147 e9df014c j_mayer
            break;
148 24be5ae3 j_mayer
        case PPC6xx_INPUT_SRESET:
149 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
150 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
151 a496775f j_mayer
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
152 a496775f j_mayer
                        __func__, level);
153 a496775f j_mayer
            }
154 e9df014c j_mayer
#endif
155 e9df014c j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
156 e9df014c j_mayer
            break;
157 e9df014c j_mayer
        default:
158 e9df014c j_mayer
            /* Unknown pin - do nothing */
159 e9df014c j_mayer
#if defined(PPC_DEBUG_IRQ)
160 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
161 a496775f j_mayer
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
162 a496775f j_mayer
            }
163 e9df014c j_mayer
#endif
164 e9df014c j_mayer
            return;
165 e9df014c j_mayer
        }
166 e9df014c j_mayer
        if (level)
167 e9df014c j_mayer
            env->irq_input_state |= 1 << pin;
168 e9df014c j_mayer
        else
169 e9df014c j_mayer
            env->irq_input_state &= ~(1 << pin);
170 d537cf6c pbrook
    }
171 d537cf6c pbrook
}
172 d537cf6c pbrook
173 e9df014c j_mayer
void ppc6xx_irq_init (CPUState *env)
174 47103572 j_mayer
{
175 e9df014c j_mayer
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
176 47103572 j_mayer
}
177 47103572 j_mayer
178 00af685f j_mayer
#if defined(TARGET_PPC64)
179 d0dfae6e j_mayer
/* PowerPC 970 internal IRQ controller */
180 d0dfae6e j_mayer
static void ppc970_set_irq (void *opaque, int pin, int level)
181 d0dfae6e j_mayer
{
182 d0dfae6e j_mayer
    CPUState *env = opaque;
183 d0dfae6e j_mayer
    int cur_level;
184 d0dfae6e j_mayer
185 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
186 d0dfae6e j_mayer
    if (loglevel & CPU_LOG_INT) {
187 d0dfae6e j_mayer
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
188 d0dfae6e j_mayer
                env, pin, level);
189 d0dfae6e j_mayer
    }
190 d0dfae6e j_mayer
#endif
191 d0dfae6e j_mayer
    cur_level = (env->irq_input_state >> pin) & 1;
192 d0dfae6e j_mayer
    /* Don't generate spurious events */
193 d0dfae6e j_mayer
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
194 d0dfae6e j_mayer
        switch (pin) {
195 d0dfae6e j_mayer
        case PPC970_INPUT_INT:
196 d0dfae6e j_mayer
            /* Level sensitive - active high */
197 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
198 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
199 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
200 d0dfae6e j_mayer
                        __func__, level);
201 d0dfae6e j_mayer
            }
202 d0dfae6e j_mayer
#endif
203 d0dfae6e j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
204 d0dfae6e j_mayer
            break;
205 d0dfae6e j_mayer
        case PPC970_INPUT_THINT:
206 d0dfae6e j_mayer
            /* Level sensitive - active high */
207 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
208 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
209 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
210 d0dfae6e j_mayer
                        level);
211 d0dfae6e j_mayer
            }
212 d0dfae6e j_mayer
#endif
213 d0dfae6e j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
214 d0dfae6e j_mayer
            break;
215 d0dfae6e j_mayer
        case PPC970_INPUT_MCP:
216 d0dfae6e j_mayer
            /* Negative edge sensitive */
217 d0dfae6e j_mayer
            /* XXX: TODO: actual reaction may depends on HID0 status
218 d0dfae6e j_mayer
             *            603/604/740/750: check HID0[EMCP]
219 d0dfae6e j_mayer
             */
220 d0dfae6e j_mayer
            if (cur_level == 1 && level == 0) {
221 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
222 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
223 d0dfae6e j_mayer
                    fprintf(logfile, "%s: raise machine check state\n",
224 d0dfae6e j_mayer
                            __func__);
225 d0dfae6e j_mayer
                }
226 d0dfae6e j_mayer
#endif
227 d0dfae6e j_mayer
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
228 d0dfae6e j_mayer
            }
229 d0dfae6e j_mayer
            break;
230 d0dfae6e j_mayer
        case PPC970_INPUT_CKSTP:
231 d0dfae6e j_mayer
            /* Level sensitive - active low */
232 d0dfae6e j_mayer
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
233 d0dfae6e j_mayer
            if (level) {
234 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
235 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
236 d0dfae6e j_mayer
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
237 d0dfae6e j_mayer
                }
238 d0dfae6e j_mayer
#endif
239 d0dfae6e j_mayer
                env->halted = 1;
240 d0dfae6e j_mayer
            } else {
241 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
242 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
243 d0dfae6e j_mayer
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
244 d0dfae6e j_mayer
                }
245 d0dfae6e j_mayer
#endif
246 d0dfae6e j_mayer
                env->halted = 0;
247 d0dfae6e j_mayer
            }
248 d0dfae6e j_mayer
            break;
249 d0dfae6e j_mayer
        case PPC970_INPUT_HRESET:
250 d0dfae6e j_mayer
            /* Level sensitive - active low */
251 d0dfae6e j_mayer
            if (level) {
252 d0dfae6e j_mayer
#if 0 // XXX: TOFIX
253 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
254 d0dfae6e j_mayer
                if (loglevel & CPU_LOG_INT) {
255 d0dfae6e j_mayer
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
256 d0dfae6e j_mayer
                }
257 d0dfae6e j_mayer
#endif
258 d0dfae6e j_mayer
                cpu_reset(env);
259 d0dfae6e j_mayer
#endif
260 d0dfae6e j_mayer
            }
261 d0dfae6e j_mayer
            break;
262 d0dfae6e j_mayer
        case PPC970_INPUT_SRESET:
263 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
264 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
265 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
266 d0dfae6e j_mayer
                        __func__, level);
267 d0dfae6e j_mayer
            }
268 d0dfae6e j_mayer
#endif
269 d0dfae6e j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
270 d0dfae6e j_mayer
            break;
271 d0dfae6e j_mayer
        case PPC970_INPUT_TBEN:
272 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
273 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
274 d0dfae6e j_mayer
                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
275 d0dfae6e j_mayer
                        level);
276 d0dfae6e j_mayer
            }
277 d0dfae6e j_mayer
#endif
278 d0dfae6e j_mayer
            /* XXX: TODO */
279 d0dfae6e j_mayer
            break;
280 d0dfae6e j_mayer
        default:
281 d0dfae6e j_mayer
            /* Unknown pin - do nothing */
282 d0dfae6e j_mayer
#if defined(PPC_DEBUG_IRQ)
283 d0dfae6e j_mayer
            if (loglevel & CPU_LOG_INT) {
284 d0dfae6e j_mayer
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
285 d0dfae6e j_mayer
            }
286 d0dfae6e j_mayer
#endif
287 d0dfae6e j_mayer
            return;
288 d0dfae6e j_mayer
        }
289 d0dfae6e j_mayer
        if (level)
290 d0dfae6e j_mayer
            env->irq_input_state |= 1 << pin;
291 d0dfae6e j_mayer
        else
292 d0dfae6e j_mayer
            env->irq_input_state &= ~(1 << pin);
293 d0dfae6e j_mayer
    }
294 d0dfae6e j_mayer
}
295 d0dfae6e j_mayer
296 d0dfae6e j_mayer
void ppc970_irq_init (CPUState *env)
297 d0dfae6e j_mayer
{
298 d0dfae6e j_mayer
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
299 d0dfae6e j_mayer
}
300 00af685f j_mayer
#endif /* defined(TARGET_PPC64) */
301 d0dfae6e j_mayer
302 4e290a0b j_mayer
/* PowerPC 40x internal IRQ controller */
303 4e290a0b j_mayer
static void ppc40x_set_irq (void *opaque, int pin, int level)
304 24be5ae3 j_mayer
{
305 24be5ae3 j_mayer
    CPUState *env = opaque;
306 24be5ae3 j_mayer
    int cur_level;
307 24be5ae3 j_mayer
308 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
309 8ecc7913 j_mayer
    if (loglevel & CPU_LOG_INT) {
310 8ecc7913 j_mayer
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
311 8ecc7913 j_mayer
                env, pin, level);
312 8ecc7913 j_mayer
    }
313 24be5ae3 j_mayer
#endif
314 24be5ae3 j_mayer
    cur_level = (env->irq_input_state >> pin) & 1;
315 24be5ae3 j_mayer
    /* Don't generate spurious events */
316 24be5ae3 j_mayer
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
317 24be5ae3 j_mayer
        switch (pin) {
318 4e290a0b j_mayer
        case PPC40x_INPUT_RESET_SYS:
319 8ecc7913 j_mayer
            if (level) {
320 8ecc7913 j_mayer
#if defined(PPC_DEBUG_IRQ)
321 8ecc7913 j_mayer
                if (loglevel & CPU_LOG_INT) {
322 8ecc7913 j_mayer
                    fprintf(logfile, "%s: reset the PowerPC system\n",
323 8ecc7913 j_mayer
                            __func__);
324 8ecc7913 j_mayer
                }
325 8ecc7913 j_mayer
#endif
326 8ecc7913 j_mayer
                ppc40x_system_reset(env);
327 8ecc7913 j_mayer
            }
328 8ecc7913 j_mayer
            break;
329 4e290a0b j_mayer
        case PPC40x_INPUT_RESET_CHIP:
330 8ecc7913 j_mayer
            if (level) {
331 8ecc7913 j_mayer
#if defined(PPC_DEBUG_IRQ)
332 8ecc7913 j_mayer
                if (loglevel & CPU_LOG_INT) {
333 8ecc7913 j_mayer
                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
334 8ecc7913 j_mayer
                }
335 8ecc7913 j_mayer
#endif
336 8ecc7913 j_mayer
                ppc40x_chip_reset(env);
337 8ecc7913 j_mayer
            }
338 8ecc7913 j_mayer
            break;
339 4e290a0b j_mayer
        case PPC40x_INPUT_RESET_CORE:
340 24be5ae3 j_mayer
            /* XXX: TODO: update DBSR[MRR] */
341 24be5ae3 j_mayer
            if (level) {
342 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
343 8ecc7913 j_mayer
                if (loglevel & CPU_LOG_INT) {
344 8ecc7913 j_mayer
                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
345 8ecc7913 j_mayer
                }
346 24be5ae3 j_mayer
#endif
347 8ecc7913 j_mayer
                ppc40x_core_reset(env);
348 24be5ae3 j_mayer
            }
349 24be5ae3 j_mayer
            break;
350 4e290a0b j_mayer
        case PPC40x_INPUT_CINT:
351 24be5ae3 j_mayer
            /* Level sensitive - active high */
352 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
353 8ecc7913 j_mayer
            if (loglevel & CPU_LOG_INT) {
354 8ecc7913 j_mayer
                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
355 8ecc7913 j_mayer
                        __func__, level);
356 8ecc7913 j_mayer
            }
357 24be5ae3 j_mayer
#endif
358 4e290a0b j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
359 24be5ae3 j_mayer
            break;
360 4e290a0b j_mayer
        case PPC40x_INPUT_INT:
361 24be5ae3 j_mayer
            /* Level sensitive - active high */
362 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
363 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
364 a496775f j_mayer
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
365 a496775f j_mayer
                        __func__, level);
366 a496775f j_mayer
            }
367 24be5ae3 j_mayer
#endif
368 24be5ae3 j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
369 24be5ae3 j_mayer
            break;
370 4e290a0b j_mayer
        case PPC40x_INPUT_HALT:
371 24be5ae3 j_mayer
            /* Level sensitive - active low */
372 24be5ae3 j_mayer
            if (level) {
373 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
374 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
375 a496775f j_mayer
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
376 a496775f j_mayer
                }
377 24be5ae3 j_mayer
#endif
378 24be5ae3 j_mayer
                env->halted = 1;
379 24be5ae3 j_mayer
            } else {
380 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
381 a496775f j_mayer
                if (loglevel & CPU_LOG_INT) {
382 a496775f j_mayer
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
383 a496775f j_mayer
                }
384 24be5ae3 j_mayer
#endif
385 24be5ae3 j_mayer
                env->halted = 0;
386 24be5ae3 j_mayer
            }
387 24be5ae3 j_mayer
            break;
388 4e290a0b j_mayer
        case PPC40x_INPUT_DEBUG:
389 24be5ae3 j_mayer
            /* Level sensitive - active high */
390 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
391 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
392 a750fc0b j_mayer
                fprintf(logfile, "%s: set the debug pin state to %d\n",
393 a496775f j_mayer
                        __func__, level);
394 a496775f j_mayer
            }
395 24be5ae3 j_mayer
#endif
396 a750fc0b j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
397 24be5ae3 j_mayer
            break;
398 24be5ae3 j_mayer
        default:
399 24be5ae3 j_mayer
            /* Unknown pin - do nothing */
400 24be5ae3 j_mayer
#if defined(PPC_DEBUG_IRQ)
401 a496775f j_mayer
            if (loglevel & CPU_LOG_INT) {
402 a496775f j_mayer
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
403 a496775f j_mayer
            }
404 24be5ae3 j_mayer
#endif
405 24be5ae3 j_mayer
            return;
406 24be5ae3 j_mayer
        }
407 24be5ae3 j_mayer
        if (level)
408 24be5ae3 j_mayer
            env->irq_input_state |= 1 << pin;
409 24be5ae3 j_mayer
        else
410 24be5ae3 j_mayer
            env->irq_input_state &= ~(1 << pin);
411 24be5ae3 j_mayer
    }
412 24be5ae3 j_mayer
}
413 24be5ae3 j_mayer
414 4e290a0b j_mayer
void ppc40x_irq_init (CPUState *env)
415 24be5ae3 j_mayer
{
416 4e290a0b j_mayer
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
417 4e290a0b j_mayer
                                                  env, PPC40x_INPUT_NB);
418 24be5ae3 j_mayer
}
419 24be5ae3 j_mayer
420 9fddaa0c bellard
/*****************************************************************************/
421 e9df014c j_mayer
/* PowerPC time base and decrementer emulation */
422 9fddaa0c bellard
struct ppc_tb_t {
423 9fddaa0c bellard
    /* Time base management */
424 dbdd2506 j_mayer
    int64_t  tb_offset;    /* Compensation                    */
425 dbdd2506 j_mayer
    int64_t  atb_offset;   /* Compensation                    */
426 dbdd2506 j_mayer
    uint32_t tb_freq;      /* TB frequency                    */
427 9fddaa0c bellard
    /* Decrementer management */
428 dbdd2506 j_mayer
    uint64_t decr_next;    /* Tick for next decr interrupt    */
429 dbdd2506 j_mayer
    uint32_t decr_freq;    /* decrementer frequency           */
430 9fddaa0c bellard
    struct QEMUTimer *decr_timer;
431 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
432 58a7d328 j_mayer
    /* Hypervisor decrementer management */
433 58a7d328 j_mayer
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
434 58a7d328 j_mayer
    struct QEMUTimer *hdecr_timer;
435 58a7d328 j_mayer
    uint64_t purr_load;
436 58a7d328 j_mayer
    uint64_t purr_start;
437 58a7d328 j_mayer
#endif
438 47103572 j_mayer
    void *opaque;
439 9fddaa0c bellard
};
440 9fddaa0c bellard
441 dbdd2506 j_mayer
static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
442 b068d6a7 j_mayer
                                              int64_t tb_offset)
443 9fddaa0c bellard
{
444 9fddaa0c bellard
    /* TB time in tb periods */
445 dbdd2506 j_mayer
    return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
446 9fddaa0c bellard
}
447 9fddaa0c bellard
448 9fddaa0c bellard
uint32_t cpu_ppc_load_tbl (CPUState *env)
449 9fddaa0c bellard
{
450 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
451 9fddaa0c bellard
    uint64_t tb;
452 9fddaa0c bellard
453 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
454 a062e36c j_mayer
#if defined(PPC_DEBUG_TB)
455 a062e36c j_mayer
    if (loglevel != 0) {
456 a062e36c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
457 9fddaa0c bellard
    }
458 9fddaa0c bellard
#endif
459 9fddaa0c bellard
460 9fddaa0c bellard
    return tb & 0xFFFFFFFF;
461 9fddaa0c bellard
}
462 9fddaa0c bellard
463 b068d6a7 j_mayer
static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
464 9fddaa0c bellard
{
465 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
466 9fddaa0c bellard
    uint64_t tb;
467 9fddaa0c bellard
468 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
469 4b6d0a4c j_mayer
#if defined(PPC_DEBUG_TB)
470 4b6d0a4c j_mayer
    if (loglevel != 0) {
471 a496775f j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
472 a496775f j_mayer
    }
473 9fddaa0c bellard
#endif
474 76a66253 j_mayer
475 9fddaa0c bellard
    return tb >> 32;
476 9fddaa0c bellard
}
477 9fddaa0c bellard
478 8a84de23 j_mayer
uint32_t cpu_ppc_load_tbu (CPUState *env)
479 8a84de23 j_mayer
{
480 8a84de23 j_mayer
    return _cpu_ppc_load_tbu(env);
481 8a84de23 j_mayer
}
482 8a84de23 j_mayer
483 dbdd2506 j_mayer
static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
484 b068d6a7 j_mayer
                                            int64_t *tb_offsetp,
485 b068d6a7 j_mayer
                                            uint64_t value)
486 9fddaa0c bellard
{
487 dbdd2506 j_mayer
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
488 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
489 4b6d0a4c j_mayer
    if (loglevel != 0) {
490 4b6d0a4c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
491 a062e36c j_mayer
                *tb_offsetp);
492 a496775f j_mayer
    }
493 9fddaa0c bellard
#endif
494 9fddaa0c bellard
}
495 9fddaa0c bellard
496 a062e36c j_mayer
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
497 a062e36c j_mayer
{
498 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
499 a062e36c j_mayer
    uint64_t tb;
500 a062e36c j_mayer
501 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
502 a062e36c j_mayer
    tb &= 0xFFFFFFFF00000000ULL;
503 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
504 dbdd2506 j_mayer
                     &tb_env->tb_offset, tb | (uint64_t)value);
505 a062e36c j_mayer
}
506 a062e36c j_mayer
507 b068d6a7 j_mayer
static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
508 9fddaa0c bellard
{
509 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
510 a062e36c j_mayer
    uint64_t tb;
511 9fddaa0c bellard
512 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
513 a062e36c j_mayer
    tb &= 0x00000000FFFFFFFFULL;
514 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
515 dbdd2506 j_mayer
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
516 9fddaa0c bellard
}
517 9fddaa0c bellard
518 8a84de23 j_mayer
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
519 8a84de23 j_mayer
{
520 8a84de23 j_mayer
    _cpu_ppc_store_tbu(env, value);
521 8a84de23 j_mayer
}
522 8a84de23 j_mayer
523 a062e36c j_mayer
uint32_t cpu_ppc_load_atbl (CPUState *env)
524 a062e36c j_mayer
{
525 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
526 a062e36c j_mayer
    uint64_t tb;
527 a062e36c j_mayer
528 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
529 a062e36c j_mayer
#if defined(PPC_DEBUG_TB)
530 a062e36c j_mayer
    if (loglevel != 0) {
531 a062e36c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
532 a062e36c j_mayer
    }
533 a062e36c j_mayer
#endif
534 a062e36c j_mayer
535 a062e36c j_mayer
    return tb & 0xFFFFFFFF;
536 a062e36c j_mayer
}
537 a062e36c j_mayer
538 a062e36c j_mayer
uint32_t cpu_ppc_load_atbu (CPUState *env)
539 a062e36c j_mayer
{
540 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
541 a062e36c j_mayer
    uint64_t tb;
542 a062e36c j_mayer
543 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
544 a062e36c j_mayer
#if defined(PPC_DEBUG_TB)
545 a062e36c j_mayer
    if (loglevel != 0) {
546 a062e36c j_mayer
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
547 a062e36c j_mayer
    }
548 a062e36c j_mayer
#endif
549 a062e36c j_mayer
550 a062e36c j_mayer
    return tb >> 32;
551 a062e36c j_mayer
}
552 a062e36c j_mayer
553 a062e36c j_mayer
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
554 a062e36c j_mayer
{
555 a062e36c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
556 a062e36c j_mayer
    uint64_t tb;
557 a062e36c j_mayer
558 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
559 a062e36c j_mayer
    tb &= 0xFFFFFFFF00000000ULL;
560 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
561 dbdd2506 j_mayer
                     &tb_env->atb_offset, tb | (uint64_t)value);
562 a062e36c j_mayer
}
563 a062e36c j_mayer
564 a062e36c j_mayer
void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
565 9fddaa0c bellard
{
566 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
567 a062e36c j_mayer
    uint64_t tb;
568 9fddaa0c bellard
569 dbdd2506 j_mayer
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
570 a062e36c j_mayer
    tb &= 0x00000000FFFFFFFFULL;
571 dbdd2506 j_mayer
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
572 dbdd2506 j_mayer
                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
573 dbdd2506 j_mayer
}
574 dbdd2506 j_mayer
575 dbdd2506 j_mayer
static void cpu_ppc_tb_stop (CPUState *env)
576 dbdd2506 j_mayer
{
577 dbdd2506 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
578 dbdd2506 j_mayer
    uint64_t tb, atb, vmclk;
579 dbdd2506 j_mayer
580 dbdd2506 j_mayer
    /* If the time base is already frozen, do nothing */
581 dbdd2506 j_mayer
    if (tb_env->tb_freq != 0) {
582 dbdd2506 j_mayer
        vmclk = qemu_get_clock(vm_clock);
583 dbdd2506 j_mayer
        /* Get the time base */
584 dbdd2506 j_mayer
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
585 dbdd2506 j_mayer
        /* Get the alternate time base */
586 dbdd2506 j_mayer
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
587 dbdd2506 j_mayer
        /* Store the time base value (ie compute the current offset) */
588 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
589 dbdd2506 j_mayer
        /* Store the alternate time base value (compute the current offset) */
590 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
591 dbdd2506 j_mayer
        /* Set the time base frequency to zero */
592 dbdd2506 j_mayer
        tb_env->tb_freq = 0;
593 dbdd2506 j_mayer
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
594 dbdd2506 j_mayer
    }
595 dbdd2506 j_mayer
}
596 dbdd2506 j_mayer
597 dbdd2506 j_mayer
static void cpu_ppc_tb_start (CPUState *env)
598 dbdd2506 j_mayer
{
599 dbdd2506 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
600 dbdd2506 j_mayer
    uint64_t tb, atb, vmclk;
601 dbdd2506 j_mayer
    
602 dbdd2506 j_mayer
    /* If the time base is not frozen, do nothing */
603 dbdd2506 j_mayer
    if (tb_env->tb_freq == 0) {
604 dbdd2506 j_mayer
        vmclk = qemu_get_clock(vm_clock);
605 dbdd2506 j_mayer
        /* Get the time base from tb_offset */
606 dbdd2506 j_mayer
        tb = tb_env->tb_offset;
607 dbdd2506 j_mayer
        /* Get the alternate time base from atb_offset */
608 dbdd2506 j_mayer
        atb = tb_env->atb_offset;
609 dbdd2506 j_mayer
        /* Restore the tb frequency from the decrementer frequency */
610 dbdd2506 j_mayer
        tb_env->tb_freq = tb_env->decr_freq;
611 dbdd2506 j_mayer
        /* Store the time base value */
612 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
613 dbdd2506 j_mayer
        /* Store the alternate time base value */
614 dbdd2506 j_mayer
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
615 dbdd2506 j_mayer
    }
616 9fddaa0c bellard
}
617 9fddaa0c bellard
618 b068d6a7 j_mayer
static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
619 b068d6a7 j_mayer
                                                  uint64_t *next)
620 9fddaa0c bellard
{
621 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
622 9fddaa0c bellard
    uint32_t decr;
623 4e588a4d bellard
    int64_t diff;
624 9fddaa0c bellard
625 4e588a4d bellard
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
626 4e588a4d bellard
    if (diff >= 0)
627 dbdd2506 j_mayer
        decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
628 4e588a4d bellard
    else
629 dbdd2506 j_mayer
        decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
630 4b6d0a4c j_mayer
#if defined(PPC_DEBUG_TB)
631 4b6d0a4c j_mayer
    if (loglevel != 0) {
632 a496775f j_mayer
        fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
633 a496775f j_mayer
    }
634 9fddaa0c bellard
#endif
635 76a66253 j_mayer
636 9fddaa0c bellard
    return decr;
637 9fddaa0c bellard
}
638 9fddaa0c bellard
639 58a7d328 j_mayer
uint32_t cpu_ppc_load_decr (CPUState *env)
640 58a7d328 j_mayer
{
641 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
642 58a7d328 j_mayer
643 58a7d328 j_mayer
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
644 58a7d328 j_mayer
}
645 58a7d328 j_mayer
646 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
647 58a7d328 j_mayer
uint32_t cpu_ppc_load_hdecr (CPUState *env)
648 58a7d328 j_mayer
{
649 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
650 58a7d328 j_mayer
651 58a7d328 j_mayer
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
652 58a7d328 j_mayer
}
653 58a7d328 j_mayer
654 58a7d328 j_mayer
uint64_t cpu_ppc_load_purr (CPUState *env)
655 58a7d328 j_mayer
{
656 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
657 58a7d328 j_mayer
    uint64_t diff;
658 58a7d328 j_mayer
659 58a7d328 j_mayer
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
660 b33c17e1 j_mayer
661 58a7d328 j_mayer
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
662 58a7d328 j_mayer
}
663 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
664 58a7d328 j_mayer
665 9fddaa0c bellard
/* When decrementer expires,
666 9fddaa0c bellard
 * all we need to do is generate or queue a CPU exception
667 9fddaa0c bellard
 */
668 b068d6a7 j_mayer
static always_inline void cpu_ppc_decr_excp (CPUState *env)
669 9fddaa0c bellard
{
670 9fddaa0c bellard
    /* Raise it */
671 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
672 4b6d0a4c j_mayer
    if (loglevel != 0) {
673 a496775f j_mayer
        fprintf(logfile, "raise decrementer exception\n");
674 a496775f j_mayer
    }
675 9fddaa0c bellard
#endif
676 47103572 j_mayer
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
677 9fddaa0c bellard
}
678 9fddaa0c bellard
679 b068d6a7 j_mayer
static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
680 58a7d328 j_mayer
{
681 58a7d328 j_mayer
    /* Raise it */
682 58a7d328 j_mayer
#ifdef PPC_DEBUG_TB
683 58a7d328 j_mayer
    if (loglevel != 0) {
684 58a7d328 j_mayer
        fprintf(logfile, "raise decrementer exception\n");
685 58a7d328 j_mayer
    }
686 58a7d328 j_mayer
#endif
687 58a7d328 j_mayer
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
688 58a7d328 j_mayer
}
689 58a7d328 j_mayer
690 58a7d328 j_mayer
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
691 b33c17e1 j_mayer
                                  struct QEMUTimer *timer,
692 b33c17e1 j_mayer
                                  void (*raise_excp)(CPUState *),
693 b33c17e1 j_mayer
                                  uint32_t decr, uint32_t value,
694 b33c17e1 j_mayer
                                  int is_excp)
695 9fddaa0c bellard
{
696 9fddaa0c bellard
    ppc_tb_t *tb_env = env->tb_env;
697 9fddaa0c bellard
    uint64_t now, next;
698 9fddaa0c bellard
699 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
700 4b6d0a4c j_mayer
    if (loglevel != 0) {
701 a496775f j_mayer
        fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
702 a496775f j_mayer
    }
703 9fddaa0c bellard
#endif
704 9fddaa0c bellard
    now = qemu_get_clock(vm_clock);
705 dbdd2506 j_mayer
    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
706 9fddaa0c bellard
    if (is_excp)
707 58a7d328 j_mayer
        next += *nextp - now;
708 9fddaa0c bellard
    if (next == now)
709 76a66253 j_mayer
        next++;
710 58a7d328 j_mayer
    *nextp = next;
711 9fddaa0c bellard
    /* Adjust timer */
712 58a7d328 j_mayer
    qemu_mod_timer(timer, next);
713 9fddaa0c bellard
    /* If we set a negative value and the decrementer was positive,
714 9fddaa0c bellard
     * raise an exception.
715 9fddaa0c bellard
     */
716 9fddaa0c bellard
    if ((value & 0x80000000) && !(decr & 0x80000000))
717 58a7d328 j_mayer
        (*raise_excp)(env);
718 58a7d328 j_mayer
}
719 58a7d328 j_mayer
720 b068d6a7 j_mayer
static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
721 b068d6a7 j_mayer
                                               uint32_t value, int is_excp)
722 58a7d328 j_mayer
{
723 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
724 58a7d328 j_mayer
725 58a7d328 j_mayer
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
726 58a7d328 j_mayer
                         &cpu_ppc_decr_excp, decr, value, is_excp);
727 9fddaa0c bellard
}
728 9fddaa0c bellard
729 9fddaa0c bellard
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
730 9fddaa0c bellard
{
731 9fddaa0c bellard
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
732 9fddaa0c bellard
}
733 9fddaa0c bellard
734 9fddaa0c bellard
static void cpu_ppc_decr_cb (void *opaque)
735 9fddaa0c bellard
{
736 9fddaa0c bellard
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
737 9fddaa0c bellard
}
738 9fddaa0c bellard
739 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
740 b068d6a7 j_mayer
static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
741 b068d6a7 j_mayer
                                                uint32_t value, int is_excp)
742 58a7d328 j_mayer
{
743 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
744 58a7d328 j_mayer
745 58a7d328 j_mayer
    __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
746 58a7d328 j_mayer
                         &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
747 58a7d328 j_mayer
}
748 58a7d328 j_mayer
749 58a7d328 j_mayer
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
750 58a7d328 j_mayer
{
751 58a7d328 j_mayer
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
752 58a7d328 j_mayer
}
753 58a7d328 j_mayer
754 58a7d328 j_mayer
static void cpu_ppc_hdecr_cb (void *opaque)
755 58a7d328 j_mayer
{
756 58a7d328 j_mayer
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
757 58a7d328 j_mayer
}
758 58a7d328 j_mayer
759 58a7d328 j_mayer
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
760 58a7d328 j_mayer
{
761 58a7d328 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
762 58a7d328 j_mayer
763 58a7d328 j_mayer
    tb_env->purr_load = value;
764 58a7d328 j_mayer
    tb_env->purr_start = qemu_get_clock(vm_clock);
765 58a7d328 j_mayer
}
766 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
767 58a7d328 j_mayer
768 8ecc7913 j_mayer
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
769 8ecc7913 j_mayer
{
770 8ecc7913 j_mayer
    CPUState *env = opaque;
771 8ecc7913 j_mayer
    ppc_tb_t *tb_env = env->tb_env;
772 8ecc7913 j_mayer
773 8ecc7913 j_mayer
    tb_env->tb_freq = freq;
774 dbdd2506 j_mayer
    tb_env->decr_freq = freq;
775 8ecc7913 j_mayer
    /* There is a bug in Linux 2.4 kernels:
776 8ecc7913 j_mayer
     * if a decrementer exception is pending when it enables msr_ee at startup,
777 8ecc7913 j_mayer
     * it's not ready to handle it...
778 8ecc7913 j_mayer
     */
779 8ecc7913 j_mayer
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
780 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
781 58a7d328 j_mayer
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
782 58a7d328 j_mayer
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
783 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
784 8ecc7913 j_mayer
}
785 8ecc7913 j_mayer
786 9fddaa0c bellard
/* Set up (once) timebase frequency (in Hz) */
787 8ecc7913 j_mayer
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
788 9fddaa0c bellard
{
789 9fddaa0c bellard
    ppc_tb_t *tb_env;
790 9fddaa0c bellard
791 9fddaa0c bellard
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
792 9fddaa0c bellard
    if (tb_env == NULL)
793 9fddaa0c bellard
        return NULL;
794 9fddaa0c bellard
    env->tb_env = tb_env;
795 8ecc7913 j_mayer
    /* Create new timer */
796 8ecc7913 j_mayer
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
797 58a7d328 j_mayer
#if defined(TARGET_PPC64H)
798 58a7d328 j_mayer
    tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
799 58a7d328 j_mayer
#endif /* defined(TARGET_PPC64H) */
800 8ecc7913 j_mayer
    cpu_ppc_set_tb_clk(env, freq);
801 9fddaa0c bellard
802 8ecc7913 j_mayer
    return &cpu_ppc_set_tb_clk;
803 9fddaa0c bellard
}
804 9fddaa0c bellard
805 76a66253 j_mayer
/* Specific helpers for POWER & PowerPC 601 RTC */
806 8ecc7913 j_mayer
clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
807 76a66253 j_mayer
{
808 76a66253 j_mayer
    return cpu_ppc_tb_init(env, 7812500);
809 76a66253 j_mayer
}
810 76a66253 j_mayer
811 76a66253 j_mayer
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
812 8a84de23 j_mayer
{
813 8a84de23 j_mayer
    _cpu_ppc_store_tbu(env, value);
814 8a84de23 j_mayer
}
815 76a66253 j_mayer
816 76a66253 j_mayer
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
817 8a84de23 j_mayer
{
818 8a84de23 j_mayer
    return _cpu_ppc_load_tbu(env);
819 8a84de23 j_mayer
}
820 76a66253 j_mayer
821 76a66253 j_mayer
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
822 76a66253 j_mayer
{
823 76a66253 j_mayer
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
824 76a66253 j_mayer
}
825 76a66253 j_mayer
826 76a66253 j_mayer
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
827 76a66253 j_mayer
{
828 76a66253 j_mayer
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
829 76a66253 j_mayer
}
830 76a66253 j_mayer
831 636aaad7 j_mayer
/*****************************************************************************/
832 76a66253 j_mayer
/* Embedded PowerPC timers */
833 636aaad7 j_mayer
834 636aaad7 j_mayer
/* PIT, FIT & WDT */
835 636aaad7 j_mayer
typedef struct ppcemb_timer_t ppcemb_timer_t;
836 636aaad7 j_mayer
struct ppcemb_timer_t {
837 636aaad7 j_mayer
    uint64_t pit_reload;  /* PIT auto-reload value        */
838 636aaad7 j_mayer
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
839 636aaad7 j_mayer
    struct QEMUTimer *fit_timer;
840 636aaad7 j_mayer
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
841 636aaad7 j_mayer
    struct QEMUTimer *wdt_timer;
842 636aaad7 j_mayer
};
843 3b46e624 ths
844 636aaad7 j_mayer
/* Fixed interval timer */
845 636aaad7 j_mayer
static void cpu_4xx_fit_cb (void *opaque)
846 636aaad7 j_mayer
{
847 636aaad7 j_mayer
    CPUState *env;
848 636aaad7 j_mayer
    ppc_tb_t *tb_env;
849 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
850 636aaad7 j_mayer
    uint64_t now, next;
851 636aaad7 j_mayer
852 636aaad7 j_mayer
    env = opaque;
853 636aaad7 j_mayer
    tb_env = env->tb_env;
854 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
855 636aaad7 j_mayer
    now = qemu_get_clock(vm_clock);
856 636aaad7 j_mayer
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
857 636aaad7 j_mayer
    case 0:
858 636aaad7 j_mayer
        next = 1 << 9;
859 636aaad7 j_mayer
        break;
860 636aaad7 j_mayer
    case 1:
861 636aaad7 j_mayer
        next = 1 << 13;
862 636aaad7 j_mayer
        break;
863 636aaad7 j_mayer
    case 2:
864 636aaad7 j_mayer
        next = 1 << 17;
865 636aaad7 j_mayer
        break;
866 636aaad7 j_mayer
    case 3:
867 636aaad7 j_mayer
        next = 1 << 21;
868 636aaad7 j_mayer
        break;
869 636aaad7 j_mayer
    default:
870 636aaad7 j_mayer
        /* Cannot occur, but makes gcc happy */
871 636aaad7 j_mayer
        return;
872 636aaad7 j_mayer
    }
873 636aaad7 j_mayer
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
874 636aaad7 j_mayer
    if (next == now)
875 636aaad7 j_mayer
        next++;
876 636aaad7 j_mayer
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
877 636aaad7 j_mayer
    env->spr[SPR_40x_TSR] |= 1 << 26;
878 636aaad7 j_mayer
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
879 636aaad7 j_mayer
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
880 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
881 4b6d0a4c j_mayer
    if (loglevel != 0) {
882 e96efcfc j_mayer
        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
883 e96efcfc j_mayer
                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
884 636aaad7 j_mayer
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
885 636aaad7 j_mayer
    }
886 4b6d0a4c j_mayer
#endif
887 636aaad7 j_mayer
}
888 636aaad7 j_mayer
889 636aaad7 j_mayer
/* Programmable interval timer */
890 4b6d0a4c j_mayer
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
891 76a66253 j_mayer
{
892 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
893 636aaad7 j_mayer
    uint64_t now, next;
894 636aaad7 j_mayer
895 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
896 4b6d0a4c j_mayer
    if (ppcemb_timer->pit_reload <= 1 ||
897 4b6d0a4c j_mayer
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
898 4b6d0a4c j_mayer
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
899 4b6d0a4c j_mayer
        /* Stop PIT */
900 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
901 4b6d0a4c j_mayer
        if (loglevel != 0) {
902 4b6d0a4c j_mayer
            fprintf(logfile, "%s: stop PIT\n", __func__);
903 4b6d0a4c j_mayer
        }
904 4b6d0a4c j_mayer
#endif
905 4b6d0a4c j_mayer
        qemu_del_timer(tb_env->decr_timer);
906 4b6d0a4c j_mayer
    } else {
907 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
908 4b6d0a4c j_mayer
        if (loglevel != 0) {
909 4b6d0a4c j_mayer
            fprintf(logfile, "%s: start PIT 0x" REGX "\n",
910 4b6d0a4c j_mayer
                    __func__, ppcemb_timer->pit_reload);
911 4b6d0a4c j_mayer
        }
912 4b6d0a4c j_mayer
#endif
913 4b6d0a4c j_mayer
        now = qemu_get_clock(vm_clock);
914 636aaad7 j_mayer
        next = now + muldiv64(ppcemb_timer->pit_reload,
915 dbdd2506 j_mayer
                              ticks_per_sec, tb_env->decr_freq);
916 4b6d0a4c j_mayer
        if (is_excp)
917 4b6d0a4c j_mayer
            next += tb_env->decr_next - now;
918 636aaad7 j_mayer
        if (next == now)
919 636aaad7 j_mayer
            next++;
920 636aaad7 j_mayer
        qemu_mod_timer(tb_env->decr_timer, next);
921 636aaad7 j_mayer
        tb_env->decr_next = next;
922 636aaad7 j_mayer
    }
923 4b6d0a4c j_mayer
}
924 4b6d0a4c j_mayer
925 4b6d0a4c j_mayer
static void cpu_4xx_pit_cb (void *opaque)
926 4b6d0a4c j_mayer
{
927 4b6d0a4c j_mayer
    CPUState *env;
928 4b6d0a4c j_mayer
    ppc_tb_t *tb_env;
929 4b6d0a4c j_mayer
    ppcemb_timer_t *ppcemb_timer;
930 4b6d0a4c j_mayer
931 4b6d0a4c j_mayer
    env = opaque;
932 4b6d0a4c j_mayer
    tb_env = env->tb_env;
933 4b6d0a4c j_mayer
    ppcemb_timer = tb_env->opaque;
934 636aaad7 j_mayer
    env->spr[SPR_40x_TSR] |= 1 << 27;
935 636aaad7 j_mayer
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
936 636aaad7 j_mayer
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
937 4b6d0a4c j_mayer
    start_stop_pit(env, tb_env, 1);
938 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
939 4b6d0a4c j_mayer
    if (loglevel != 0) {
940 e96efcfc j_mayer
        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
941 e96efcfc j_mayer
                "%016" PRIx64 "\n", __func__,
942 e96efcfc j_mayer
                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
943 e96efcfc j_mayer
                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
944 636aaad7 j_mayer
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
945 636aaad7 j_mayer
                ppcemb_timer->pit_reload);
946 636aaad7 j_mayer
    }
947 4b6d0a4c j_mayer
#endif
948 636aaad7 j_mayer
}
949 636aaad7 j_mayer
950 636aaad7 j_mayer
/* Watchdog timer */
951 636aaad7 j_mayer
static void cpu_4xx_wdt_cb (void *opaque)
952 636aaad7 j_mayer
{
953 636aaad7 j_mayer
    CPUState *env;
954 636aaad7 j_mayer
    ppc_tb_t *tb_env;
955 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
956 636aaad7 j_mayer
    uint64_t now, next;
957 636aaad7 j_mayer
958 636aaad7 j_mayer
    env = opaque;
959 636aaad7 j_mayer
    tb_env = env->tb_env;
960 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
961 636aaad7 j_mayer
    now = qemu_get_clock(vm_clock);
962 636aaad7 j_mayer
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
963 636aaad7 j_mayer
    case 0:
964 636aaad7 j_mayer
        next = 1 << 17;
965 636aaad7 j_mayer
        break;
966 636aaad7 j_mayer
    case 1:
967 636aaad7 j_mayer
        next = 1 << 21;
968 636aaad7 j_mayer
        break;
969 636aaad7 j_mayer
    case 2:
970 636aaad7 j_mayer
        next = 1 << 25;
971 636aaad7 j_mayer
        break;
972 636aaad7 j_mayer
    case 3:
973 636aaad7 j_mayer
        next = 1 << 29;
974 636aaad7 j_mayer
        break;
975 636aaad7 j_mayer
    default:
976 636aaad7 j_mayer
        /* Cannot occur, but makes gcc happy */
977 636aaad7 j_mayer
        return;
978 636aaad7 j_mayer
    }
979 dbdd2506 j_mayer
    next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
980 636aaad7 j_mayer
    if (next == now)
981 636aaad7 j_mayer
        next++;
982 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
983 4b6d0a4c j_mayer
    if (loglevel != 0) {
984 e96efcfc j_mayer
        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
985 636aaad7 j_mayer
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
986 636aaad7 j_mayer
    }
987 4b6d0a4c j_mayer
#endif
988 636aaad7 j_mayer
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
989 636aaad7 j_mayer
    case 0x0:
990 636aaad7 j_mayer
    case 0x1:
991 636aaad7 j_mayer
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
992 636aaad7 j_mayer
        ppcemb_timer->wdt_next = next;
993 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] |= 1 << 31;
994 636aaad7 j_mayer
        break;
995 636aaad7 j_mayer
    case 0x2:
996 636aaad7 j_mayer
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
997 636aaad7 j_mayer
        ppcemb_timer->wdt_next = next;
998 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] |= 1 << 30;
999 636aaad7 j_mayer
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
1000 636aaad7 j_mayer
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
1001 636aaad7 j_mayer
        break;
1002 636aaad7 j_mayer
    case 0x3:
1003 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] &= ~0x30000000;
1004 636aaad7 j_mayer
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
1005 636aaad7 j_mayer
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
1006 636aaad7 j_mayer
        case 0x0:
1007 636aaad7 j_mayer
            /* No reset */
1008 636aaad7 j_mayer
            break;
1009 636aaad7 j_mayer
        case 0x1: /* Core reset */
1010 8ecc7913 j_mayer
            ppc40x_core_reset(env);
1011 8ecc7913 j_mayer
            break;
1012 636aaad7 j_mayer
        case 0x2: /* Chip reset */
1013 8ecc7913 j_mayer
            ppc40x_chip_reset(env);
1014 8ecc7913 j_mayer
            break;
1015 636aaad7 j_mayer
        case 0x3: /* System reset */
1016 8ecc7913 j_mayer
            ppc40x_system_reset(env);
1017 8ecc7913 j_mayer
            break;
1018 636aaad7 j_mayer
        }
1019 636aaad7 j_mayer
    }
1020 76a66253 j_mayer
}
1021 76a66253 j_mayer
1022 76a66253 j_mayer
void store_40x_pit (CPUState *env, target_ulong val)
1023 76a66253 j_mayer
{
1024 636aaad7 j_mayer
    ppc_tb_t *tb_env;
1025 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
1026 636aaad7 j_mayer
1027 636aaad7 j_mayer
    tb_env = env->tb_env;
1028 636aaad7 j_mayer
    ppcemb_timer = tb_env->opaque;
1029 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1030 4b6d0a4c j_mayer
    if (loglevel != 0) {
1031 636aaad7 j_mayer
        fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
1032 a496775f j_mayer
    }
1033 4b6d0a4c j_mayer
#endif
1034 636aaad7 j_mayer
    ppcemb_timer->pit_reload = val;
1035 4b6d0a4c j_mayer
    start_stop_pit(env, tb_env, 0);
1036 76a66253 j_mayer
}
1037 76a66253 j_mayer
1038 636aaad7 j_mayer
target_ulong load_40x_pit (CPUState *env)
1039 76a66253 j_mayer
{
1040 636aaad7 j_mayer
    return cpu_ppc_load_decr(env);
1041 76a66253 j_mayer
}
1042 76a66253 j_mayer
1043 76a66253 j_mayer
void store_booke_tsr (CPUState *env, target_ulong val)
1044 76a66253 j_mayer
{
1045 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1046 4b6d0a4c j_mayer
    if (loglevel != 0) {
1047 4b6d0a4c j_mayer
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1048 4b6d0a4c j_mayer
    }
1049 4b6d0a4c j_mayer
#endif
1050 4b6d0a4c j_mayer
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1051 4b6d0a4c j_mayer
    if (val & 0x80000000)
1052 4b6d0a4c j_mayer
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
1053 636aaad7 j_mayer
}
1054 636aaad7 j_mayer
1055 636aaad7 j_mayer
void store_booke_tcr (CPUState *env, target_ulong val)
1056 636aaad7 j_mayer
{
1057 4b6d0a4c j_mayer
    ppc_tb_t *tb_env;
1058 4b6d0a4c j_mayer
1059 4b6d0a4c j_mayer
    tb_env = env->tb_env;
1060 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1061 4b6d0a4c j_mayer
    if (loglevel != 0) {
1062 4b6d0a4c j_mayer
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1063 4b6d0a4c j_mayer
    }
1064 4b6d0a4c j_mayer
#endif
1065 4b6d0a4c j_mayer
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1066 4b6d0a4c j_mayer
    start_stop_pit(env, tb_env, 1);
1067 8ecc7913 j_mayer
    cpu_4xx_wdt_cb(env);
1068 636aaad7 j_mayer
}
1069 636aaad7 j_mayer
1070 4b6d0a4c j_mayer
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1071 4b6d0a4c j_mayer
{
1072 4b6d0a4c j_mayer
    CPUState *env = opaque;
1073 4b6d0a4c j_mayer
    ppc_tb_t *tb_env = env->tb_env;
1074 4b6d0a4c j_mayer
1075 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1076 4b6d0a4c j_mayer
    if (loglevel != 0) {
1077 4b6d0a4c j_mayer
        fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
1078 4b6d0a4c j_mayer
    }
1079 4b6d0a4c j_mayer
#endif
1080 4b6d0a4c j_mayer
    tb_env->tb_freq = freq;
1081 dbdd2506 j_mayer
    tb_env->decr_freq = freq;
1082 4b6d0a4c j_mayer
    /* XXX: we should also update all timers */
1083 4b6d0a4c j_mayer
}
1084 4b6d0a4c j_mayer
1085 8ecc7913 j_mayer
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1086 636aaad7 j_mayer
{
1087 636aaad7 j_mayer
    ppc_tb_t *tb_env;
1088 636aaad7 j_mayer
    ppcemb_timer_t *ppcemb_timer;
1089 636aaad7 j_mayer
1090 8ecc7913 j_mayer
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1091 4b6d0a4c j_mayer
    if (tb_env == NULL) {
1092 8ecc7913 j_mayer
        return NULL;
1093 4b6d0a4c j_mayer
    }
1094 8ecc7913 j_mayer
    env->tb_env = tb_env;
1095 636aaad7 j_mayer
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1096 8ecc7913 j_mayer
    tb_env->tb_freq = freq;
1097 dbdd2506 j_mayer
    tb_env->decr_freq = freq;
1098 636aaad7 j_mayer
    tb_env->opaque = ppcemb_timer;
1099 4b6d0a4c j_mayer
#ifdef PPC_DEBUG_TB
1100 4b6d0a4c j_mayer
    if (loglevel != 0) {
1101 4b6d0a4c j_mayer
        fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
1102 4b6d0a4c j_mayer
                &ppc_emb_set_tb_clk);
1103 8ecc7913 j_mayer
    }
1104 4b6d0a4c j_mayer
#endif
1105 636aaad7 j_mayer
    if (ppcemb_timer != NULL) {
1106 636aaad7 j_mayer
        /* We use decr timer for PIT */
1107 636aaad7 j_mayer
        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1108 636aaad7 j_mayer
        ppcemb_timer->fit_timer =
1109 636aaad7 j_mayer
            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1110 636aaad7 j_mayer
        ppcemb_timer->wdt_timer =
1111 636aaad7 j_mayer
            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1112 636aaad7 j_mayer
    }
1113 8ecc7913 j_mayer
1114 4b6d0a4c j_mayer
    return &ppc_emb_set_tb_clk;
1115 76a66253 j_mayer
}
1116 76a66253 j_mayer
1117 2e719ba3 j_mayer
/*****************************************************************************/
1118 2e719ba3 j_mayer
/* Embedded PowerPC Device Control Registers */
1119 2e719ba3 j_mayer
typedef struct ppc_dcrn_t ppc_dcrn_t;
1120 2e719ba3 j_mayer
struct ppc_dcrn_t {
1121 2e719ba3 j_mayer
    dcr_read_cb dcr_read;
1122 2e719ba3 j_mayer
    dcr_write_cb dcr_write;
1123 2e719ba3 j_mayer
    void *opaque;
1124 2e719ba3 j_mayer
};
1125 2e719ba3 j_mayer
1126 a750fc0b j_mayer
/* XXX: on 460, DCR addresses are 32 bits wide,
1127 a750fc0b j_mayer
 *      using DCRIPR to get the 22 upper bits of the DCR address
1128 a750fc0b j_mayer
 */
1129 2e719ba3 j_mayer
#define DCRN_NB 1024
1130 2e719ba3 j_mayer
struct ppc_dcr_t {
1131 2e719ba3 j_mayer
    ppc_dcrn_t dcrn[DCRN_NB];
1132 2e719ba3 j_mayer
    int (*read_error)(int dcrn);
1133 2e719ba3 j_mayer
    int (*write_error)(int dcrn);
1134 2e719ba3 j_mayer
};
1135 2e719ba3 j_mayer
1136 2e719ba3 j_mayer
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1137 2e719ba3 j_mayer
{
1138 2e719ba3 j_mayer
    ppc_dcrn_t *dcr;
1139 2e719ba3 j_mayer
1140 2e719ba3 j_mayer
    if (dcrn < 0 || dcrn >= DCRN_NB)
1141 2e719ba3 j_mayer
        goto error;
1142 2e719ba3 j_mayer
    dcr = &dcr_env->dcrn[dcrn];
1143 2e719ba3 j_mayer
    if (dcr->dcr_read == NULL)
1144 2e719ba3 j_mayer
        goto error;
1145 2e719ba3 j_mayer
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1146 2e719ba3 j_mayer
1147 2e719ba3 j_mayer
    return 0;
1148 2e719ba3 j_mayer
1149 2e719ba3 j_mayer
 error:
1150 2e719ba3 j_mayer
    if (dcr_env->read_error != NULL)
1151 2e719ba3 j_mayer
        return (*dcr_env->read_error)(dcrn);
1152 2e719ba3 j_mayer
1153 2e719ba3 j_mayer
    return -1;
1154 2e719ba3 j_mayer
}
1155 2e719ba3 j_mayer
1156 2e719ba3 j_mayer
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1157 2e719ba3 j_mayer
{
1158 2e719ba3 j_mayer
    ppc_dcrn_t *dcr;
1159 2e719ba3 j_mayer
1160 2e719ba3 j_mayer
    if (dcrn < 0 || dcrn >= DCRN_NB)
1161 2e719ba3 j_mayer
        goto error;
1162 2e719ba3 j_mayer
    dcr = &dcr_env->dcrn[dcrn];
1163 2e719ba3 j_mayer
    if (dcr->dcr_write == NULL)
1164 2e719ba3 j_mayer
        goto error;
1165 2e719ba3 j_mayer
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1166 2e719ba3 j_mayer
1167 2e719ba3 j_mayer
    return 0;
1168 2e719ba3 j_mayer
1169 2e719ba3 j_mayer
 error:
1170 2e719ba3 j_mayer
    if (dcr_env->write_error != NULL)
1171 2e719ba3 j_mayer
        return (*dcr_env->write_error)(dcrn);
1172 2e719ba3 j_mayer
1173 2e719ba3 j_mayer
    return -1;
1174 2e719ba3 j_mayer
}
1175 2e719ba3 j_mayer
1176 2e719ba3 j_mayer
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1177 2e719ba3 j_mayer
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1178 2e719ba3 j_mayer
{
1179 2e719ba3 j_mayer
    ppc_dcr_t *dcr_env;
1180 2e719ba3 j_mayer
    ppc_dcrn_t *dcr;
1181 2e719ba3 j_mayer
1182 2e719ba3 j_mayer
    dcr_env = env->dcr_env;
1183 2e719ba3 j_mayer
    if (dcr_env == NULL)
1184 2e719ba3 j_mayer
        return -1;
1185 2e719ba3 j_mayer
    if (dcrn < 0 || dcrn >= DCRN_NB)
1186 2e719ba3 j_mayer
        return -1;
1187 2e719ba3 j_mayer
    dcr = &dcr_env->dcrn[dcrn];
1188 2e719ba3 j_mayer
    if (dcr->opaque != NULL ||
1189 2e719ba3 j_mayer
        dcr->dcr_read != NULL ||
1190 2e719ba3 j_mayer
        dcr->dcr_write != NULL)
1191 2e719ba3 j_mayer
        return -1;
1192 2e719ba3 j_mayer
    dcr->opaque = opaque;
1193 2e719ba3 j_mayer
    dcr->dcr_read = dcr_read;
1194 2e719ba3 j_mayer
    dcr->dcr_write = dcr_write;
1195 2e719ba3 j_mayer
1196 2e719ba3 j_mayer
    return 0;
1197 2e719ba3 j_mayer
}
1198 2e719ba3 j_mayer
1199 2e719ba3 j_mayer
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1200 2e719ba3 j_mayer
                  int (*write_error)(int dcrn))
1201 2e719ba3 j_mayer
{
1202 2e719ba3 j_mayer
    ppc_dcr_t *dcr_env;
1203 2e719ba3 j_mayer
1204 2e719ba3 j_mayer
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1205 2e719ba3 j_mayer
    if (dcr_env == NULL)
1206 2e719ba3 j_mayer
        return -1;
1207 2e719ba3 j_mayer
    dcr_env->read_error = read_error;
1208 2e719ba3 j_mayer
    dcr_env->write_error = write_error;
1209 2e719ba3 j_mayer
    env->dcr_env = dcr_env;
1210 2e719ba3 j_mayer
1211 2e719ba3 j_mayer
    return 0;
1212 2e719ba3 j_mayer
}
1213 2e719ba3 j_mayer
1214 9fddaa0c bellard
#if 0
1215 9fddaa0c bellard
/*****************************************************************************/
1216 9fddaa0c bellard
/* Handle system reset (for now, just stop emulation) */
1217 9fddaa0c bellard
void cpu_ppc_reset (CPUState *env)
1218 9fddaa0c bellard
{
1219 9fddaa0c bellard
    printf("Reset asked... Stop emulation\n");
1220 9fddaa0c bellard
    abort();
1221 9fddaa0c bellard
}
1222 9fddaa0c bellard
#endif
1223 9fddaa0c bellard
1224 64201201 bellard
/*****************************************************************************/
1225 64201201 bellard
/* Debug port */
1226 fd0bbb12 bellard
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1227 64201201 bellard
{
1228 64201201 bellard
    addr &= 0xF;
1229 64201201 bellard
    switch (addr) {
1230 64201201 bellard
    case 0:
1231 64201201 bellard
        printf("%c", val);
1232 64201201 bellard
        break;
1233 64201201 bellard
    case 1:
1234 64201201 bellard
        printf("\n");
1235 64201201 bellard
        fflush(stdout);
1236 64201201 bellard
        break;
1237 64201201 bellard
    case 2:
1238 64201201 bellard
        printf("Set loglevel to %04x\n", val);
1239 fd0bbb12 bellard
        cpu_set_log(val | 0x100);
1240 64201201 bellard
        break;
1241 64201201 bellard
    }
1242 64201201 bellard
}
1243 64201201 bellard
1244 64201201 bellard
/*****************************************************************************/
1245 64201201 bellard
/* NVRAM helpers */
1246 3cbee15b j_mayer
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1247 64201201 bellard
{
1248 3cbee15b j_mayer
    return (*nvram->read_fn)(nvram->opaque, addr);;
1249 64201201 bellard
}
1250 64201201 bellard
1251 3cbee15b j_mayer
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1252 64201201 bellard
{
1253 3cbee15b j_mayer
    (*nvram->write_fn)(nvram->opaque, addr, val);
1254 64201201 bellard
}
1255 64201201 bellard
1256 3cbee15b j_mayer
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1257 64201201 bellard
{
1258 3cbee15b j_mayer
    nvram_write(nvram, addr, value);
1259 64201201 bellard
}
1260 64201201 bellard
1261 3cbee15b j_mayer
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1262 3cbee15b j_mayer
{
1263 3cbee15b j_mayer
    return nvram_read(nvram, addr);
1264 3cbee15b j_mayer
}
1265 3cbee15b j_mayer
1266 3cbee15b j_mayer
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1267 3cbee15b j_mayer
{
1268 3cbee15b j_mayer
    nvram_write(nvram, addr, value >> 8);
1269 3cbee15b j_mayer
    nvram_write(nvram, addr + 1, value & 0xFF);
1270 3cbee15b j_mayer
}
1271 3cbee15b j_mayer
1272 3cbee15b j_mayer
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1273 64201201 bellard
{
1274 64201201 bellard
    uint16_t tmp;
1275 64201201 bellard
1276 3cbee15b j_mayer
    tmp = nvram_read(nvram, addr) << 8;
1277 3cbee15b j_mayer
    tmp |= nvram_read(nvram, addr + 1);
1278 3cbee15b j_mayer
1279 64201201 bellard
    return tmp;
1280 64201201 bellard
}
1281 64201201 bellard
1282 3cbee15b j_mayer
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1283 64201201 bellard
{
1284 3cbee15b j_mayer
    nvram_write(nvram, addr, value >> 24);
1285 3cbee15b j_mayer
    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1286 3cbee15b j_mayer
    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1287 3cbee15b j_mayer
    nvram_write(nvram, addr + 3, value & 0xFF);
1288 64201201 bellard
}
1289 64201201 bellard
1290 3cbee15b j_mayer
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1291 64201201 bellard
{
1292 64201201 bellard
    uint32_t tmp;
1293 64201201 bellard
1294 3cbee15b j_mayer
    tmp = nvram_read(nvram, addr) << 24;
1295 3cbee15b j_mayer
    tmp |= nvram_read(nvram, addr + 1) << 16;
1296 3cbee15b j_mayer
    tmp |= nvram_read(nvram, addr + 2) << 8;
1297 3cbee15b j_mayer
    tmp |= nvram_read(nvram, addr + 3);
1298 76a66253 j_mayer
1299 64201201 bellard
    return tmp;
1300 64201201 bellard
}
1301 64201201 bellard
1302 3cbee15b j_mayer
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1303 64201201 bellard
                       const unsigned char *str, uint32_t max)
1304 64201201 bellard
{
1305 64201201 bellard
    int i;
1306 64201201 bellard
1307 64201201 bellard
    for (i = 0; i < max && str[i] != '\0'; i++) {
1308 3cbee15b j_mayer
        nvram_write(nvram, addr + i, str[i]);
1309 64201201 bellard
    }
1310 3cbee15b j_mayer
    nvram_write(nvram, addr + i, str[i]);
1311 3cbee15b j_mayer
    nvram_write(nvram, addr + max - 1, '\0');
1312 64201201 bellard
}
1313 64201201 bellard
1314 3cbee15b j_mayer
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1315 64201201 bellard
{
1316 64201201 bellard
    int i;
1317 64201201 bellard
1318 64201201 bellard
    memset(dst, 0, max);
1319 64201201 bellard
    for (i = 0; i < max; i++) {
1320 64201201 bellard
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1321 64201201 bellard
        if (dst[i] == '\0')
1322 64201201 bellard
            break;
1323 64201201 bellard
    }
1324 64201201 bellard
1325 64201201 bellard
    return i;
1326 64201201 bellard
}
1327 64201201 bellard
1328 64201201 bellard
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1329 64201201 bellard
{
1330 64201201 bellard
    uint16_t tmp;
1331 64201201 bellard
    uint16_t pd, pd1, pd2;
1332 64201201 bellard
1333 64201201 bellard
    tmp = prev >> 8;
1334 64201201 bellard
    pd = prev ^ value;
1335 64201201 bellard
    pd1 = pd & 0x000F;
1336 64201201 bellard
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1337 64201201 bellard
    tmp ^= (pd1 << 3) | (pd1 << 8);
1338 64201201 bellard
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1339 64201201 bellard
1340 64201201 bellard
    return tmp;
1341 64201201 bellard
}
1342 64201201 bellard
1343 3cbee15b j_mayer
uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1344 64201201 bellard
{
1345 64201201 bellard
    uint32_t i;
1346 64201201 bellard
    uint16_t crc = 0xFFFF;
1347 64201201 bellard
    int odd;
1348 64201201 bellard
1349 64201201 bellard
    odd = count & 1;
1350 64201201 bellard
    count &= ~1;
1351 64201201 bellard
    for (i = 0; i != count; i++) {
1352 76a66253 j_mayer
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1353 64201201 bellard
    }
1354 64201201 bellard
    if (odd) {
1355 76a66253 j_mayer
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1356 64201201 bellard
    }
1357 64201201 bellard
1358 64201201 bellard
    return crc;
1359 64201201 bellard
}
1360 64201201 bellard
1361 fd0bbb12 bellard
#define CMDLINE_ADDR 0x017ff000
1362 fd0bbb12 bellard
1363 3cbee15b j_mayer
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1364 64201201 bellard
                          const unsigned char *arch,
1365 64201201 bellard
                          uint32_t RAM_size, int boot_device,
1366 64201201 bellard
                          uint32_t kernel_image, uint32_t kernel_size,
1367 fd0bbb12 bellard
                          const char *cmdline,
1368 64201201 bellard
                          uint32_t initrd_image, uint32_t initrd_size,
1369 fd0bbb12 bellard
                          uint32_t NVRAM_image,
1370 fd0bbb12 bellard
                          int width, int height, int depth)
1371 64201201 bellard
{
1372 64201201 bellard
    uint16_t crc;
1373 64201201 bellard
1374 64201201 bellard
    /* Set parameters for Open Hack'Ware BIOS */
1375 64201201 bellard
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1376 64201201 bellard
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1377 64201201 bellard
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1378 64201201 bellard
    NVRAM_set_string(nvram, 0x20, arch, 16);
1379 64201201 bellard
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1380 64201201 bellard
    NVRAM_set_byte(nvram,   0x34, boot_device);
1381 64201201 bellard
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1382 64201201 bellard
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1383 fd0bbb12 bellard
    if (cmdline) {
1384 fd0bbb12 bellard
        /* XXX: put the cmdline in NVRAM too ? */
1385 fd0bbb12 bellard
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
1386 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1387 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1388 fd0bbb12 bellard
    } else {
1389 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x40, 0);
1390 fd0bbb12 bellard
        NVRAM_set_lword(nvram,  0x44, 0);
1391 fd0bbb12 bellard
    }
1392 64201201 bellard
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1393 64201201 bellard
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1394 64201201 bellard
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1395 fd0bbb12 bellard
1396 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x54, width);
1397 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x56, height);
1398 fd0bbb12 bellard
    NVRAM_set_word(nvram,   0x58, depth);
1399 fd0bbb12 bellard
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1400 3cbee15b j_mayer
    NVRAM_set_word(nvram,   0xFC, crc);
1401 64201201 bellard
1402 64201201 bellard
    return 0;
1403 a541f297 bellard
}