Annotation of qemu/hw/sun4u.c, revision 1.1.1.11

1.1       root        1: /*
1.1.1.7   root        2:  * QEMU Sun4u/Sun4v System Emulator
1.1.1.6   root        3:  *
1.1       root        4:  * Copyright (c) 2005 Fabrice Bellard
1.1.1.6   root        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.6   root       24: #include "hw.h"
                     25: #include "pci.h"
1.1.1.9   root       26: #include "apb_pci.h"
1.1.1.6   root       27: #include "pc.h"
                     28: #include "nvram.h"
                     29: #include "fdc.h"
                     30: #include "net.h"
                     31: #include "qemu-timer.h"
                     32: #include "sysemu.h"
                     33: #include "boards.h"
                     34: #include "firmware_abi.h"
1.1.1.7   root       35: #include "fw_cfg.h"
1.1.1.9   root       36: #include "sysbus.h"
                     37: #include "ide.h"
                     38: #include "loader.h"
                     39: #include "elf.h"
1.1.1.11! root       40: #include "blockdev.h"
1.1.1.7   root       41: 
                     42: //#define DEBUG_IRQ
1.1.1.10  root       43: //#define DEBUG_EBUS
                     44: //#define DEBUG_TIMER
1.1.1.7   root       45: 
                     46: #ifdef DEBUG_IRQ
1.1.1.10  root       47: #define CPUIRQ_DPRINTF(fmt, ...)                                \
1.1.1.8   root       48:     do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.7   root       49: #else
1.1.1.10  root       50: #define CPUIRQ_DPRINTF(fmt, ...)
                     51: #endif
                     52: 
                     53: #ifdef DEBUG_EBUS
                     54: #define EBUS_DPRINTF(fmt, ...)                                  \
                     55:     do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0)
                     56: #else
                     57: #define EBUS_DPRINTF(fmt, ...)
                     58: #endif
                     59: 
                     60: #ifdef DEBUG_TIMER
                     61: #define TIMER_DPRINTF(fmt, ...)                                  \
                     62:     do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
                     63: #else
                     64: #define TIMER_DPRINTF(fmt, ...)
1.1.1.7   root       65: #endif
1.1       root       66: 
                     67: #define KERNEL_LOAD_ADDR     0x00404000
                     68: #define CMDLINE_ADDR         0x003ff000
                     69: #define INITRD_LOAD_ADDR     0x00300000
1.1.1.7   root       70: #define PROM_SIZE_MAX        (4 * 1024 * 1024)
1.1.1.6   root       71: #define PROM_VADDR           0x000ffd00000ULL
1.1       root       72: #define APB_SPECIAL_BASE     0x1fe00000000ULL
1.1.1.6   root       73: #define APB_MEM_BASE         0x1ff00000000ULL
1.1.1.10  root       74: #define APB_PCI_IO_BASE      (APB_SPECIAL_BASE + 0x02000000ULL)
1.1.1.6   root       75: #define PROM_FILENAME        "openbios-sparc64"
1.1       root       76: #define NVRAM_SIZE           0x2000
1.1.1.6   root       77: #define MAX_IDE_BUS          2
1.1.1.7   root       78: #define BIOS_CFG_IOPORT      0x510
1.1.1.9   root       79: #define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
                     80: #define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
                     81: #define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
1.1       root       82: 
1.1.1.7   root       83: #define MAX_PILS 16
1.1       root       84: 
1.1.1.7   root       85: #define TICK_MAX             0x7fffffffffffffffULL
                     86: 
                     87: struct hwdef {
                     88:     const char * const default_cpu_model;
                     89:     uint16_t machine_id;
                     90:     uint64_t prom_addr;
                     91:     uint64_t console_serial_base;
                     92: };
1.1       root       93: 
                     94: int DMA_get_channel_mode (int nchan)
                     95: {
                     96:     return 0;
                     97: }
                     98: int DMA_read_memory (int nchan, void *buf, int pos, int size)
                     99: {
                    100:     return 0;
                    101: }
                    102: int DMA_write_memory (int nchan, void *buf, int pos, int size)
                    103: {
                    104:     return 0;
                    105: }
                    106: void DMA_hold_DREQ (int nchan) {}
                    107: void DMA_release_DREQ (int nchan) {}
                    108: void DMA_schedule(int nchan) {}
1.1.1.10  root      109: 
                    110: void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
                    111: {
                    112: }
                    113: 
1.1       root      114: void DMA_register_channel (int nchan,
                    115:                            DMA_transfer_handler transfer_handler,
                    116:                            void *opaque)
                    117: {
                    118: }
                    119: 
1.1.1.8   root      120: static int fw_cfg_boot_set(void *opaque, const char *boot_device)
1.1.1.7   root      121: {
1.1.1.8   root      122:     fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
1.1.1.7   root      123:     return 0;
                    124: }
1.1       root      125: 
1.1.1.10  root      126: static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
                    127:                                   const char *arch, ram_addr_t RAM_size,
                    128:                                   const char *boot_devices,
                    129:                                   uint32_t kernel_image, uint32_t kernel_size,
                    130:                                   const char *cmdline,
                    131:                                   uint32_t initrd_image, uint32_t initrd_size,
                    132:                                   uint32_t NVRAM_image,
                    133:                                   int width, int height, int depth,
                    134:                                   const uint8_t *macaddr)
1.1       root      135: {
1.1.1.6   root      136:     unsigned int i;
                    137:     uint32_t start, end;
                    138:     uint8_t image[0x1ff0];
                    139:     struct OpenBIOS_nvpart_v1 *part_header;
                    140: 
                    141:     memset(image, '\0', sizeof(image));
                    142: 
1.1.1.8   root      143:     start = 0;
1.1.1.6   root      144: 
                    145:     // OpenBIOS nvram variables
                    146:     // Variable partition
                    147:     part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
                    148:     part_header->signature = OPENBIOS_PART_SYSTEM;
1.1.1.7   root      149:     pstrcpy(part_header->name, sizeof(part_header->name), "system");
1.1.1.6   root      150: 
                    151:     end = start + sizeof(struct OpenBIOS_nvpart_v1);
                    152:     for (i = 0; i < nb_prom_envs; i++)
                    153:         end = OpenBIOS_set_var(image, end, prom_envs[i]);
                    154: 
                    155:     // End marker
                    156:     image[end++] = '\0';
                    157: 
                    158:     end = start + ((end - start + 15) & ~15);
                    159:     OpenBIOS_finish_partition(part_header, end - start);
                    160: 
                    161:     // free partition
                    162:     start = end;
                    163:     part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
                    164:     part_header->signature = OPENBIOS_PART_FREE;
1.1.1.7   root      165:     pstrcpy(part_header->name, sizeof(part_header->name), "free");
1.1       root      166: 
1.1.1.6   root      167:     end = 0x1fd0;
                    168:     OpenBIOS_finish_partition(part_header, end - start);
1.1       root      169: 
1.1.1.7   root      170:     Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
                    171: 
1.1.1.6   root      172:     for (i = 0; i < sizeof(image); i++)
                    173:         m48t59_write(nvram, i, image[i]);
1.1       root      174: 
1.1.1.6   root      175:     return 0;
1.1       root      176: }
1.1.1.9   root      177: static unsigned long sun4u_load_kernel(const char *kernel_filename,
                    178:                                        const char *initrd_filename,
                    179:                                        ram_addr_t RAM_size, long *initrd_size)
                    180: {
                    181:     int linux_boot;
                    182:     unsigned int i;
                    183:     long kernel_size;
1.1.1.10  root      184:     uint8_t *ptr;
1.1.1.9   root      185: 
                    186:     linux_boot = (kernel_filename != NULL);
                    187: 
                    188:     kernel_size = 0;
                    189:     if (linux_boot) {
                    190:         int bswap_needed;
                    191: 
                    192: #ifdef BSWAP_NEEDED
                    193:         bswap_needed = 1;
                    194: #else
                    195:         bswap_needed = 0;
                    196: #endif
1.1.1.10  root      197:         kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
                    198:                                NULL, NULL, 1, ELF_MACHINE, 0);
1.1.1.9   root      199:         if (kernel_size < 0)
                    200:             kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
                    201:                                     RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
                    202:                                     TARGET_PAGE_SIZE);
                    203:         if (kernel_size < 0)
                    204:             kernel_size = load_image_targphys(kernel_filename,
                    205:                                               KERNEL_LOAD_ADDR,
                    206:                                               RAM_size - KERNEL_LOAD_ADDR);
                    207:         if (kernel_size < 0) {
                    208:             fprintf(stderr, "qemu: could not load kernel '%s'\n",
                    209:                     kernel_filename);
                    210:             exit(1);
                    211:         }
                    212: 
                    213:         /* load initrd */
                    214:         *initrd_size = 0;
                    215:         if (initrd_filename) {
                    216:             *initrd_size = load_image_targphys(initrd_filename,
                    217:                                                INITRD_LOAD_ADDR,
                    218:                                                RAM_size - INITRD_LOAD_ADDR);
                    219:             if (*initrd_size < 0) {
                    220:                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                    221:                         initrd_filename);
                    222:                 exit(1);
                    223:             }
                    224:         }
                    225:         if (*initrd_size > 0) {
                    226:             for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
1.1.1.10  root      227:                 ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
                    228:                 if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
                    229:                     stl_p(ptr + 24, INITRD_LOAD_ADDR + KERNEL_LOAD_ADDR - 0x4000);
                    230:                     stl_p(ptr + 28, *initrd_size);
1.1.1.9   root      231:                     break;
                    232:                 }
                    233:             }
                    234:         }
                    235:     }
                    236:     return kernel_size;
                    237: }
