RISC-V: Mark ROM read-only after copying in code

The sifive_u machine already marks its ROM readonly however
it has the wrong base address for its mask ROM. This patch
fixes the sifive_u mask ROM base address.

This commit makes all other boards consistently use mask_rom
as the variable name for their ROMs. Boards that use device
tree now check that that the device tree fits in the assigned
ROM space using the new qemu_fdt_totalsize(void *fdt)
interface, adding a bounds check and error message. This
can detect truncation.

Cc: Sagar Karandikar <sagark@eecs.berkeley.edu>
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Alistair Francis <Alistair.Francis@wdc.com>
Signed-off-by: Michael Clark <mjc@sifive.com>
Reviewed-by: Alistair Francis <Alistair.Francis@wdc.com>
This commit is contained in:
Michael Clark 2018-03-04 11:52:13 +13:00
parent b8643bd608
commit 5aec3247c1
No known key found for this signature in database
GPG Key ID: 6BF1D7B357EF3E4F
4 changed files with 101 additions and 82 deletions

View File

@ -74,14 +74,6 @@ static const struct MemmapEntry {
[SIFIVE_E_DTIM] = { 0x80000000, 0x4000 }
};
static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
{
int i;
for (i = 0; i < (len >> 2); i++) {
stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
}
}
static uint64_t load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
@ -112,6 +104,7 @@ static void riscv_sifive_e_init(MachineState *machine)
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
int i;
/* Initialize SOC */
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@ -131,7 +124,7 @@ static void riscv_sifive_e_init(MachineState *machine)
memmap[SIFIVE_E_DTIM].base, main_mem);
/* Mask ROM */
memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom",
memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
memmap[SIFIVE_E_MROM].size, &error_fatal);
memory_region_add_subregion(sys_mem,
memmap[SIFIVE_E_MROM].base, mask_rom);
@ -185,9 +178,12 @@ static void riscv_sifive_e_init(MachineState *machine)
0x00028067, /* 0x1004: jr t0 */
};
/* copy in the reset vector */
copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec, sizeof(reset_vec));
memory_region_set_readonly(mask_rom, true);
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
reset_vec[i] = cpu_to_le32(reset_vec[i]);
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[SIFIVE_E_MROM].base, &address_space_memory);
if (machine->kernel_filename) {
load_kernel(machine->kernel_filename);

View File

@ -47,12 +47,14 @@
#include "exec/address-spaces.h"
#include "elf.h"
#include <libfdt.h>
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
} sifive_u_memmap[] = {
[SIFIVE_U_DEBUG] = { 0x0, 0x100 },
[SIFIVE_U_MROM] = { 0x1000, 0x2000 },
[SIFIVE_U_MROM] = { 0x1000, 0x11000 },
[SIFIVE_U_CLINT] = { 0x2000000, 0x10000 },
[SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 },
[SIFIVE_U_UART0] = { 0x10013000, 0x1000 },
@ -60,14 +62,6 @@ static const struct MemmapEntry {
[SIFIVE_U_DRAM] = { 0x80000000, 0x0 },
};
static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
{
int i;
for (i = 0; i < (len >> 2); i++) {
stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
}
}
static uint64_t load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
@ -221,9 +215,10 @@ static void riscv_sifive_u_init(MachineState *machine)
const struct MemmapEntry *memmap = sifive_u_memmap;
SiFiveUState *s = g_new0(SiFiveUState, 1);
MemoryRegion *sys_memory = get_system_memory();
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
int i;
/* Initialize SOC */
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@ -239,17 +234,17 @@ static void riscv_sifive_u_init(MachineState *machine)
/* register RAM */
memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
machine->ram_size, &error_fatal);
memory_region_add_subregion(sys_memory, memmap[SIFIVE_U_DRAM].base,
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base,
main_mem);
/* create device tree */
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
/* boot rom */
memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom",
memmap[SIFIVE_U_MROM].base, &error_fatal);
memory_region_set_readonly(boot_rom, true);
memory_region_add_subregion(sys_memory, 0x0, boot_rom);
memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
memmap[SIFIVE_U_MROM].size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
mask_rom);
if (machine->kernel_filename) {
load_kernel(machine->kernel_filename);
@ -272,13 +267,23 @@ static void riscv_sifive_u_init(MachineState *machine)
/* dtb: */
};
/* copy in the reset vector */
copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec, sizeof(reset_vec));
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
reset_vec[i] = cpu_to_le32(reset_vec[i]);
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[SIFIVE_U_MROM].base, &address_space_memory);
/* copy in the device tree */
qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base +
sizeof(reset_vec), s->fdt, s->fdt_size);
if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
error_report("not enough space to store device-tree");
exit(1);
}
qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
&address_space_memory);
/* MMIO */
s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
@ -292,9 +297,9 @@ static void riscv_sifive_u_init(MachineState *machine)
SIFIVE_U_PLIC_CONTEXT_BASE,
SIFIVE_U_PLIC_CONTEXT_STRIDE,
memmap[SIFIVE_U_PLIC].size);
sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base,
sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
/* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base,
/* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]); */
sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
memmap[SIFIVE_U_CLINT].size, smp_cpus,

View File

