Annotation of qemu/hw/ppc.c, revision 1.1.1.12

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.