1.1       root      238: 
1.1.1.8   root      239: void pic_info(Monitor *mon)
1.1       root      240: {
                    241: }
                    242: 
1.1.1.8   root      243: void irq_info(Monitor *mon)
1.1       root      244: {
                    245: }
                    246: 
1.1.1.7   root      247: void cpu_check_irqs(CPUState *env)
                    248: {
1.1.1.10  root      249:     uint32_t pil = env->pil_in |
                    250:                   (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
                    251: 
                    252:     /* check if TM or SM in SOFTINT are set
                    253:        setting these also causes interrupt 14 */
                    254:     if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
                    255:         pil |= 1 << 14;
                    256:     }
                    257: 
                    258:     if (!pil) {
                    259:         if (env->interrupt_request & CPU_INTERRUPT_HARD) {
                    260:             CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                    261:                            env->interrupt_index);
                    262:             env->interrupt_index = 0;
                    263:             cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
                    264:         }
                    265:         return;
                    266:     }
                    267: 
                    268:     if (cpu_interrupts_enabled(env)) {
1.1.1.7   root      269: 
                    270:         unsigned int i;
                    271: 
1.1.1.10  root      272:         for (i = 15; i > env->psrpil; i--) {
1.1.1.7   root      273:             if (pil & (1 << i)) {
                    274:                 int old_interrupt = env->interrupt_index;
1.1.1.10  root      275:                 int new_interrupt = TT_EXTINT | i;
1.1.1.7   root      276: 
1.1.1.10  root      277:                 if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) {
                    278:                     CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
                    279:                                    "current %x >= pending %x\n",
                    280:                                    env->tl, cpu_tsptr(env)->tt, new_interrupt);
                    281:                 } else if (old_interrupt != new_interrupt) {
                    282:                     env->interrupt_index = new_interrupt;
                    283:                     CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
                    284:                                    old_interrupt, new_interrupt);
1.1.1.7   root      285:                     cpu_interrupt(env, CPU_INTERRUPT_HARD);
                    286:                 }
                    287:                 break;
                    288:             }
                    289:         }
