From 37ed7c4b24f265c2a8c7248666544c9755514ec2 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 20 Jun 2014 18:02:10 +0400 Subject: hw/xtensa/xtfpga: fix FLASH mapping to boot region for KC705 On KC705 bootloader area is located at FLASH offset 0x06000000, not 0 as on older xtfpga boards. Cc: qemu-stable@nongnu.org Signed-off-by: Max Filippov --- hw/xtensa/xtensa_lx60.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c index 507dd88452..183527f6a7 100644 --- a/hw/xtensa/xtensa_lx60.c +++ b/hw/xtensa/xtensa_lx60.c @@ -42,6 +42,7 @@ typedef struct LxBoardDesc { hwaddr flash_base; size_t flash_size; + size_t flash_boot_base; size_t flash_sector_size; size_t sram_size; } LxBoardDesc; @@ -266,9 +267,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); memory_region_init_alias(flash_io, NULL, "lx60.flash", - flash_mr, 0, - board->flash_size < 0x02000000 ? - board->flash_size : 0x02000000); + flash_mr, board->flash_boot_base, + board->flash_size - board->flash_boot_base < 0x02000000 ? + board->flash_size - board->flash_boot_base : 0x02000000); memory_region_add_subregion(system_memory, 0xfe000000, flash_io); } @@ -313,6 +314,7 @@ static void xtensa_kc705_init(MachineState *machine) static const LxBoardDesc kc705_board = { .flash_base = 0xf0000000, .flash_size = 0x08000000, + .flash_boot_base = 0x06000000, .flash_sector_size = 0x20000, .sram_size = 0x2000000, }; -- cgit v1.2.3-55-g7522 From b707ab757e66e05a8447b4efe15733b10659a3dd Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 10:39:58 +0400 Subject: hw/xtensa: remove extraneous xtensa_ prefix from file names While at it rename lx60 (named after the first board of the family) to more generic xtfpga (the family name). Signed-off-by: Max Filippov --- hw/xtensa/Makefile.objs | 4 +- hw/xtensa/bootparam.h | 25 +++ hw/xtensa/sim.c | 118 ++++++++++++++ hw/xtensa/xtensa_bootparam.h | 25 --- hw/xtensa/xtensa_lx60.c | 360 ------------------------------------------- hw/xtensa/xtensa_sim.c | 118 -------------- hw/xtensa/xtfpga.c | 360 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 505 insertions(+), 505 deletions(-) create mode 100644 hw/xtensa/bootparam.h create mode 100644 hw/xtensa/sim.c delete mode 100644 hw/xtensa/xtensa_bootparam.h delete mode 100644 hw/xtensa/xtensa_lx60.c delete mode 100644 hw/xtensa/xtensa_sim.c create mode 100644 hw/xtensa/xtfpga.c diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs index 6ead7820c4..cb77dc3793 100644 --- a/hw/xtensa/Makefile.objs +++ b/hw/xtensa/Makefile.objs @@ -1,3 +1,3 @@ obj-y += pic_cpu.o -obj-y += xtensa_sim.o -obj-y += xtensa_lx60.o +obj-y += sim.o +obj-y += xtfpga.o diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h new file mode 100644 index 0000000000..38ef32bdb6 --- /dev/null +++ b/hw/xtensa/bootparam.h @@ -0,0 +1,25 @@ +#ifndef HW_XTENSA_BOOTPARAM +#define HW_XTENSA_BOOTPARAM + +typedef struct BpTag { + uint16_t tag; + uint16_t size; +} BpTag; + +static inline ram_addr_t put_tag(ram_addr_t addr, uint16_t tag, + size_t size, const void *data) +{ + BpTag bp_tag = { + .tag = tswap16(tag), + .size = tswap16((size + 3) & ~3), + }; + + cpu_physical_memory_write(addr, &bp_tag, sizeof(bp_tag)); + addr += sizeof(bp_tag); + cpu_physical_memory_write(addr, data, size); + addr += (size + 3) & ~3; + + return addr; +} + +#endif diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c new file mode 100644 index 0000000000..89da43c160 --- /dev/null +++ b/hw/xtensa/sim.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Open Source and Linux Lab nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sysemu/sysemu.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "elf.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" + +static uint64_t translate_phys_addr(void *opaque, uint64_t addr) +{ + XtensaCPU *cpu = opaque; + + return cpu_get_phys_page_debug(CPU(cpu), addr); +} + +static void sim_reset(void *opaque) +{ + XtensaCPU *cpu = opaque; + + cpu_reset(CPU(cpu)); +} + +static void xtensa_sim_init(MachineState *machine) +{ + XtensaCPU *cpu = NULL; + CPUXtensaState *env = NULL; + MemoryRegion *ram, *rom; + ram_addr_t ram_size = machine->ram_size; + const char *cpu_model = machine->cpu_model; + const char *kernel_filename = machine->kernel_filename; + int n; + + if (!cpu_model) { + cpu_model = XTENSA_DEFAULT_CPU_MODEL; + } + + for (n = 0; n < smp_cpus; n++) { + cpu = cpu_xtensa_init(cpu_model); + if (cpu == NULL) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + env = &cpu->env; + + env->sregs[PRID] = n; + qemu_register_reset(sim_reset, cpu); + /* Need MMU initialized prior to ELF loading, + * so that ELF gets loaded into virtual addresses + */ + sim_reset(cpu); + } + + ram = g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size); + vmstate_register_ram_global(ram); + memory_region_add_subregion(get_system_memory(), 0, ram); + + rom = g_malloc(sizeof(*rom)); + memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000); + vmstate_register_ram_global(rom); + memory_region_add_subregion(get_system_memory(), 0xfe000000, rom); + + if (kernel_filename) { + uint64_t elf_entry; + uint64_t elf_lowaddr; +#ifdef TARGET_WORDS_BIGENDIAN + int success = load_elf(kernel_filename, translate_phys_addr, cpu, + &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0); +#else + int success = load_elf(kernel_filename, translate_phys_addr, cpu, + &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0); +#endif + if (success > 0) { + env->pc = elf_entry; + } + } +} + +static QEMUMachine xtensa_sim_machine = { + .name = "sim", + .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")", + .is_default = true, + .init = xtensa_sim_init, + .max_cpus = 4, +}; + +static void xtensa_sim_machine_init(void) +{ + qemu_register_machine(&xtensa_sim_machine); +} + +machine_init(xtensa_sim_machine_init); diff --git a/hw/xtensa/xtensa_bootparam.h b/hw/xtensa/xtensa_bootparam.h deleted file mode 100644 index 38ef32bdb6..0000000000 --- a/hw/xtensa/xtensa_bootparam.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef HW_XTENSA_BOOTPARAM -#define HW_XTENSA_BOOTPARAM - -typedef struct BpTag { - uint16_t tag; - uint16_t size; -} BpTag; - -static inline ram_addr_t put_tag(ram_addr_t addr, uint16_t tag, - size_t size, const void *data) -{ - BpTag bp_tag = { - .tag = tswap16(tag), - .size = tswap16((size + 3) & ~3), - }; - - cpu_physical_memory_write(addr, &bp_tag, sizeof(bp_tag)); - addr += sizeof(bp_tag); - cpu_physical_memory_write(addr, data, size); - addr += (size + 3) & ~3; - - return addr; -} - -#endif diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c deleted file mode 100644 index 183527f6a7..0000000000 --- a/hw/xtensa/xtensa_lx60.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the Open Source and Linux Lab nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sysemu/sysemu.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "elf.h" -#include "exec/memory.h" -#include "exec/address-spaces.h" -#include "hw/char/serial.h" -#include "net/net.h" -#include "hw/sysbus.h" -#include "hw/block/flash.h" -#include "sysemu/blockdev.h" -#include "sysemu/char.h" -#include "xtensa_bootparam.h" - -typedef struct LxBoardDesc { - hwaddr flash_base; - size_t flash_size; - size_t flash_boot_base; - size_t flash_sector_size; - size_t sram_size; -} LxBoardDesc; - -typedef struct Lx60FpgaState { - MemoryRegion iomem; - uint32_t leds; - uint32_t switches; -} Lx60FpgaState; - -static void lx60_fpga_reset(void *opaque) -{ - Lx60FpgaState *s = opaque; - - s->leds = 0; - s->switches = 0; -} - -static uint64_t lx60_fpga_read(void *opaque, hwaddr addr, - unsigned size) -{ - Lx60FpgaState *s = opaque; - - switch (addr) { - case 0x0: /*build date code*/ - return 0x09272011; - - case 0x4: /*processor clock frequency, Hz*/ - return 10000000; - - case 0x8: /*LEDs (off = 0, on = 1)*/ - return s->leds; - - case 0xc: /*DIP switches (off = 0, on = 1)*/ - return s->switches; - } - return 0; -} - -static void lx60_fpga_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - Lx60FpgaState *s = opaque; - - switch (addr) { - case 0x8: /*LEDs (off = 0, on = 1)*/ - s->leds = val; - break; - - case 0x10: /*board reset*/ - if (val == 0xdead) { - qemu_system_reset_request(); - } - break; - } -} - -static const MemoryRegionOps lx60_fpga_ops = { - .read = lx60_fpga_read, - .write = lx60_fpga_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, - hwaddr base) -{ - Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); - - memory_region_init_io(&s->iomem, NULL, &lx60_fpga_ops, s, - "lx60.fpga", 0x10000); - memory_region_add_subregion(address_space, base, &s->iomem); - lx60_fpga_reset(s); - qemu_register_reset(lx60_fpga_reset, s); - return s; -} - -static void lx60_net_init(MemoryRegion *address_space, - hwaddr base, - hwaddr descriptors, - hwaddr buffers, - qemu_irq irq, NICInfo *nd) -{ - DeviceState *dev; - SysBusDevice *s; - MemoryRegion *ram; - - dev = qdev_create(NULL, "open_eth"); - qdev_set_nic_properties(dev, nd); - qdev_init_nofail(dev); - - s = SYS_BUS_DEVICE(dev); - sysbus_connect_irq(s, 0, irq); - memory_region_add_subregion(address_space, base, - sysbus_mmio_get_region(s, 0)); - memory_region_add_subregion(address_space, descriptors, - sysbus_mmio_get_region(s, 1)); - - ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, OBJECT(s), "open_eth.ram", 16384); - vmstate_register_ram_global(ram); - memory_region_add_subregion(address_space, buffers, ram); -} - -static uint64_t translate_phys_addr(void *opaque, uint64_t addr) -{ - XtensaCPU *cpu = opaque; - - return cpu_get_phys_page_debug(CPU(cpu), addr); -} - -static void lx60_reset(void *opaque) -{ - XtensaCPU *cpu = opaque; - - cpu_reset(CPU(cpu)); -} - -static void lx_init(const LxBoardDesc *board, MachineState *machine) -{ -#ifdef TARGET_WORDS_BIGENDIAN - int be = 1; -#else - int be = 0; -#endif - MemoryRegion *system_memory = get_system_memory(); - XtensaCPU *cpu = NULL; - CPUXtensaState *env = NULL; - MemoryRegion *ram, *rom, *system_io; - DriveInfo *dinfo; - pflash_t *flash = NULL; - const char *cpu_model = machine->cpu_model; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - int n; - - if (!cpu_model) { - cpu_model = XTENSA_DEFAULT_CPU_MODEL; - } - - for (n = 0; n < smp_cpus; n++) { - cpu = cpu_xtensa_init(cpu_model); - if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - env = &cpu->env; - - env->sregs[PRID] = n; - qemu_register_reset(lx60_reset, cpu); - /* Need MMU initialized prior to ELF loading, - * so that ELF gets loaded into virtual addresses - */ - cpu_reset(CPU(cpu)); - } - - ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "lx60.dram", machine->ram_size); - vmstate_register_ram_global(ram); - memory_region_add_subregion(system_memory, 0, ram); - - system_io = g_malloc(sizeof(*system_io)); - memory_region_init(system_io, NULL, "lx60.io", 224 * 1024 * 1024); - memory_region_add_subregion(system_memory, 0xf0000000, system_io); - lx60_fpga_init(system_io, 0x0d020000); - if (nd_table[0].used) { - lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, - xtensa_get_extint(env, 1), nd_table); - } - - if (!serial_hds[0]) { - serial_hds[0] = qemu_chr_new("serial0", "null", NULL); - } - - serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0), - 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); - - dinfo = drive_get(IF_PFLASH, 0, 0); - if (dinfo) { - flash = pflash_cfi01_register(board->flash_base, - NULL, "lx60.io.flash", board->flash_size, - dinfo->bdrv, board->flash_sector_size, - board->flash_size / board->flash_sector_size, - 4, 0x0000, 0x0000, 0x0000, 0x0000, be); - if (flash == NULL) { - fprintf(stderr, "Unable to mount pflash\n"); - exit(1); - } - } - - /* Use presence of kernel file name as 'boot from SRAM' switch. */ - if (kernel_filename) { - rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); - vmstate_register_ram_global(rom); - memory_region_add_subregion(system_memory, 0xfe000000, rom); - - /* Put kernel bootparameters to the end of that SRAM */ - if (kernel_cmdline) { - size_t cmdline_size = strlen(kernel_cmdline) + 1; - size_t bp_size = sizeof(BpTag[4]) + cmdline_size; - uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff; - - env->regs[2] = tagptr; - - tagptr = put_tag(tagptr, 0x7b0b, 0, NULL); - if (cmdline_size > 1) { - tagptr = put_tag(tagptr, 0x1001, - cmdline_size, kernel_cmdline); - } - tagptr = put_tag(tagptr, 0x7e0b, 0, NULL); - } - uint64_t elf_entry; - uint64_t elf_lowaddr; - int success = load_elf(kernel_filename, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0); - if (success > 0) { - env->pc = elf_entry; - } - } else { - if (flash) { - MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); - MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); - - memory_region_init_alias(flash_io, NULL, "lx60.flash", - flash_mr, board->flash_boot_base, - board->flash_size - board->flash_boot_base < 0x02000000 ? - board->flash_size - board->flash_boot_base : 0x02000000); - memory_region_add_subregion(system_memory, 0xfe000000, - flash_io); - } - } -} - -static void xtensa_lx60_init(MachineState *machine) -{ - static const LxBoardDesc lx60_board = { - .flash_base = 0xf8000000, - .flash_size = 0x00400000, - .flash_sector_size = 0x10000, - .sram_size = 0x20000, - }; - lx_init(&lx60_board, machine); -} - -static void xtensa_lx200_init(MachineState *machine) -{ - static const LxBoardDesc lx200_board = { - .flash_base = 0xf8000000, - .flash_size = 0x01000000, - .flash_sector_size = 0x20000, - .sram_size = 0x2000000, - }; - lx_init(&lx200_board, machine); -} - -static void xtensa_ml605_init(MachineState *machine) -{ - static const LxBoardDesc ml605_board = { - .flash_base = 0xf8000000, - .flash_size = 0x02000000, - .flash_sector_size = 0x20000, - .sram_size = 0x2000000, - }; - lx_init(&ml605_board, machine); -} - -static void xtensa_kc705_init(MachineState *machine) -{ - static const LxBoardDesc kc705_board = { - .flash_base = 0xf0000000, - .flash_size = 0x08000000, - .flash_boot_base = 0x06000000, - .flash_sector_size = 0x20000, - .sram_size = 0x2000000, - }; - lx_init(&kc705_board, machine); -} - -static QEMUMachine xtensa_lx60_machine = { - .name = "lx60", - .desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", - .init = xtensa_lx60_init, - .max_cpus = 4, -}; - -static QEMUMachine xtensa_lx200_machine = { - .name = "lx200", - .desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", - .init = xtensa_lx200_init, - .max_cpus = 4, -}; - -static QEMUMachine xtensa_ml605_machine = { - .name = "ml605", - .desc = "ml605 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", - .init = xtensa_ml605_init, - .max_cpus = 4, -}; - -static QEMUMachine xtensa_kc705_machine = { - .name = "kc705", - .desc = "kc705 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", - .init = xtensa_kc705_init, - .max_cpus = 4, -}; - -static void xtensa_lx_machines_init(void) -{ - qemu_register_machine(&xtensa_lx60_machine); - qemu_register_machine(&xtensa_lx200_machine); - qemu_register_machine(&xtensa_ml605_machine); - qemu_register_machine(&xtensa_kc705_machine); -} - -machine_init(xtensa_lx_machines_init); diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/xtensa_sim.c deleted file mode 100644 index 89da43c160..0000000000 --- a/hw/xtensa/xtensa_sim.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the Open Source and Linux Lab nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sysemu/sysemu.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "elf.h" -#include "exec/memory.h" -#include "exec/address-spaces.h" - -static uint64_t translate_phys_addr(void *opaque, uint64_t addr) -{ - XtensaCPU *cpu = opaque; - - return cpu_get_phys_page_debug(CPU(cpu), addr); -} - -static void sim_reset(void *opaque) -{ - XtensaCPU *cpu = opaque; - - cpu_reset(CPU(cpu)); -} - -static void xtensa_sim_init(MachineState *machine) -{ - XtensaCPU *cpu = NULL; - CPUXtensaState *env = NULL; - MemoryRegion *ram, *rom; - ram_addr_t ram_size = machine->ram_size; - const char *cpu_model = machine->cpu_model; - const char *kernel_filename = machine->kernel_filename; - int n; - - if (!cpu_model) { - cpu_model = XTENSA_DEFAULT_CPU_MODEL; - } - - for (n = 0; n < smp_cpus; n++) { - cpu = cpu_xtensa_init(cpu_model); - if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - env = &cpu->env; - - env->sregs[PRID] = n; - qemu_register_reset(sim_reset, cpu); - /* Need MMU initialized prior to ELF loading, - * so that ELF gets loaded into virtual addresses - */ - sim_reset(cpu); - } - - ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size); - vmstate_register_ram_global(ram); - memory_region_add_subregion(get_system_memory(), 0, ram); - - rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000); - vmstate_register_ram_global(rom); - memory_region_add_subregion(get_system_memory(), 0xfe000000, rom); - - if (kernel_filename) { - uint64_t elf_entry; - uint64_t elf_lowaddr; -#ifdef TARGET_WORDS_BIGENDIAN - int success = load_elf(kernel_filename, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0); -#else - int success = load_elf(kernel_filename, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0); -#endif - if (success > 0) { - env->pc = elf_entry; - } - } -} - -static QEMUMachine xtensa_sim_machine = { - .name = "sim", - .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")", - .is_default = true, - .init = xtensa_sim_init, - .max_cpus = 4, -}; - -static void xtensa_sim_machine_init(void) -{ - qemu_register_machine(&xtensa_sim_machine); -} - -machine_init(xtensa_sim_machine_init); diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c new file mode 100644 index 0000000000..0b8a2eda06 --- /dev/null +++ b/hw/xtensa/xtfpga.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Open Source and Linux Lab nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sysemu/sysemu.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "elf.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" +#include "hw/char/serial.h" +#include "net/net.h" +#include "hw/sysbus.h" +#include "hw/block/flash.h" +#include "sysemu/blockdev.h" +#include "sysemu/char.h" +#include "bootparam.h" + +typedef struct LxBoardDesc { + hwaddr flash_base; + size_t flash_size; + size_t flash_boot_base; + size_t flash_sector_size; + size_t sram_size; +} LxBoardDesc; + +typedef struct Lx60FpgaState { + MemoryRegion iomem; + uint32_t leds; + uint32_t switches; +} Lx60FpgaState; + +static void lx60_fpga_reset(void *opaque) +{ + Lx60FpgaState *s = opaque; + + s->leds = 0; + s->switches = 0; +} + +static uint64_t lx60_fpga_read(void *opaque, hwaddr addr, + unsigned size) +{ + Lx60FpgaState *s = opaque; + + switch (addr) { + case 0x0: /*build date code*/ + return 0x09272011; + + case 0x4: /*processor clock frequency, Hz*/ + return 10000000; + + case 0x8: /*LEDs (off = 0, on = 1)*/ + return s->leds; + + case 0xc: /*DIP switches (off = 0, on = 1)*/ + return s->switches; + } + return 0; +} + +static void lx60_fpga_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + Lx60FpgaState *s = opaque; + + switch (addr) { + case 0x8: /*LEDs (off = 0, on = 1)*/ + s->leds = val; + break; + + case 0x10: /*board reset*/ + if (val == 0xdead) { + qemu_system_reset_request(); + } + break; + } +} + +static const MemoryRegionOps lx60_fpga_ops = { + .read = lx60_fpga_read, + .write = lx60_fpga_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, + hwaddr base) +{ + Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); + + memory_region_init_io(&s->iomem, NULL, &lx60_fpga_ops, s, + "lx60.fpga", 0x10000); + memory_region_add_subregion(address_space, base, &s->iomem); + lx60_fpga_reset(s); + qemu_register_reset(lx60_fpga_reset, s); + return s; +} + +static void lx60_net_init(MemoryRegion *address_space, + hwaddr base, + hwaddr descriptors, + hwaddr buffers, + qemu_irq irq, NICInfo *nd) +{ + DeviceState *dev; + SysBusDevice *s; + MemoryRegion *ram; + + dev = qdev_create(NULL, "open_eth"); + qdev_set_nic_properties(dev, nd); + qdev_init_nofail(dev); + + s = SYS_BUS_DEVICE(dev); + sysbus_connect_irq(s, 0, irq); + memory_region_add_subregion(address_space, base, + sysbus_mmio_get_region(s, 0)); + memory_region_add_subregion(address_space, descriptors, + sysbus_mmio_get_region(s, 1)); + + ram = g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, OBJECT(s), "open_eth.ram", 16384); + vmstate_register_ram_global(ram); + memory_region_add_subregion(address_space, buffers, ram); +} + +static uint64_t translate_phys_addr(void *opaque, uint64_t addr) +{ + XtensaCPU *cpu = opaque; + + return cpu_get_phys_page_debug(CPU(cpu), addr); +} + +static void lx60_reset(void *opaque) +{ + XtensaCPU *cpu = opaque; + + cpu_reset(CPU(cpu)); +} + +static void lx_init(const LxBoardDesc *board, MachineState *machine) +{ +#ifdef TARGET_WORDS_BIGENDIAN + int be = 1; +#else + int be = 0; +#endif + MemoryRegion *system_memory = get_system_memory(); + XtensaCPU *cpu = NULL; + CPUXtensaState *env = NULL; + MemoryRegion *ram, *rom, *system_io; + DriveInfo *dinfo; + pflash_t *flash = NULL; + const char *cpu_model = machine->cpu_model; + const char *kernel_filename = machine->kernel_filename; + const char *kernel_cmdline = machine->kernel_cmdline; + int n; + + if (!cpu_model) { + cpu_model = XTENSA_DEFAULT_CPU_MODEL; + } + + for (n = 0; n < smp_cpus; n++) { + cpu = cpu_xtensa_init(cpu_model); + if (cpu == NULL) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + env = &cpu->env; + + env->sregs[PRID] = n; + qemu_register_reset(lx60_reset, cpu); + /* Need MMU initialized prior to ELF loading, + * so that ELF gets loaded into virtual addresses + */ + cpu_reset(CPU(cpu)); + } + + ram = g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, NULL, "lx60.dram", machine->ram_size); + vmstate_register_ram_global(ram); + memory_region_add_subregion(system_memory, 0, ram); + + system_io = g_malloc(sizeof(*system_io)); + memory_region_init(system_io, NULL, "lx60.io", 224 * 1024 * 1024); + memory_region_add_subregion(system_memory, 0xf0000000, system_io); + lx60_fpga_init(system_io, 0x0d020000); + if (nd_table[0].used) { + lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, + xtensa_get_extint(env, 1), nd_table); + } + + if (!serial_hds[0]) { + serial_hds[0] = qemu_chr_new("serial0", "null", NULL); + } + + serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0), + 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); + + dinfo = drive_get(IF_PFLASH, 0, 0); + if (dinfo) { + flash = pflash_cfi01_register(board->flash_base, + NULL, "lx60.io.flash", board->flash_size, + dinfo->bdrv, board->flash_sector_size, + board->flash_size / board->flash_sector_size, + 4, 0x0000, 0x0000, 0x0000, 0x0000, be); + if (flash == NULL) { + fprintf(stderr, "Unable to mount pflash\n"); + exit(1); + } + } + + /* Use presence of kernel file name as 'boot from SRAM' switch. */ + if (kernel_filename) { + rom = g_malloc(sizeof(*rom)); + memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); + vmstate_register_ram_global(rom); + memory_region_add_subregion(system_memory, 0xfe000000, rom); + + /* Put kernel bootparameters to the end of that SRAM */ + if (kernel_cmdline) { + size_t cmdline_size = strlen(kernel_cmdline) + 1; + size_t bp_size = sizeof(BpTag[4]) + cmdline_size; + uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff; + + env->regs[2] = tagptr; + + tagptr = put_tag(tagptr, 0x7b0b, 0, NULL); + if (cmdline_size > 1) { + tagptr = put_tag(tagptr, 0x1001, + cmdline_size, kernel_cmdline); + } + tagptr = put_tag(tagptr, 0x7e0b, 0, NULL); + } + uint64_t elf_entry; + uint64_t elf_lowaddr; + int success = load_elf(kernel_filename, translate_phys_addr, cpu, + &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0); + if (success > 0) { + env->pc = elf_entry; + } + } else { + if (flash) { + MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); + MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); + + memory_region_init_alias(flash_io, NULL, "lx60.flash", + flash_mr, board->flash_boot_base, + board->flash_size - board->flash_boot_base < 0x02000000 ? + board->flash_size - board->flash_boot_base : 0x02000000); + memory_region_add_subregion(system_memory, 0xfe000000, + flash_io); + } + } +} + +static void xtensa_lx60_init(MachineState *machine) +{ + static const LxBoardDesc lx60_board = { + .flash_base = 0xf8000000, + .flash_size = 0x00400000, + .flash_sector_size = 0x10000, + .sram_size = 0x20000, + }; + lx_init(&lx60_board, machine); +} + +static void xtensa_lx200_init(MachineState *machine) +{ + static const LxBoardDesc lx200_board = { + .flash_base = 0xf8000000, + .flash_size = 0x01000000, + .flash_sector_size = 0x20000, + .sram_size = 0x2000000, + }; + lx_init(&lx200_board, machine); +} + +static void xtensa_ml605_init(MachineState *machine) +{ + static const LxBoardDesc ml605_board = { + .flash_base = 0xf8000000, + .flash_size = 0x02000000, + .flash_sector_size = 0x20000, + .sram_size = 0x2000000, + }; + lx_init(&ml605_board, machine); +} + +static void xtensa_kc705_init(MachineState *machine) +{ + static const LxBoardDesc kc705_board = { + .flash_base = 0xf0000000, + .flash_size = 0x08000000, + .flash_boot_base = 0x06000000, + .flash_sector_size = 0x20000, + .sram_size = 0x2000000, + }; + lx_init(&kc705_board, machine); +} + +static QEMUMachine xtensa_lx60_machine = { + .name = "lx60", + .desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", + .init = xtensa_lx60_init, + .max_cpus = 4, +}; + +static QEMUMachine xtensa_lx200_machine = { + .name = "lx200", + .desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", + .init = xtensa_lx200_init, + .max_cpus = 4, +}; + +static QEMUMachine xtensa_ml605_machine = { + .name = "ml605", + .desc = "ml605 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", + .init = xtensa_ml605_init, + .max_cpus = 4, +}; + +static QEMUMachine xtensa_kc705_machine = { + .name = "kc705", + .desc = "kc705 EVB (" XTENSA_DEFAULT_CPU_MODEL ")", + .init = xtensa_kc705_init, + .max_cpus = 4, +}; + +static void xtensa_lx_machines_init(void) +{ + qemu_register_machine(&xtensa_lx60_machine); + qemu_register_machine(&xtensa_lx200_machine); + qemu_register_machine(&xtensa_ml605_machine); + qemu_register_machine(&xtensa_kc705_machine); +} + +machine_init(xtensa_lx_machines_init); -- cgit v1.2.3-55-g7522 From 8488ab021ba40383f4ab3a595f006fe920737397 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 16:14:56 +0400 Subject: hw/xtensa: replace fprintfs with error_report Signed-off-by: Max Filippov --- hw/xtensa/sim.c | 6 ++++-- hw/xtensa/xtfpga.c | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index 89da43c160..9642bf54c7 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -31,6 +31,7 @@ #include "elf.h" #include "exec/memory.h" #include "exec/address-spaces.h" +#include "qemu/error-report.h" static uint64_t translate_phys_addr(void *opaque, uint64_t addr) { @@ -63,8 +64,9 @@ static void xtensa_sim_init(MachineState *machine) for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); + error_report("unable to find CPU definition '%s'\n", + cpu_model); + exit(EXIT_FAILURE); } env = &cpu->env; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 0b8a2eda06..75bc479e36 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -37,6 +37,7 @@ #include "hw/block/flash.h" #include "sysemu/blockdev.h" #include "sysemu/char.h" +#include "qemu/error-report.h" #include "bootparam.h" typedef struct LxBoardDesc { @@ -185,8 +186,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); + error_report("unable to find CPU definition '%s'\n", + cpu_model); + exit(EXIT_FAILURE); } env = &cpu->env; @@ -227,8 +229,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) board->flash_size / board->flash_sector_size, 4, 0x0000, 0x0000, 0x0000, 0x0000, be); if (flash == NULL) { - fprintf(stderr, "Unable to mount pflash\n"); - exit(1); + error_report("unable to mount pflash\n"); + exit(EXIT_FAILURE); } } -- cgit v1.2.3-55-g7522 From 37b259d034c4e6eda5e7a677238d8a5efb666e9f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 23 Jun 2014 18:42:39 +0400 Subject: hw/xtensa/xtfpga: retrieve parameters from machine_opts Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 75bc479e36..0aa3eeb046 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -174,9 +174,10 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) MemoryRegion *ram, *rom, *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; + QemuOpts *machine_opts = qemu_get_machine_opts(); const char *cpu_model = machine->cpu_model; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; + const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); + const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); int n; if (!cpu_model) { -- cgit v1.2.3-55-g7522 From 62dbaede80b396aaae5394a9b6922b51be835e86 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 10:29:29 +0400 Subject: hw/xtensa/xtfpga: use symbolic constants for bootparam tags Import bootparam tag names from linux/arch/xtensa/include/asm/bootparam.h No functional changes. Signed-off-by: Max Filippov --- hw/xtensa/bootparam.h | 10 ++++++++++ hw/xtensa/xtfpga.c | 6 +++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index 38ef32bdb6..e6cf3b1492 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -1,6 +1,16 @@ #ifndef HW_XTENSA_BOOTPARAM #define HW_XTENSA_BOOTPARAM +#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ +#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ +#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ +#define BP_TAG_SERIAL_BAUDRATE 0x1004 /* baud rate of current console. */ +#define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ +#define BP_TAG_FDT 0x1006 /* flat device tree addr */ + +#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */ +#define BP_TAG_LAST 0x7E0B /* last tag */ + typedef struct BpTag { uint16_t tag; uint16_t size; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 0aa3eeb046..6d070b0d64 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -250,12 +250,12 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) env->regs[2] = tagptr; - tagptr = put_tag(tagptr, 0x7b0b, 0, NULL); + tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); if (cmdline_size > 1) { - tagptr = put_tag(tagptr, 0x1001, + tagptr = put_tag(tagptr, BP_TAG_COMMAND_LINE, cmdline_size, kernel_cmdline); } - tagptr = put_tag(tagptr, 0x7e0b, 0, NULL); + tagptr = put_tag(tagptr, BP_TAG_LAST, 0, NULL); } uint64_t elf_entry; uint64_t elf_lowaddr; -- cgit v1.2.3-55-g7522 From a9a28591fbd4dc20d19b6408361b45c9b7300434 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 13:10:38 +0400 Subject: hw/xtensa/xtfpga: refactor bootparameters filling Separate filling first/last tag and size calculation from the kernel command line setup. Signed-off-by: Max Filippov --- hw/xtensa/bootparam.h | 5 +++++ hw/xtensa/xtfpga.c | 28 ++++++++++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index e6cf3b1492..e839bee576 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -16,6 +16,11 @@ typedef struct BpTag { uint16_t size; } BpTag; +static inline size_t get_tag_size(size_t data_size) +{ + return data_size + sizeof(BpTag) + 4; +} + static inline ram_addr_t put_tag(ram_addr_t addr, uint16_t tag, size_t size, const void *data) { diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 6d070b0d64..689d07843b 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -237,26 +237,30 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { + size_t bp_size = 2 * get_tag_size(0); + uint32_t tagptr = 0xfe000000 + board->sram_size; + uint32_t cur_tagptr; + rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); vmstate_register_ram_global(rom); memory_region_add_subregion(system_memory, 0xfe000000, rom); + if (kernel_cmdline) { + bp_size += get_tag_size(strlen(kernel_cmdline) + 1); + } + /* Put kernel bootparameters to the end of that SRAM */ + tagptr = (tagptr - bp_size) & ~0xff; + cur_tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); + if (kernel_cmdline) { - size_t cmdline_size = strlen(kernel_cmdline) + 1; - size_t bp_size = sizeof(BpTag[4]) + cmdline_size; - uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff; - - env->regs[2] = tagptr; - - tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); - if (cmdline_size > 1) { - tagptr = put_tag(tagptr, BP_TAG_COMMAND_LINE, - cmdline_size, kernel_cmdline); - } - tagptr = put_tag(tagptr, BP_TAG_LAST, 0, NULL); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, + strlen(kernel_cmdline) + 1, kernel_cmdline); } + cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); + env->regs[2] = tagptr; + uint64_t elf_entry; uint64_t elf_lowaddr; int success = load_elf(kernel_filename, translate_phys_addr, cpu, -- cgit v1.2.3-55-g7522 From b6edea8b687182bc4572c4e2e8af48f32b213dad Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 23 Jun 2014 17:24:48 +0400 Subject: hw/xtensa/xtfpga: add memory info to bootparam Signed-off-by: Max Filippov --- hw/xtensa/bootparam.h | 9 +++++++++ hw/xtensa/xtfpga.c | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h index e839bee576..955f4e86e3 100644 --- a/hw/xtensa/bootparam.h +++ b/hw/xtensa/bootparam.h @@ -16,6 +16,15 @@ typedef struct BpTag { uint16_t size; } BpTag; +typedef struct BpMemInfo { + uint32_t type; + uint32_t start; + uint32_t end; +} BpMemInfo; + +#define MEMORY_TYPE_CONVENTIONAL 0x1000 +#define MEMORY_TYPE_NONE 0x2000 + static inline size_t get_tag_size(size_t data_size) { return data_size + sizeof(BpTag) + 4; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 689d07843b..97e5842e6d 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -237,9 +237,14 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { - size_t bp_size = 2 * get_tag_size(0); + size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ uint32_t tagptr = 0xfe000000 + board->sram_size; uint32_t cur_tagptr; + BpMemInfo memory_location = { + .type = tswap32(MEMORY_TYPE_CONVENTIONAL), + .start = tswap32(0), + .end = tswap32(machine->ram_size), + }; rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); @@ -253,6 +258,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; cur_tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_MEMORY, + sizeof(memory_location), &memory_location); if (kernel_cmdline) { cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, -- cgit v1.2.3-55-g7522 From 364d4802429a5c7d3985f322e54a104024fd3f75 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 4 Mar 2013 07:07:52 +0400 Subject: hw/xtensa/xtfpga: implement uImage loading Provide a simple bootloader code at the reset address that jumps to the loaded image entry point when it's not equal to the reset address. This is needed because the old method of setting pc doesn't work due to cpu reset done after the machine setup. Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 97e5842e6d..0e0d825556 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -237,6 +237,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { + uint32_t entry_point = env->pc; size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ uint32_t tagptr = 0xfe000000 + board->sram_size; uint32_t cur_tagptr; @@ -273,7 +274,29 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) int success = load_elf(kernel_filename, translate_phys_addr, cpu, &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0); if (success > 0) { - env->pc = elf_entry; + entry_point = elf_entry; + } else { + hwaddr ep; + int is_linux; + success = load_uimage(kernel_filename, &ep, NULL, &is_linux); + if (success > 0 && is_linux) { + entry_point = ep; + } else { + error_report("could not load kernel '%s'\n", + kernel_filename); + exit(EXIT_FAILURE); + } + } + if (entry_point != env->pc) { + static const uint8_t jx_a0[] = { +#ifdef TARGET_WORDS_BIGENDIAN + 0x0a, 0, 0, +#else + 0xa0, 0, 0, +#endif + }; + env->regs[0] = entry_point; + cpu_physical_memory_write(env->pc, jx_a0, sizeof(jx_a0)); } } else { if (flash) { -- cgit v1.2.3-55-g7522 From 996dfe98ed6bd57290f198ca29d0d9c614b4feef Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 23 Jun 2014 18:45:43 +0400 Subject: hw/xtensa/xtfpga: implement DTB loading Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 0e0d825556..01825d61c2 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -37,6 +37,7 @@ #include "hw/block/flash.h" #include "sysemu/blockdev.h" #include "sysemu/char.h" +#include "sysemu/device_tree.h" #include "qemu/error-report.h" #include "bootparam.h" @@ -178,6 +179,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) const char *cpu_model = machine->cpu_model; const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); + const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); int n; if (!cpu_model) { @@ -246,6 +248,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) .start = tswap32(0), .end = tswap32(machine->ram_size), }; + uint32_t lowmem_end = machine->ram_size < 0x08000000 ? + machine->ram_size : 0x08000000; + uint32_t cur_lowmem = QEMU_ALIGN_UP(lowmem_end / 2, 4096); rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); @@ -255,6 +260,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (kernel_cmdline) { bp_size += get_tag_size(strlen(kernel_cmdline) + 1); } + if (dtb_filename) { + bp_size += get_tag_size(sizeof(uint32_t)); + } /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; @@ -266,6 +274,21 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, strlen(kernel_cmdline) + 1, kernel_cmdline); } + if (dtb_filename) { + int fdt_size; + void *fdt = load_device_tree(dtb_filename, &fdt_size); + uint32_t dtb_addr = tswap32(cur_lowmem); + + if (!fdt) { + error_report("could not load DTB '%s'\n", dtb_filename); + exit(EXIT_FAILURE); + } + + cpu_physical_memory_write(cur_lowmem, fdt, fdt_size); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_FDT, + sizeof(dtb_addr), &dtb_addr); + cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4096); + } cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); env->regs[2] = tagptr; -- cgit v1.2.3-55-g7522 From f55b32e7499b291058a0d0fd7d35b14c24791684 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 21 Jun 2014 13:35:35 +0400 Subject: hw/xtensa/xtfpga: implement initrd loading Signed-off-by: Max Filippov --- hw/xtensa/xtfpga.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 01825d61c2..a2dff5a13e 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -180,6 +180,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); + const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); int n; if (!cpu_model) { @@ -263,6 +264,9 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (dtb_filename) { bp_size += get_tag_size(sizeof(uint32_t)); } + if (initrd_filename) { + bp_size += get_tag_size(sizeof(BpMemInfo)); + } /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; @@ -289,6 +293,26 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) sizeof(dtb_addr), &dtb_addr); cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4096); } + if (initrd_filename) { + BpMemInfo initrd_location = { 0 }; + int initrd_size = load_ramdisk(initrd_filename, cur_lowmem, + lowmem_end - cur_lowmem); + + if (initrd_size < 0) { + initrd_size = load_image_targphys(initrd_filename, + cur_lowmem, + lowmem_end - cur_lowmem); + } + if (initrd_size < 0) { + error_report("could not load initrd '%s'\n", initrd_filename); + exit(EXIT_FAILURE); + } + initrd_location.start = tswap32(cur_lowmem); + initrd_location.end = tswap32(cur_lowmem + initrd_size); + cur_tagptr = put_tag(cur_tagptr, BP_TAG_INITRD, + sizeof(initrd_location), &initrd_location); + cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + initrd_size, 4096); + } cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); env->regs[2] = tagptr; -- cgit v1.2.3-55-g7522