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

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