1.1.1.10  root      290:     } else {
                    291:         CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
                    292:                        "current interrupt %x\n",
                    293:                        pil, env->pil_in, env->softint, env->interrupt_index);
1.1.1.7   root      294:     }
                    295: }
                    296: 
1.1.1.10  root      297: static void cpu_kick_irq(CPUState *env)
                    298: {
                    299:     env->halted = 0;
                    300:     cpu_check_irqs(env);
                    301: }
                    302: 
1.1.1.7   root      303: static void cpu_set_irq(void *opaque, int irq, int level)
                    304: {
                    305:     CPUState *env = opaque;
                    306: 
                    307:     if (level) {
1.1.1.10  root      308:         CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
1.1.1.7   root      309:         env->halted = 0;
                    310:         env->pil_in |= 1 << irq;
                    311:         cpu_check_irqs(env);
                    312:     } else {
1.1.1.10  root      313:         CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
1.1.1.7   root      314:         env->pil_in &= ~(1 << irq);
                    315:         cpu_check_irqs(env);
                    316:     }
                    317: }
                    318: 
                    319: typedef struct ResetData {
                    320:     CPUState *env;
1.1.1.9   root      321:     uint64_t prom_addr;
1.1.1.7   root      322: } ResetData;
                    323: 
1.1.1.10  root      324: void cpu_put_timer(QEMUFile *f, CPUTimer *s)
                    325: {
                    326:     qemu_put_be32s(f, &s->frequency);
                    327:     qemu_put_be32s(f, &s->disabled);
                    328:     qemu_put_be64s(f, &s->disabled_mask);
                    329:     qemu_put_sbe64s(f, &s->clock_offset);
                    330: 
                    331:     qemu_put_timer(f, s->qtimer);
                    332: }
                    333: 
                    334: void cpu_get_timer(QEMUFile *f, CPUTimer *s)
                    335: {
                    336:     qemu_get_be32s(f, &s->frequency);
                    337:     qemu_get_be32s(f, &s->disabled);
                    338:     qemu_get_be64s(f, &s->disabled_mask);
                    339:     qemu_get_sbe64s(f, &s->clock_offset);
                    340: 
                    341:     qemu_get_timer(f, s->qtimer);
                    342: }
                    343: 
                    344: static CPUTimer* cpu_timer_create(const char* name, CPUState *env,
                    345:                                   QEMUBHFunc *cb, uint32_t frequency,
                    346:                                   uint64_t disabled_mask)
                    347: {
                    348:     CPUTimer *timer = qemu_mallocz(sizeof (CPUTimer));
                    349: 
                    350:     timer->name = name;
                    351:     timer->frequency = frequency;
                    352:     timer->disabled_mask = disabled_mask;
                    353: 
                    354:     timer->disabled = 1;
                    355:     timer->clock_offset = qemu_get_clock(vm_clock);
                    356: 
                    357:     timer->qtimer = qemu_new_timer(vm_clock, cb, env);
                    358: 
                    359:     return timer;
                    360: }
                    361: 
                    362: static void cpu_timer_reset(CPUTimer *timer)
                    363: {
                    364:     timer->disabled = 1;
                    365:     timer->clock_offset = qemu_get_clock(vm_clock);
                    366: 
                    367:     qemu_del_timer(timer->qtimer);
                    368: }
                    369: 
