diff options
author | Blue Swirl <blauwirbel@gmail.com> | 2011-11-02 20:52:23 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2011-11-02 20:52:23 +0000 |
commit | 932eacc158c064935c7bab920c88a93a629e1ca4 (patch) | |
tree | 9ef2c78808c180bf937fc1905073ee93ce3b601f | |
parent | c51d9cb5b6e2fde9878d2be23dab389c2882de93 (diff) | |
parent | 556ba6684547f5f0aae60aaa2a16e39e43f9739d (diff) |
Merge branch 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa
* 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa:
xtensa_lx60: fix build date code and change memory region names
xtensa_lx60: pass kernel arguments from -append
xtensa_lx60: add FLASH support
target-xtensa: raise an exception for invalid and reserved opcodes
target-xtensa: handle cache options in the overlay tool
target-xtensa: mask out undefined bits of WINDOWSTART SR
-rw-r--r-- | default-configs/xtensa-softmmu.mak | 1 | ||||
-rw-r--r-- | default-configs/xtensaeb-softmmu.mak | 1 | ||||
-rw-r--r-- | hw/xtensa_bootparam.h | 25 | ||||
-rw-r--r-- | hw/xtensa_lx60.c | 111 | ||||
-rw-r--r-- | target-xtensa/overlay_tool.h | 6 | ||||
-rw-r--r-- | target-xtensa/translate.c | 9 |
6 files changed, 135 insertions, 18 deletions
diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak index 7f0df3499e..9d8899cde7 100644 --- a/default-configs/xtensa-softmmu.mak +++ b/default-configs/xtensa-softmmu.mak @@ -2,3 +2,4 @@ CONFIG_SERIAL=y CONFIG_OPENCORES_ETH=y +CONFIG_PFLASH_CFI01=y diff --git a/default-configs/xtensaeb-softmmu.mak b/default-configs/xtensaeb-softmmu.mak index 7f0df3499e..9d8899cde7 100644 --- a/default-configs/xtensaeb-softmmu.mak +++ b/default-configs/xtensaeb-softmmu.mak @@ -2,3 +2,4 @@ CONFIG_SERIAL=y CONFIG_OPENCORES_ETH=y +CONFIG_PFLASH_CFI01=y 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_lx60.c b/hw/xtensa_lx60.c index 3cebca1cfc..8947157bfc 100644 --- a/hw/xtensa_lx60.c +++ b/hw/xtensa_lx60.c @@ -33,6 +33,14 @@ #include "exec-memory.h" #include "pc.h" #include "sysbus.h" +#include "flash.h" +#include "xtensa_bootparam.h" + +typedef struct LxBoardDesc { + size_t flash_size; + size_t flash_sector_size; + size_t sram_size; +} LxBoardDesc; typedef struct Lx60FpgaState { MemoryRegion iomem; @@ -55,7 +63,7 @@ static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr, switch (addr) { case 0x0: /*build date code*/ - return 0x27092011; + return 0x09272011; case 0x4: /*processor clock frequency, Hz*/ return 10000000; @@ -99,7 +107,7 @@ static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); memory_region_init_io(&s->iomem, &lx60_fpga_ops, s, - "lx60-fpga", 0x10000); + "lx60.fpga", 0x10000); memory_region_add_subregion(address_space, base, &s->iomem); lx60_fpga_reset(s); qemu_register_reset(lx60_fpga_reset, s); @@ -142,8 +150,8 @@ static void lx60_reset(void *env) cpu_reset(env); } -static void lx60_init(ram_addr_t ram_size, - const char *boot_device, +static void lx_init(const LxBoardDesc *board, + ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { @@ -155,8 +163,14 @@ static void lx60_init(ram_addr_t ram_size, MemoryRegion *system_memory = get_system_memory(); CPUState *env = NULL; MemoryRegion *ram, *rom, *system_io; + DriveInfo *dinfo; + pflash_t *flash = NULL; int n; + if (!cpu_model) { + cpu_model = "dc232b"; + } + for (n = 0; n < smp_cpus; n++) { env = cpu_init(cpu_model); if (!env) { @@ -172,15 +186,11 @@ static void lx60_init(ram_addr_t ram_size, } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size); + memory_region_init_ram(ram, NULL, "lx60.dram", ram_size); memory_region_add_subregion(system_memory, 0, ram); - rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000); - memory_region_add_subregion(system_memory, 0xfe000000, rom); - system_io = g_malloc(sizeof(*system_io)); - memory_region_init(system_io, "system.io", 224 * 1024 * 1024); + memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024); memory_region_add_subregion(system_memory, 0xf0000000, system_io); lx60_fpga_init(system_io, 0x0d020000); if (nd_table[0].vlan) { @@ -195,7 +205,40 @@ static void lx60_init(ram_addr_t ram_size, 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(0xf8000000, + 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); + 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, env, @@ -203,6 +246,16 @@ static void lx60_init(ram_addr_t ram_size, 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, "lx60.flash", + flash_mr, 0, board->flash_size); + memory_region_add_subregion(system_memory, 0xfe000000, + flash_io); + } } } @@ -211,10 +264,28 @@ static void xtensa_lx60_init(ram_addr_t ram_size, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { - if (!cpu_model) { - cpu_model = "dc232b"; - } - lx60_init(ram_size, boot_device, kernel_filename, kernel_cmdline, + static const LxBoardDesc lx60_board = { + .flash_size = 0x400000, + .flash_sector_size = 0x10000, + .sram_size = 0x20000, + }; + lx_init(&lx60_board, ram_size, boot_device, + kernel_filename, kernel_cmdline, + initrd_filename, cpu_model); +} + +static void xtensa_lx200_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + static const LxBoardDesc lx200_board = { + .flash_size = 0x1000000, + .flash_sector_size = 0x20000, + .sram_size = 0x2000000, + }; + lx_init(&lx200_board, ram_size, boot_device, + kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } @@ -225,9 +296,17 @@ static QEMUMachine xtensa_lx60_machine = { .max_cpus = 4, }; -static void xtensa_lx60_machine_init(void) +static QEMUMachine xtensa_lx200_machine = { + .name = "lx200", + .desc = "lx200 EVB (dc232b)", + .init = xtensa_lx200_init, + .max_cpus = 4, +}; + +static void xtensa_lx_machines_init(void) { qemu_register_machine(&xtensa_lx60_machine); + qemu_register_machine(&xtensa_lx200_machine); } -machine_init(xtensa_lx60_machine_init); +machine_init(xtensa_lx_machines_init); diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h index 060e8e54d1..9cef27d03e 100644 --- a/target-xtensa/overlay_tool.h +++ b/target-xtensa/overlay_tool.h @@ -71,6 +71,12 @@ XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT) | \ XCHAL_OPTION(XCHAL_HAVE_CCOUNT, XTENSA_OPTION_TIMER_INTERRUPT) | \ /* Local memory, TODO */ \ + XCHAL_OPTION(XCHAL_ICACHE_WAYS, XTENSA_OPTION_ICACHE) | \ + XCHAL_OPTION(XCHAL_ICACHE_LINE_LOCKABLE, \ + XTENSA_OPTION_ICACHE_INDEX_LOCK) | \ + XCHAL_OPTION(XCHAL_DCACHE_WAYS, XTENSA_OPTION_DCACHE) | \ + XCHAL_OPTION(XCHAL_DCACHE_LINE_LOCKABLE, \ + XTENSA_OPTION_DCACHE_INDEX_LOCK) | \ XCHAL_OPTION(XCHAL_UNALIGNED_LOAD_HW, XTENSA_OPTION_HW_ALIGNMENT) | \ /* Memory protection and translation */ \ XCHAL_OPTION(XCHAL_HAVE_MIMIC_CACHEATTR, \ diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 1688bb2462..c81450d1a5 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -266,6 +266,10 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause) gen_helper_exception_cause(tpc, tcause); tcg_temp_free(tpc); tcg_temp_free(tcause); + if (cause == ILLEGAL_INSTRUCTION_CAUSE || + cause == SYSCALL_CAUSE) { + dc->is_jmp = DISAS_UPDATE; + } } static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause, @@ -283,6 +287,7 @@ static void gen_check_privilege(DisasContext *dc) { if (dc->cring) { gen_exception_cause(dc, PRIVILEGED_CAUSE); + dc->is_jmp = DISAS_UPDATE; } } @@ -466,7 +471,7 @@ static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v) static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v) { - tcg_gen_mov_i32(cpu_SR[sr], v); + tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1); reset_used_window(dc); } @@ -2378,7 +2383,7 @@ static void disas_xtensa_insn(DisasContext *dc) invalid_opcode: qemu_log("INVALID(pc = %08x)\n", dc->pc); - dc->pc = dc->next_pc; + gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); #undef HAS_OPTION } |