@ -42,23 +42,17 @@
#include "exec/address-spaces.h"
#include "elf.h"
#include <libfdt.h>
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
} spike_memmap[] = {
[SPIKE_MROM] = { 0x1000, 0x2000 },
[SPIKE_MROM] = { 0x1000, 0x11000 },
[SPIKE_CLINT] = { 0x2000000, 0x10000 },
[SPIKE_DRAM] = { 0x80000000, 0x0 },
};
static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
{
int i;
for (i = 0; i < (len >> 2); i++) {
stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
}
}
static uint64_t load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
@ -173,7 +167,8 @@ static void spike_v1_10_0_board_init(MachineState *machine)
SpikeState *s = g_new0(SpikeState, 1);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
int i;
/* Initialize SOC */
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@ -196,9 +191,10 @@ static void spike_v1_10_0_board_init(MachineState *machine)
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
/* boot rom */
memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
s->fdt_size + 0x2000, &error_fatal);
memory_region_add_subregion(system_memory, 0x0, boot_rom);
memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
memmap[SPIKE_MROM].size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
if (machine->kernel_filename) {
load_kernel(machine->kernel_filename);
@ -221,16 +217,26 @@ static void spike_v1_10_0_board_init(MachineState *machine)
/* dtb: */
};
/* copy in the reset vector */
copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec));
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
reset_vec[i] = cpu_to_le32(reset_vec[i]);
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[SPIKE_MROM].base, &address_space_memory);
/* copy in the device tree */
qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec),
s->fdt, s->fdt_size);
if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
memmap[SPIKE_MROM].size - sizeof(reset_vec)) {
error_report("not enough space to store device-tree");
exit(1);
}
qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
memmap[SPIKE_MROM].base + sizeof(reset_vec),
&address_space_memory);
/* initialize HTIF using symbols found in load_kernel */
htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hd(0));
htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0));
/* Core Local Interruptor (timer and IPI) */
sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
@ -244,7 +250,8 @@ static void spike_v1_09_1_board_init(MachineState *machine)
SpikeState *s = g_new0(SpikeState, 1);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
int i;
/* Initialize SOC */
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
@ -264,9 +271,10 @@ static void spike_v1_09_1_board_init(MachineState *machine)
main_mem);
/* boot rom */
memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
0x40000, &error_fatal);
memory_region_add_subregion(system_memory, 0x0, boot_rom);
memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
memmap[SPIKE_MROM].size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
if (machine->kernel_filename) {
load_kernel(machine->kernel_filename);
@ -319,15 +327,20 @@ static void spike_v1_09_1_board_init(MachineState *machine)
g_free(isa);
size_t config_string_len = strlen(config_string);
/* copy in the reset vector */
copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec));
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
reset_vec[i] = cpu_to_le32(reset_vec[i]);
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[SPIKE_MROM].base, &address_space_memory);
/* copy in the config string */
cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec),
config_string, config_string_len);
rom_add_blob_fixed_as("mrom.reset", config_string, config_string_len,
memmap[SPIKE_MROM].base + sizeof(reset_vec),
&address_space_memory);
/* initialize HTIF using symbols found in load_kernel */
htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hd(0));
htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0));
/* Core Local Interruptor (timer and IPI) */
sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,

View File

@ -40,13 +40,15 @@
#include "exec/address-spaces.h"
#include "elf.h"
#include <libfdt.h>
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
} virt_memmap[] = {
[VIRT_DEBUG] = { 0x0, 0x100 },
[VIRT_MROM] = { 0x1000, 0x2000 },
[VIRT_TEST] = { 0x4000, 0x1000 },
[VIRT_MROM] = { 0x1000, 0x11000 },
[VIRT_TEST] = { 0x100000, 0x1000 },
[VIRT_CLINT] = { 0x2000000, 0x10000 },
[VIRT_PLIC] = { 0xc000000, 0x4000000 },
[VIRT_UART0] = { 0x10000000, 0x100 },
@ -54,14 +56,6 @@ static const struct MemmapEntry {
[VIRT_DRAM] = { 0x80000000, 0x0 },
};
static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
{
int i;
for (i = 0; i < (len >> 2); i++) {
stl_phys(&address_space_memory, pa + (i << 2), rom[i]);
}
}
static uint64_t load_kernel(const char *kernel_filename)
{
uint64_t kernel_entry, kernel_high;
@ -272,7 +266,7 @@ static void riscv_virt_board_init(MachineState *machine)
RISCVVirtState *s = g_new0(RISCVVirtState, 1);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
char *plic_hart_config;
size_t plic_hart_config_len;
int i;
@ -299,9 +293,10 @@ static void riscv_virt_board_init(MachineState *machine)
fdt = create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
/* boot rom */
memory_region_init_ram(boot_rom, NULL, "riscv_virt_board.bootrom",
s->fdt_size + 0x2000, &error_fatal);
memory_region_add_subregion(system_memory, 0x0, boot_rom);
memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
memmap[VIRT_MROM].size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
if (machine->kernel_filename) {
uint64_t kernel_entry = load_kernel(machine->kernel_filename);
@ -335,13 +330,23 @@ static void riscv_virt_board_init(MachineState *machine)
/* dtb: */
};
/* copy in the reset vector */
copy_le32_to_phys(memmap[VIRT_MROM].base, reset_vec, sizeof(reset_vec));
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
reset_vec[i] = cpu_to_le32(reset_vec[i]);
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[VIRT_MROM].base, &address_space_memory);
/* copy in the device tree */
qemu_fdt_dumpdtb(s->fdt, s->fdt_size);
cpu_physical_memory_write(memmap[VIRT_MROM].base + sizeof(reset_vec),
s->fdt, s->fdt_size);
if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
memmap[VIRT_MROM].size - sizeof(reset_vec)) {
error_report("not enough space to store device-tree");
exit(1);
}
qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
memmap[VIRT_MROM].base + sizeof(reset_vec),
&address_space_memory);
/* create PLIC hart topology configuration string */
plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * smp_cpus;