1.1.1.6   root      370: static void main_cpu_reset(void *opaque)
1.1       root      371: {
1.1.1.7   root      372:     ResetData *s = (ResetData *)opaque;
                    373:     CPUState *env = s->env;
1.1.1.9   root      374:     static unsigned int nr_resets;
1.1       root      375: 
1.1.1.6   root      376:     cpu_reset(env);
1.1.1.10  root      377: 
                    378:     cpu_timer_reset(env->tick);
                    379:     cpu_timer_reset(env->stick);
                    380:     cpu_timer_reset(env->hstick);
                    381: 
1.1.1.7   root      382:     env->gregs[1] = 0; // Memory start
                    383:     env->gregs[2] = ram_size; // Memory size
                    384:     env->gregs[3] = 0; // Machine description XXX
1.1.1.9   root      385:     if (nr_resets++ == 0) {
                    386:         /* Power on reset */
                    387:         env->pc = s->prom_addr + 0x20ULL;
                    388:     } else {
                    389:         env->pc = s->prom_addr + 0x40ULL;
                    390:     }
1.1.1.7   root      391:     env->npc = env->pc + 4;
1.1       root      392: }
                    393: 
1.1.1.7   root      394: static void tick_irq(void *opaque)
1.1       root      395: {
1.1.1.6   root      396:     CPUState *env = opaque;
1.1       root      397: 
1.1.1.10  root      398:     CPUTimer* timer = env->tick;
                    399: 
                    400:     if (timer->disabled) {
                    401:         CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
                    402:         return;
                    403:     } else {
                    404:         CPUIRQ_DPRINTF("tick: fire\n");
1.1.1.7   root      405:     }
1.1.1.10  root      406: 
                    407:     env->softint |= SOFTINT_TIMER;
                    408:     cpu_kick_irq(env);
1.1       root      409: }
                    410: 
1.1.1.7   root      411: static void stick_irq(void *opaque)
1.1       root      412: {
1.1.1.6   root      413:     CPUState *env = opaque;
1.1       root      414: 
1.1.1.10  root      415:     CPUTimer* timer = env->stick;
                    416: 
                    417:     if (timer->disabled) {
                    418:         CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
                    419:         return;
                    420:     } else {
                    421:         CPUIRQ_DPRINTF("stick: fire\n");
1.1.1.7   root      422:     }
1.1.1.10  root      423: 
                    424:     env->softint |= SOFTINT_STIMER;
                    425:     cpu_kick_irq(env);
1.1       root      426: }
                    427: 
1.1.1.7   root      428: static void hstick_irq(void *opaque)
1.1       root      429: {
1.1.1.6   root      430:     CPUState *env = opaque;
1.1       root      431: 
1.1.1.10  root      432:     CPUTimer* timer = env->hstick;
                    433: 
                    434:     if (timer->disabled) {
                    435:         CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
                    436:         return;
                    437:     } else {
                    438:         CPUIRQ_DPRINTF("hstick: fire\n");
1.1.1.7   root      439:     }
1.1.1.10  root      440: 
                    441:     env->softint |= SOFTINT_STIMER;
                    442:     cpu_kick_irq(env);
1.1.1.7   root      443: }
                    444: 
1.1.1.10  root      445: static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
1.1.1.7   root      446: {
1.1.1.10  root      447:     return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency);
                    448: }
                    449: 
                    450: static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
                    451: {
                    452:     return muldiv64(timer_ticks, frequency, get_ticks_per_sec());
                    453: }
                    454: 
                    455: void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
                    456: {
                    457:     uint64_t real_count = count & ~timer->disabled_mask;
                    458:     uint64_t disabled_bit = count & timer->disabled_mask;
                    459: 
                    460:     int64_t vm_clock_offset = qemu_get_clock(vm_clock) -
                    461:                     cpu_to_timer_ticks(real_count, timer->frequency);
                    462: 
                    463:     TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
                    464:                   timer->name, real_count,
                    465:                   timer->disabled?"disabled":"enabled", timer);
                    466: 
                    467:     timer->disabled = disabled_bit ? 1 : 0;
                    468:     timer->clock_offset = vm_clock_offset;
1.1       root      469: }
                    470: 
1.1.1.10  root      471: uint64_t cpu_tick_get_count(CPUTimer *timer)
1.1.1.2   root      472: {
1.1.1.10  root      473:     uint64_t real_count = timer_to_cpu_ticks(
                    474:                     qemu_get_clock(vm_clock) - timer->clock_offset,
                    475:                     timer->frequency);
                    476: 
                    477:     TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
                    478:            timer->name, real_count,
                    479:            timer->disabled?"disabled":"enabled", timer);
                    480: 
                    481:     if (timer->disabled)
                    482:         real_count |= timer->disabled_mask;
                    483: 
                    484:     return real_count;
1.1.1.7   root      485: }
                    486: 
