diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-01-18 10:28:26 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-01-18 10:28:26 +0000 |
commit | 20b8016ed847ac751e508c38aa27a9f8ecb93ac8 (patch) | |
tree | 1205e1aa81e75d1b5d232a27b565878814913417 /hw | |
parent | e0cbcf1eea16e81f116560130a1b36da711fb102 (diff) | |
parent | a8259b53230782f5e0a0d66013655c4ed5d71b7e (diff) | |
download | qemu-20b8016ed847ac751e508c38aa27a9f8ecb93ac8.zip qemu-20b8016ed847ac751e508c38aa27a9f8ecb93ac8.tar.gz qemu-20b8016ed847ac751e508c38aa27a9f8ecb93ac8.tar.bz2 |
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210117-3' into staging
First RISC-V PR for 6.0
This PR:
- Fixes some issues with the m25p80
- Improves GDB support for RISC-V
- Fixes some Linux boot issues, specifiaclly 32-bit boot failures
- Enforces PMP exceptions correctly
- Fixes some Coverity issues
# gpg: Signature made Sun 17 Jan 2021 21:53:19 GMT
# gpg: using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full]
# Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054
* remotes/alistair/tags/pull-riscv-to-apply-20210117-3:
riscv: Pass RISCVHartArrayState by pointer
target/riscv: Remove built-in GDB XML files for CSRs
target/riscv: Generate the GDB XML file for CSR registers dynamically
target/riscv: Add CSR name in the CSR function table
target/riscv: Make csr_ops[CSR_TABLE_SIZE] external
hw/misc/sifive_u_otp: handling the fails of blk_pread and blk_pwrite
hw/riscv: sifive_u: Use SIFIVE_U_CPU for mc->default_cpu_type
target/riscv/pmp: Raise exception if no PMP entry is configured
RISC-V: Place DTB at 3GB boundary instead of 4GB
gdb: riscv: Add target description
hw/block: m25p80: Implement AAI-WP command support for SST flashes
hw/block: m25p80: Don't write to flash if write is disabled
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/block/m25p80.c | 74 | ||||
-rw-r--r-- | hw/misc/sifive_u_otp.c | 31 | ||||
-rw-r--r-- | hw/riscv/boot.c | 18 | ||||
-rw-r--r-- | hw/riscv/sifive_u.c | 16 | ||||
-rw-r--r-- | hw/riscv/spike.c | 8 | ||||
-rw-r--r-- | hw/riscv/virt.c | 8 |
6 files changed, 119 insertions, 36 deletions
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 1b3f240..b744a58 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -360,6 +360,7 @@ typedef enum { QPP_4 = 0x34, RDID_90 = 0x90, RDID_AB = 0xab, + AAI_WP = 0xad, ERASE_4K = 0x20, ERASE4_4K = 0x21, @@ -456,6 +457,7 @@ struct Flash { bool four_bytes_address_mode; bool reset_enable; bool quad_enable; + bool aai_enable; uint8_t ear; int64_t dirty_page; @@ -601,6 +603,7 @@ void flash_write8(Flash *s, uint32_t addr, uint8_t data) if (!s->write_enable) { qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\n"); + return; } if ((prev ^ data) & data) { @@ -670,6 +673,11 @@ static void complete_collecting_data(Flash *s) case PP4_4: s->state = STATE_PAGE_PROGRAM; break; + case AAI_WP: + /* AAI programming starts from the even address */ + s->cur_addr &= ~BIT(0); + s->state = STATE_PAGE_PROGRAM; + break; case READ: case READ4: case FAST_READ: @@ -768,6 +776,7 @@ static void reset_memory(Flash *s) s->write_enable = false; s->reset_enable = false; s->quad_enable = false; + s->aai_enable = false; switch (get_man(s)) { case MAN_NUMONYX: @@ -973,6 +982,11 @@ static void decode_qio_read_cmd(Flash *s) s->state = STATE_COLLECTING_DATA; } +static bool is_valid_aai_cmd(uint32_t cmd) +{ + return cmd == AAI_WP || cmd == WRDI || cmd == RDSR; +} + static void decode_new_cmd(Flash *s, uint32_t value) { int i; @@ -984,6 +998,11 @@ static void decode_new_cmd(Flash *s, uint32_t value) s->reset_enable = false; } + if (get_man(s) == MAN_SST && s->aai_enable && !is_valid_aai_cmd(value)) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: Invalid cmd within AAI programming sequence"); + } + switch (value) { case ERASE_4K: @@ -1103,6 +1122,9 @@ static void decode_new_cmd(Flash *s, uint32_t value) case WRDI: s->write_enable = false; + if (get_man(s) == MAN_SST) { + s->aai_enable = false; + } break; case WREN: s->write_enable = true; @@ -1113,6 +1135,10 @@ static void decode_new_cmd(Flash *s, uint32_t value) if (get_man(s) == MAN_MACRONIX) { s->data[0] |= (!!s->quad_enable) << 6; } + if (get_man(s) == MAN_SST) { + s->data[0] |= (!!s->aai_enable) << 6; + } + s->pos = 0; s->len = 1; s->data_read_loop = true; @@ -1260,6 +1286,24 @@ static void decode_new_cmd(Flash *s, uint32_t value) case RSTQIO: s->quad_enable = false; break; + case AAI_WP: + if (get_man(s) == MAN_SST) { + if (s->write_enable) { + if (s->aai_enable) { + s->state = STATE_PAGE_PROGRAM; + } else { + s->aai_enable = true; + s->needed_bytes = get_addr_length(s); + s->state = STATE_COLLECTING_DATA; + } + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: AAI_WP with write protect\n"); + } + } else { + qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value); + } + break; default: s->pos = 0; s->len = 1; @@ -1305,6 +1349,17 @@ static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx) trace_m25p80_page_program(s, s->cur_addr, (uint8_t)tx); flash_write8(s, s->cur_addr, (uint8_t)tx); s->cur_addr = (s->cur_addr + 1) & (s->size - 1); + + if (get_man(s) == MAN_SST && s->aai_enable && s->cur_addr == 0) { + /* + * There is no wrap mode during AAI programming once the highest + * unprotected memory address is reached. The Write-Enable-Latch + * bit is automatically reset, and AAI programming mode aborts. + */ + s->write_enable = false; + s->aai_enable = false; + } + break; case STATE_READ: @@ -1450,6 +1505,24 @@ static const VMStateDescription vmstate_m25p80_data_read_loop = { } }; +static bool m25p80_aai_enable_needed(void *opaque) +{ + Flash *s = (Flash *)opaque; + + return s->aai_enable; +} + +static const VMStateDescription vmstate_m25p80_aai_enable = { + .name = "m25p80/aai_enable", + .version_id = 1, + .minimum_version_id = 1, + .needed = m25p80_aai_enable_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(aai_enable, Flash), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_m25p80 = { .name = "m25p80", .version_id = 0, @@ -1480,6 +1553,7 @@ static const VMStateDescription vmstate_m25p80 = { }, .subsections = (const VMStateDescription * []) { &vmstate_m25p80_data_read_loop, + &vmstate_m25p80_aai_enable, NULL } }; diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c index 4401787..f921c67 100644 --- a/hw/misc/sifive_u_otp.c +++ b/hw/misc/sifive_u_otp.c @@ -63,8 +63,13 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) if (s->blk) { int32_t buf; - blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, - SIFIVE_U_OTP_FUSE_WORD); + if (blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, + SIFIVE_U_OTP_FUSE_WORD) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "read error index<%d>\n", s->pa); + return 0xff; + } + return buf; } @@ -161,8 +166,12 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr, /* write to backend */ if (s->blk) { - blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, - &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, 0); + if (blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, + &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD, + 0) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "write error index<%d>\n", s->pa); + } } /* update written bit */ @@ -249,12 +258,18 @@ static void sifive_u_otp_reset(DeviceState *dev) int index = SIFIVE_U_OTP_SERIAL_ADDR; serial_data = s->serial; - blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, - &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); + if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, + &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "write error index<%d>\n", index); + } serial_data = ~(s->serial); - blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, - &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0); + if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, + &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "write error index<%d>\n", index + 1); + } } /* Initialize write-once map */ diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 83586ae..0d38bb7 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -33,14 +33,12 @@ #include <libfdt.h> -bool riscv_is_32bit(RISCVHartArrayState harts) +bool riscv_is_32bit(RISCVHartArrayState *harts) { - RISCVCPU hart = harts.harts[0]; - - return riscv_cpu_is_32bit(&hart.env); + return riscv_cpu_is_32bit(&harts->harts[0].env); } -target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState harts, +target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts, target_ulong firmware_end_addr) { if (riscv_is_32bit(harts)) { return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB); @@ -194,11 +192,11 @@ uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt) /* * We should put fdt as far as possible to avoid kernel/initrd overwriting * its content. But it should be addressable by 32 bit system as well. - * Thus, put it at an aligned address that less than fdt size from end of - * dram or 4GB whichever is lesser. + * Thus, put it at an 16MB aligned address that less than fdt size from the + * end of dram or 3GB whichever is lesser. */ - temp = MIN(dram_end, 4096 * MiB); - fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB); + temp = MIN(dram_end, 3072 * MiB); + fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 16 * MiB); fdt_pack(fdt); /* copy in the device tree */ @@ -247,7 +245,7 @@ void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base, &address_space_memory); } -void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState harts, +void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts, hwaddr start_addr, hwaddr rom_base, hwaddr rom_size, uint64_t kernel_entry, diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index f5c400d..59b61ce 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -466,7 +466,7 @@ static void sifive_u_machine_init(MachineState *machine) /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, - riscv_is_32bit(s->soc.u_cpus)); + riscv_is_32bit(&s->soc.u_cpus)); if (s->start_in_flash) { /* @@ -495,7 +495,7 @@ static void sifive_u_machine_init(MachineState *machine) break; } - if (riscv_is_32bit(s->soc.u_cpus)) { + if (riscv_is_32bit(&s->soc.u_cpus)) { firmware_end_addr = riscv_find_and_load_firmware(machine, "opensbi-riscv32-generic-fw_dynamic.bin", start_addr, NULL); @@ -506,7 +506,7 @@ static void sifive_u_machine_init(MachineState *machine) } if (machine->kernel_filename) { - kernel_start_addr = riscv_calc_kernel_start_addr(s->soc.u_cpus, + kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, firmware_end_addr); kernel_entry = riscv_load_kernel(machine->kernel_filename, @@ -533,7 +533,7 @@ static void sifive_u_machine_init(MachineState *machine) /* Compute the fdt load address in dram */ fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DEV_DRAM].base, machine->ram_size, s->fdt); - if (!riscv_is_32bit(s->soc.u_cpus)) { + if (!riscv_is_32bit(&s->soc.u_cpus)) { start_addr_hi32 = (uint64_t)start_addr >> 32; } @@ -552,7 +552,7 @@ static void sifive_u_machine_init(MachineState *machine) 0x00000000, /* fw_dyn: */ }; - if (riscv_is_32bit(s->soc.u_cpus)) { + if (riscv_is_32bit(&s->soc.u_cpus)) { reset_vec[4] = 0x0202a583; /* lw a1, 32(t0) */ reset_vec[5] = 0x0182a283; /* lw t0, 24(t0) */ } else { @@ -628,11 +628,7 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data) mc->init = sifive_u_machine_init; mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT; mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; -#if defined(TARGET_RISCV32) - mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U34; -#elif defined(TARGET_RISCV64) - mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U54; -#endif + mc->default_cpu_type = SIFIVE_U_CPU; mc->default_cpus = mc->min_cpus; object_class_property_add_bool(oc, "start-in-flash", diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index e723ca0..56986ec 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -244,7 +244,7 @@ static void spike_board_init(MachineState *machine) /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, - riscv_is_32bit(s->soc[0])); + riscv_is_32bit(&s->soc[0])); /* boot rom */ memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom", @@ -257,7 +257,7 @@ static void spike_board_init(MachineState *machine) * keeping ELF files here was intentional because BIN files don't work * for the Spike machine as HTIF emulation depends on ELF parsing. */ - if (riscv_is_32bit(s->soc[0])) { + if (riscv_is_32bit(&s->soc[0])) { firmware_end_addr = riscv_find_and_load_firmware(machine, "opensbi-riscv32-generic-fw_dynamic.elf", memmap[SPIKE_DRAM].base, @@ -270,7 +270,7 @@ static void spike_board_init(MachineState *machine) } if (machine->kernel_filename) { - kernel_start_addr = riscv_calc_kernel_start_addr(s->soc[0], + kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], firmware_end_addr); kernel_entry = riscv_load_kernel(machine->kernel_filename, @@ -299,7 +299,7 @@ static void spike_board_init(MachineState *machine) fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base, machine->ram_size, s->fdt); /* load the reset vector */ - riscv_setup_rom_reset_vec(machine, s->soc[0], memmap[SPIKE_DRAM].base, + riscv_setup_rom_reset_vec(machine, &s->soc[0], memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base, memmap[SPIKE_MROM].size, kernel_entry, fdt_load_addr, s->fdt); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 8de4c35..2299b3a 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -601,7 +601,7 @@ static void virt_machine_init(MachineState *machine) /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, - riscv_is_32bit(s->soc[0])); + riscv_is_32bit(&s->soc[0])); /* boot rom */ memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom", @@ -609,7 +609,7 @@ static void virt_machine_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base, mask_rom); - if (riscv_is_32bit(s->soc[0])) { + if (riscv_is_32bit(&s->soc[0])) { firmware_end_addr = riscv_find_and_load_firmware(machine, "opensbi-riscv32-generic-fw_dynamic.bin", start_addr, NULL); @@ -620,7 +620,7 @@ static void virt_machine_init(MachineState *machine) } if (machine->kernel_filename) { - kernel_start_addr = riscv_calc_kernel_start_addr(s->soc[0], + kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], firmware_end_addr); kernel_entry = riscv_load_kernel(machine->kernel_filename, @@ -656,7 +656,7 @@ static void virt_machine_init(MachineState *machine) fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base, machine->ram_size, s->fdt); /* load the reset vector */ - riscv_setup_rom_reset_vec(machine, s->soc[0], start_addr, + riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, virt_memmap[VIRT_MROM].base, virt_memmap[VIRT_MROM].size, kernel_entry, fdt_load_addr, s->fdt); |