Unverified Commit 5aec3247 authored by Michael Clark's avatar Michael Clark
Browse files

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: default avatarMichael Clark <mjc@sifive.com>
Reviewed-by: default avatarAlistair Francis <Alistair.Francis@wdc.com>
parent b8643bd6
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -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);
+28 −23
Original line number Diff line number Diff line
@@ -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,
+41 −28
Original line number Diff line number Diff line
@@ -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,
+24 −19
Original line number Diff line number Diff line
@@ -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;