1.1.1.10  root      487: void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
1.1.1.7   root      488: {
1.1.1.10  root      489:     int64_t now = qemu_get_clock(vm_clock);
                    490: 
                    491:     uint64_t real_limit = limit & ~timer->disabled_mask;
                    492:     timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
                    493: 
                    494:     int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
                    495:                     timer->clock_offset;
                    496: 
                    497:     if (expires < now) {
                    498:         expires = now + 1;
                    499:     }
                    500: 
                    501:     TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
                    502:                   "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
                    503:                   timer->name, real_limit,
                    504:                   timer->disabled?"disabled":"enabled",
                    505:                   timer, limit,
                    506:                   timer_to_cpu_ticks(now - timer->clock_offset,
                    507:                                      timer->frequency),
                    508:                   timer_to_cpu_ticks(expires - now, timer->frequency));
                    509: 
                    510:     if (!real_limit) {
                    511:         TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
                    512:                 timer->name);
                    513:         qemu_del_timer(timer->qtimer);
                    514:     } else if (timer->disabled) {
                    515:         qemu_del_timer(timer->qtimer);
                    516:     } else {
                    517:         qemu_mod_timer(timer->qtimer, expires);
                    518:     }
1.1.1.2   root      519: }
                    520: 
1.1.1.7   root      521: static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
1.1.1.9   root      522:                               pcibus_t addr, pcibus_t size, int type)
1.1.1.7   root      523: {
1.1.1.10  root      524:     EBUS_DPRINTF("Mapping region %d registers at %" FMT_PCIBUS "\n",
                    525:                  region_num, addr);
1.1.1.7   root      526:     switch (region_num) {
                    527:     case 0:
1.1.1.11! root      528:         isa_mmio_init(addr, 0x1000000);
1.1.1.7   root      529:         break;
                    530:     case 1:
1.1.1.11! root      531:         isa_mmio_init(addr, 0x800000);
1.1.1.7   root      532:         break;
                    533:     }
                    534: }
                    535: 
1.1.1.9   root      536: static void dummy_isa_irq_handler(void *opaque, int n, int level)
                    537: {
                    538: }
                    539: 
1.1.1.7   root      540: /* EBUS (Eight bit bus) bridge */
                    541: static void
                    542: pci_ebus_init(PCIBus *bus, int devfn)
                    543: {
1.1.1.9   root      544:     qemu_irq *isa_irq;
                    545: 
1.1.1.8   root      546:     pci_create_simple(bus, devfn, "ebus");
1.1.1.9   root      547:     isa_irq = qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16);
                    548:     isa_bus_irqs(isa_irq);
1.1.1.8   root      549: }
1.1.1.7   root      550: 
1.1.1.9   root      551: static int
1.1.1.8   root      552: pci_ebus_init1(PCIDevice *s)
                    553: {
1.1.1.9   root      554:     isa_bus_new(&s->qdev);
                    555: 
1.1.1.7   root      556:     pci_config_set_vendor_id(s->config, PCI_VENDOR_ID_SUN);
                    557:     pci_config_set_device_id(s->config, PCI_DEVICE_ID_SUN_EBUS);
                    558:     s->config[0x04] = 0x06; // command = bus master, pci mem
                    559:     s->config[0x05] = 0x00;
                    560:     s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
                    561:     s->config[0x07] = 0x03; // status = medium devsel
                    562:     s->config[0x08] = 0x01; // revision
                    563:     s->config[0x09] = 0x00; // programming i/f
                    564:     pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER);
                    565:     s->config[0x0D] = 0x0a; // latency_timer
                    566: 
1.1.1.9   root      567:     pci_register_bar(s, 0, 0x1000000, PCI_BASE_ADDRESS_SPACE_MEMORY,
1.1.1.7   root      568:                            ebus_mmio_mapfunc);
1.1.1.9   root      569:     pci_register_bar(s, 1, 0x800000,  PCI_BASE_ADDRESS_SPACE_MEMORY,
1.1.1.7   root      570:                            ebus_mmio_mapfunc);
1.1.1.9   root      571:     return 0;
1.1.1.7   root      572: }
                    573: 
1.1.1.8   root      574: static PCIDeviceInfo ebus_info = {
                    575:     .qdev.name = "ebus",
                    576:     .qdev.size = sizeof(PCIDevice),
                    577:     .init = pci_ebus_init1,
                    578: };
                    579: 
                    580: static void pci_ebus_register(void)
                    581: {
                    582:     pci_qdev_register(&ebus_info);
                    583: }
                    584: 
                    585: device_init(pci_ebus_register);
                    586: 
1.1.1.10  root      587: static uint64_t translate_prom_address(void *opaque, uint64_t addr)
                    588: {
                    589:     target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque;
                    590:     return addr + *base_addr - PROM_VADDR;
                    591: }
                    592: 
1.1.1.9   root      593: /* Boot PROM (OpenBIOS) */
                    594: static void prom_init(target_phys_addr_t addr, const char *bios_name)
