aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-01-18 10:28:26 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-01-18 10:28:26 +0000
commit20b8016ed847ac751e508c38aa27a9f8ecb93ac8 (patch)
tree1205e1aa81e75d1b5d232a27b565878814913417 /hw
parente0cbcf1eea16e81f116560130a1b36da711fb102 (diff)
parenta8259b53230782f5e0a0d66013655c4ed5d71b7e (diff)
downloadqemu-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.c74
-rw-r--r--hw/misc/sifive_u_otp.c31
-rw-r--r--hw/riscv/boot.c18
-rw-r--r--hw/riscv/sifive_u.c16
-rw-r--r--hw/riscv/spike.c8
-rw-r--r--hw/riscv/virt.c8
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);