diff --git a/hw/boards.h b/hw/boards.h index e6dd1987f5..6aa155db98 100644 --- a/hw/boards.h +++ b/hw/boards.h @@ -66,6 +66,7 @@ extern QEMUMachine ss1000_machine, ss2000_machine; /* sun4u.c */ extern QEMUMachine sun4u_machine; extern QEMUMachine sun4v_machine; +extern QEMUMachine niagara_machine; /* integratorcp.c */ extern QEMUMachine integratorcp_machine; diff --git a/hw/sun4u.c b/hw/sun4u.c index 59418f69e5..0c0091beb0 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -46,7 +46,6 @@ #define CMDLINE_ADDR 0x003ff000 #define INITRD_LOAD_ADDR 0x00300000 #define PROM_SIZE_MAX (4 * 1024 * 1024) -#define PROM_ADDR 0x1fff0000000ULL #define PROM_VADDR 0x000ffd00000ULL #define APB_SPECIAL_BASE 0x1fe00000000ULL #define APB_MEM_BASE 0x1ff00000000ULL @@ -61,6 +60,8 @@ struct hwdef { const char * const default_cpu_model; uint16_t machine_id; + uint64_t prom_addr; + uint64_t console_serial_base; }; int DMA_get_channel_mode (int nchan) @@ -260,9 +261,15 @@ void qemu_system_powerdown(void) { } +typedef struct ResetData { + CPUState *env; + uint64_t reset_addr; +} ResetData; + static void main_cpu_reset(void *opaque) { - CPUState *env = opaque; + ResetData *s = (ResetData *)opaque; + CPUState *env = s->env; cpu_reset(env); ptimer_set_limit(env->tick, 0x7fffffffffffffffULL, 1); @@ -271,6 +278,11 @@ static void main_cpu_reset(void *opaque) ptimer_run(env->stick, 0); ptimer_set_limit(env->hstick, 0x7fffffffffffffffULL, 1); ptimer_run(env->hstick, 0); + env->gregs[1] = 0; // Memory start + env->gregs[2] = ram_size; // Memory size + env->gregs[3] = 0; // Machine description XXX + env->pc = s->reset_addr; + env->npc = env->pc + 4; } static void tick_irq(void *opaque) @@ -328,6 +340,7 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BlockDriverState *fd[MAX_FD]; void *fw_cfg; + ResetData *reset_info; linux_boot = (kernel_filename != NULL); @@ -351,14 +364,21 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, bh = qemu_bh_new(hstick_irq, env); env->hstick = ptimer_init(bh); ptimer_set_period(env->hstick, 1ULL); - qemu_register_reset(main_cpu_reset, env); - main_cpu_reset(env); + + reset_info = qemu_mallocz(sizeof(ResetData)); + reset_info->env = env; + reset_info->reset_addr = hwdef->prom_addr + 0x40ULL; + qemu_register_reset(main_cpu_reset, reset_info); + main_cpu_reset(reset_info); + // Override warm reset address with cold start address + env->pc = hwdef->prom_addr + 0x20ULL; + env->npc = env->pc + 4; /* allocate RAM */ cpu_register_physical_memory(0, RAM_size, 0); prom_offset = RAM_size + vga_ram_size; - cpu_register_physical_memory(PROM_ADDR, + cpu_register_physical_memory(hwdef->prom_addr, (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK, prom_offset | IO_MEM_ROM); @@ -366,11 +386,16 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, if (bios_name == NULL) bios_name = PROM_FILENAME; snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); - ret = load_elf(buf, PROM_ADDR - PROM_VADDR, NULL, NULL, NULL); + ret = load_elf(buf, hwdef->prom_addr - PROM_VADDR, NULL, NULL, NULL); if (ret < 0) { - fprintf(stderr, "qemu: could not load prom '%s'\n", - buf); - exit(1); + ret = load_image_targphys(buf, hwdef->prom_addr, + (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & + TARGET_PAGE_MASK); + if (ret < 0) { + fprintf(stderr, "qemu: could not load prom '%s'\n", + buf); + exit(1); + } } kernel_size = 0; @@ -417,7 +442,13 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + RAM_size, RAM_size, vga_ram_size); - for(i = 0; i < MAX_SERIAL_PORTS; i++) { + i = 0; + if (hwdef->console_serial_base) { + serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200, + serial_hds[i], 1); + i++; + } + for(; i < MAX_SERIAL_PORTS; i++) { if (serial_hds[i]) { serial_init(serial_io[i], NULL/*serial_irq[i]*/, 115200, serial_hds[i]); @@ -482,6 +513,7 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, enum { sun4u_id = 0, sun4v_id = 64, + niagara_id, }; static const struct hwdef hwdefs[] = { @@ -489,11 +521,22 @@ static const struct hwdef hwdefs[] = { { .default_cpu_model = "TI UltraSparc II", .machine_id = sun4u_id, + .prom_addr = 0x1fff0000000ULL, + .console_serial_base = 0, }, /* Sun4v generic PC-like machine */ { .default_cpu_model = "Sun UltraSparc T1", .machine_id = sun4v_id, + .prom_addr = 0x1fff0000000ULL, + .console_serial_base = 0, + }, + /* Sun4v generic Niagara machine */ + { + .default_cpu_model = "Sun UltraSparc T1", + .machine_id = niagara_id, + .prom_addr = 0xfff0000000ULL, + .console_serial_base = 0xfff0c2c000ULL, }, }; @@ -517,6 +560,16 @@ static void sun4v_init(ram_addr_t RAM_size, int vga_ram_size, kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]); } +/* Niagara hardware initialisation */ +static void niagara_init(ram_addr_t RAM_size, int vga_ram_size, + const char *boot_devices, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + sun4uv_init(RAM_size, vga_ram_size, boot_devices, ds, kernel_filename, + kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]); +} + QEMUMachine sun4u_machine = { .name = "sun4u", .desc = "Sun4u platform", @@ -532,3 +585,11 @@ QEMUMachine sun4v_machine = { .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE, .nodisk_ok = 1, }; + +QEMUMachine niagara_machine = { + .name = "Niagara", + .desc = "Sun4v platform, Niagara", + .init = niagara_init, + .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE, + .nodisk_ok = 1, +}; diff --git a/target-sparc/helper.c b/target-sparc/helper.c index ab96428388..12070b9246 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -658,13 +658,12 @@ void cpu_reset(CPUSPARCState *env) #ifdef TARGET_SPARC64 env->pstate = PS_PRIV; env->hpstate = HS_PRIV; - env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset env->tsptr = &env->ts[env->tl & MAXTL_MASK]; #else - env->pc = 0; env->mmuregs[0] &= ~(MMU_E | MMU_NF); env->mmuregs[0] |= env->def->mmu_bm; #endif + env->pc = 0; env->npc = env->pc + 4; #endif } diff --git a/target-sparc/machine.c b/target-sparc/machine.c index 626a088c21..417523f883 100644 --- a/target-sparc/machine.c +++ b/target-sparc/machine.c @@ -9,6 +9,7 @@ void register_machines(void) #ifdef TARGET_SPARC64 qemu_register_machine(&sun4u_machine); qemu_register_machine(&sun4v_machine); + qemu_register_machine(&niagara_machine); #else qemu_register_machine(&ss5_machine); qemu_register_machine(&ss10_machine);