1.1       root      595: {
1.1.1.9   root      596:     DeviceState *dev;
                    597:     SysBusDevice *s;
1.1.1.8   root      598:     char *filename;
1.1.1.9   root      599:     int ret;
                    600: 
                    601:     dev = qdev_create(NULL, "openprom");
                    602:     qdev_init_nofail(dev);
                    603:     s = sysbus_from_qdev(dev);
                    604: 
                    605:     sysbus_mmio_map(s, 0, addr);
                    606: 
                    607:     /* load boot prom */
                    608:     if (bios_name == NULL) {
                    609:         bios_name = PROM_FILENAME;
                    610:     }
                    611:     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
                    612:     if (filename) {
1.1.1.10  root      613:         ret = load_elf(filename, translate_prom_address, &addr,
                    614:                        NULL, NULL, NULL, 1, ELF_MACHINE, 0);
1.1.1.9   root      615:         if (ret < 0 || ret > PROM_SIZE_MAX) {
                    616:             ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
                    617:         }
                    618:         qemu_free(filename);
                    619:     } else {
                    620:         ret = -1;
                    621:     }
                    622:     if (ret < 0 || ret > PROM_SIZE_MAX) {
                    623:         fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
                    624:         exit(1);
                    625:     }
                    626: }
                    627: 
                    628: static int prom_init1(SysBusDevice *dev)
                    629: {
                    630:     ram_addr_t prom_offset;
                    631: 
1.1.1.10  root      632:     prom_offset = qemu_ram_alloc(NULL, "sun4u.prom", PROM_SIZE_MAX);
1.1.1.9   root      633:     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
                    634:     return 0;
                    635: }
                    636: 
                    637: static SysBusDeviceInfo prom_info = {
                    638:     .init = prom_init1,
                    639:     .qdev.name  = "openprom",
                    640:     .qdev.size  = sizeof(SysBusDevice),
                    641:     .qdev.props = (Property[]) {
                    642:         {/* end of property list */}
                    643:     }
                    644: };
                    645: 
                    646: static void prom_register_devices(void)
                    647: {
                    648:     sysbus_register_withprop(&prom_info);
                    649: }
                    650: 
                    651: device_init(prom_register_devices);
                    652: 
                    653: 
                    654: typedef struct RamDevice
                    655: {
                    656:     SysBusDevice busdev;
                    657:     uint64_t size;
                    658: } RamDevice;
                    659: 
                    660: /* System RAM */
                    661: static int ram_init1(SysBusDevice *dev)
                    662: {
                    663:     ram_addr_t RAM_size, ram_offset;
                    664:     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
                    665: 
                    666:     RAM_size = d->size;
                    667: 
1.1.1.10  root      668:     ram_offset = qemu_ram_alloc(NULL, "sun4u.ram", RAM_size);
1.1.1.9   root      669:     sysbus_init_mmio(dev, RAM_size, ram_offset);
                    670:     return 0;
                    671: }
                    672: 
                    673: static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size)
                    674: {
                    675:     DeviceState *dev;
                    676:     SysBusDevice *s;
                    677:     RamDevice *d;
                    678: 
                    679:     /* allocate RAM */
                    680:     dev = qdev_create(NULL, "memory");
                    681:     s = sysbus_from_qdev(dev);
                    682: 
                    683:     d = FROM_SYSBUS(RamDevice, s);
                    684:     d->size = RAM_size;
                    685:     qdev_init_nofail(dev);
                    686: 
                    687:     sysbus_mmio_map(s, 0, addr);
                    688: }
                    689: 
                    690: static SysBusDeviceInfo ram_info = {
                    691:     .init = ram_init1,
                    692:     .qdev.name  = "memory",
                    693:     .qdev.size  = sizeof(RamDevice),
                    694:     .qdev.props = (Property[]) {
                    695:         DEFINE_PROP_UINT64("size", RamDevice, size, 0),
                    696:         DEFINE_PROP_END_OF_LIST(),
                    697:     }
                    698: };
                    699: 
                    700: static void ram_register_devices(void)
                    701: {
                    702:     sysbus_register_withprop(&ram_info);
                    703: }
                    704: 
                    705: device_init(ram_register_devices);
                    706: 
                    707: static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
                    708: {
                    709:     CPUState *env;
1.1.1.7   root      710:     ResetData *reset_info;
1.1       root      711: 
1.1.1.10  root      712:     uint32_t   tick_frequency = 100*1000000;
                    713:     uint32_t  stick_frequency = 100*1000000;
                    714:     uint32_t hstick_frequency = 100*1000000;
                    715: 
1.1.1.7   root      716:     if (!cpu_model)
                    717:         cpu_model = hwdef->default_cpu_model;
1.1.1.6   root      718:     env = cpu_init(cpu_model);
                    719:     if (!env) {
                    720:         fprintf(stderr, "Unable to find Sparc CPU definition\n");
                    721:         exit(1);
                    722:     }
1.1.1.10  root      723: 
                    724:     env->tick = cpu_timer_create("tick", env, tick_irq,
                    725:                                   tick_frequency, TICK_NPT_MASK);
                    726: 
                    727:     env->stick = cpu_timer_create("stick", env, stick_irq,
                    728:                                    stick_frequency, TICK_INT_DIS);
                    729: 
                    730:     env->hstick = cpu_timer_create("hstick", env, hstick_irq,
                    731:                                     hstick_frequency, TICK_INT_DIS);
1.1.1.7   root      732: 
                    733:     reset_info = qemu_mallocz(sizeof(ResetData));
                    734:     reset_info->env = env;
1.1.1.9   root      735:     reset_info->prom_addr = hwdef->prom_addr;
1.1.1.7   root      736:     qemu_register_reset(main_cpu_reset, reset_info);
1.1.1.2   root      737: 
1.1.1.9   root      738:     return env;
                    739: }
1.1       root      740: 
1.1.1.9   root      741: static void sun4uv_init(ram_addr_t RAM_size,
                    742:                         const char *boot_devices,
                    743:                         const char *kernel_filename, const char *kernel_cmdline,
                    744:                         const char *initrd_filename, const char *cpu_model,
                    745:                         const struct hwdef *hwdef)
                    746: {
                    747:     CPUState *env;
1.1.1.10  root      748:     M48t59State *nvram;
1.1.1.9   root      749:     unsigned int i;
                    750:     long initrd_size, kernel_size;
                    751:     PCIBus *pci_bus, *pci_bus2, *pci_bus3;
                    752:     qemu_irq *irq;
                    753:     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
                    754:     DriveInfo *fd[MAX_FD];
                    755:     void *fw_cfg;
1.1       root      756: 
1.1.1.9   root      757:     /* init CPUs */
                    758:     env = cpu_devinit(cpu_model, hwdef);
1.1       root      759: 
1.1.1.9   root      760:     /* set up devices */
                    761:     ram_init(0, RAM_size);
                    762: 
                    763:     prom_init(hwdef->prom_addr, bios_name);
1.1       root      764: 
1.1.1.8   root      765: 
                    766:     irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
                    767:     pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
1.1.1.7   root      768:                            &pci_bus3);
1.1.1.10  root      769:     isa_mem_base = APB_PCI_IO_BASE;
1.1.1.11! root      770:     pci_vga_init(pci_bus);
1.1.1.7   root      771: 
                    772:     // XXX Should be pci_bus3
                    773:     pci_ebus_init(pci_bus, -1);
                    774: 
                    775:     i = 0;
                    776:     if (hwdef->console_serial_base) {
                    777:         serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200,
1.1.1.10  root      778:                        serial_hds[i], 1, 1);
1.1.1.7   root      779:         i++;
                    780:     }
                    781:     for(; i < MAX_SERIAL_PORTS; i++) {
1.1       root      782:         if (serial_hds[i]) {
1.1.1.9   root      783:             serial_isa_init(i, serial_hds[i]);
1.1       root      784:         }
                    785:     }
                    786: 
                    787:     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
                    788:         if (parallel_hds[i]) {
1.1.1.9   root      789:             parallel_init(i, parallel_hds[i]);
1.1       root      790:         }
                    791:     }
                    792: 
1.1.1.7   root      793:     for(i = 0; i < nb_nics; i++)
1.1.1.9   root      794:         pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
1.1       root      795: 
1.1.1.6   root      796:     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
                    797:         fprintf(stderr, "qemu: too many IDE bus\n");
                    798:         exit(1);
                    799:     }
                    800:     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
1.1.1.9   root      801:         hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS,
                    802:                           i % MAX_IDE_DEVS);
1.1.1.6   root      803:     }
                    804: 
1.1.1.7   root      805:     pci_cmd646_ide_init(pci_bus, hd, 1);
                    806: 
1.1.1.9   root      807:     isa_create_simple("i8042");
1.1.1.6   root      808:     for(i = 0; i < MAX_FD; i++) {
1.1.1.9   root      809:         fd[i] = drive_get(IF_FLOPPY, 0, i);
1.1.1.6   root      810:     }
1.1.1.9   root      811:     fdctrl_init_isa(fd);
                    812:     nvram = m48t59_init_isa(0x0074, NVRAM_SIZE, 59);
                    813: 
                    814:     initrd_size = 0;
                    815:     kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
                    816:                                     ram_size, &initrd_size);
                    817: 
1.1.1.7   root      818:     sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
                    819:                            KERNEL_LOAD_ADDR, kernel_size,
                    820:                            kernel_cmdline,
                    821:                            INITRD_LOAD_ADDR, initrd_size,
                    822:                            /* XXX: need an option to load a NVRAM image */
                    823:                            0,
                    824:                            graphic_width, graphic_height, graphic_depth,
                    825:                            (uint8_t *)&nd_table[0].macaddr);
                    826: 
                    827:     fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
                    828:     fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
                    829:     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
                    830:     fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
1.1.1.8   root      831:     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
                    832:     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
                    833:     if (kernel_cmdline) {
1.1.1.10  root      834:         fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                    835:                        strlen(kernel_cmdline) + 1);
                    836:         fw_cfg_add_bytes(fw_cfg, FW_CFG_CMDLINE_DATA,
                    837:                          (uint8_t*)strdup(kernel_cmdline),
                    838:                          strlen(kernel_cmdline) + 1);
1.1.1.8   root      839:     } else {
1.1.1.10  root      840:         fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
1.1.1.8   root      841:     }
                    842:     fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
                    843:     fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
                    844:     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
1.1.1.9   root      845: 
                    846:     fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
                    847:     fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
                    848:     fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
                    849: 
1.1.1.8   root      850:     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1.1.1.7   root      851: }
                    852: 
                    853: enum {
                    854:     sun4u_id = 0,
                    855:     sun4v_id = 64,
                    856:     niagara_id,
                    857: };
1.1       root      858: 
1.1.1.7   root      859: static const struct hwdef hwdefs[] = {
                    860:     /* Sun4u generic PC-like machine */
                    861:     {
1.1.1.10  root      862:         .default_cpu_model = "TI UltraSparc IIi",
1.1.1.7   root      863:         .machine_id = sun4u_id,
                    864:         .prom_addr = 0x1fff0000000ULL,
                    865:         .console_serial_base = 0,
                    866:     },
                    867:     /* Sun4v generic PC-like machine */
                    868:     {
                    869:         .default_cpu_model = "Sun UltraSparc T1",
                    870:         .machine_id = sun4v_id,
                    871:         .prom_addr = 0x1fff0000000ULL,
                    872:         .console_serial_base = 0,
                    873:     },
                    874:     /* Sun4v generic Niagara machine */
                    875:     {
                    876:         .default_cpu_model = "Sun UltraSparc T1",
                    877:         .machine_id = niagara_id,
                    878:         .prom_addr = 0xfff0000000ULL,
                    879:         .console_serial_base = 0xfff0c2c000ULL,
                    880:     },
                    881: };
                    882: 
                    883: /* Sun4u hardware initialisation */
1.1.1.8   root      884: static void sun4u_init(ram_addr_t RAM_size,
1.1.1.7   root      885:                        const char *boot_devices,
                    886:                        const char *kernel_filename, const char *kernel_cmdline,
                    887:                        const char *initrd_filename, const char *cpu_model)
                    888: {
1.1.1.8   root      889:     sun4uv_init(RAM_size, boot_devices, kernel_filename,
1.1.1.7   root      890:                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
                    891: }
                    892: 
                    893: /* Sun4v hardware initialisation */
1.1.1.8   root      894: static void sun4v_init(ram_addr_t RAM_size,
1.1.1.7   root      895:                        const char *boot_devices,
                    896:                        const char *kernel_filename, const char *kernel_cmdline,
                    897:                        const char *initrd_filename, const char *cpu_model)
                    898: {
1.1.1.8   root      899:     sun4uv_init(RAM_size, boot_devices, kernel_filename,
1.1.1.7   root      900:                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
                    901: }
                    902: 
                    903: /* Niagara hardware initialisation */
1.1.1.8   root      904: static void niagara_init(ram_addr_t RAM_size,
1.1.1.7   root      905:                          const char *boot_devices,
                    906:                          const char *kernel_filename, const char *kernel_cmdline,
                    907:                          const char *initrd_filename, const char *cpu_model)
                    908: {
1.1.1.8   root      909:     sun4uv_init(RAM_size, boot_devices, kernel_filename,
1.1.1.7   root      910:                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
1.1       root      911: }
                    912: 
1.1.1.8   root      913: static QEMUMachine sun4u_machine = {
1.1.1.7   root      914:     .name = "sun4u",
                    915:     .desc = "Sun4u platform",
                    916:     .init = sun4u_init,
                    917:     .max_cpus = 1, // XXX for now
1.1.1.8   root      918:     .is_default = 1,
1.1.1.7   root      919: };
                    920: 
1.1.1.8   root      921: static QEMUMachine sun4v_machine = {
1.1.1.7   root      922:     .name = "sun4v",
                    923:     .desc = "Sun4v platform",
                    924:     .init = sun4v_init,
                    925:     .max_cpus = 1, // XXX for now
                    926: };
                    927: 
1.1.1.8   root      928: static QEMUMachine niagara_machine = {
1.1.1.7   root      929:     .name = "Niagara",
                    930:     .desc = "Sun4v platform, Niagara",
                    931:     .init = niagara_init,
                    932:     .max_cpus = 1, // XXX for now
1.1       root      933: };
1.1.1.8   root      934: 
                    935: static void sun4u_machine_init(void)
                    936: {
                    937:     qemu_register_machine(&sun4u_machine);
                    938:     qemu_register_machine(&sun4v_machine);
                    939:     qemu_register_machine(&niagara_machine);
                    940: }
                    941: 
                    942: machine_init(sun4u_machine_init);

unix.superglobalmegacorp.com

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