Commit aeb07b5f authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20200713' into staging



This is a colection of bug fixes and small imrprovements for RISC-V.

This includes some vector extensions fixes, a PMP bug fix, OpenTitan
UART bug fix and support for OpenSBI dynamic firmware.

# gpg: Signature made Tue 14 Jul 2020 01:29:44 BST
# 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-20200713:
  target/riscv: Fix pmp NA4 implementation
  tcg/riscv: Remove superfluous breaks
  hw/char: Convert the Ibex UART to use the registerfields API
  hw/char: Convert the Ibex UART to use the qdev Clock model
  target/riscv: fix vill bit index in vtype register
  target/riscv: fix return value of do_opivx_widen()
  target/riscv: correct the gvec IR called in gen_vec_rsub16_i64()
  target/riscv: fix rsub gvec tcg_assert_listed_vecop assertion
  hw/riscv: Modify MROM size to end at 0x10000
  RISC-V: Support 64 bit start address
  riscv: Add opensbi firmware dynamic support
  RISC-V: Copy the fdt in dram instead of ROM
  riscv: Unify Qemu's reset vector code path
  hw/riscv: virt: Sort the SoC memmap table entries
  MAINTAINERS: Add an entry for OpenSBI firmware

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents beff47a2 cfad709b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2681,6 +2681,13 @@ F: hw/i386/intel_iommu.c
F: hw/i386/intel_iommu_internal.h
F: include/hw/i386/intel_iommu.h

OpenSBI Firmware
M: Bin Meng <bmeng.cn@gmail.com>
S: Supported
F: pc-bios/opensbi-*
F: .gitlab-ci.d/opensbi.yml
F: .gitlab-ci.d/opensbi/

Usermode Emulation
------------------
Overall usermode emulation
+91 −67
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "qemu/osdep.h"
#include "hw/char/ibex_uart.h"
#include "hw/irq.h"
#include "hw/qdev-clock.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "qemu/log.h"
@@ -35,25 +36,25 @@

static void ibex_uart_update_irqs(IbexUartState *s)
{
    if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_TX_WATERMARK) {
    if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_WATERMARK_MASK) {
        qemu_set_irq(s->tx_watermark, 1);
    } else {
        qemu_set_irq(s->tx_watermark, 0);
    }

    if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_RX_WATERMARK) {
    if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_RX_WATERMARK_MASK) {
        qemu_set_irq(s->rx_watermark, 1);
    } else {
        qemu_set_irq(s->rx_watermark, 0);
    }

    if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_TX_EMPTY) {
    if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_EMPTY_MASK) {
        qemu_set_irq(s->tx_empty, 1);
    } else {
        qemu_set_irq(s->tx_empty, 0);
    }

    if (s->uart_intr_state & s->uart_intr_enable & INTR_STATE_RX_OVERFLOW) {
    if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_RX_OVERFLOW_MASK) {
        qemu_set_irq(s->rx_overflow, 1);
    } else {
        qemu_set_irq(s->rx_overflow, 0);
@@ -64,7 +65,7 @@ static int ibex_uart_can_receive(void *opaque)
{
    IbexUartState *s = opaque;

    if (s->uart_ctrl & UART_CTRL_RX_ENABLE) {
    if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
        return 1;
    }

@@ -74,16 +75,16 @@ static int ibex_uart_can_receive(void *opaque)
static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
{
    IbexUartState *s = opaque;
    uint8_t rx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_RXILVL)
                            >> FIFO_CTRL_RXILVL_SHIFT;
    uint8_t rx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_RXILVL_MASK)
                            >> R_FIFO_CTRL_RXILVL_SHIFT;

    s->uart_rdata = *buf;

    s->uart_status &= ~UART_STATUS_RXIDLE;
    s->uart_status &= ~UART_STATUS_RXEMPTY;
    s->uart_status &= ~R_STATUS_RXIDLE_MASK;
    s->uart_status &= ~R_STATUS_RXEMPTY_MASK;

    if (size > rx_fifo_level) {
        s->uart_intr_state |= INTR_STATE_RX_WATERMARK;
        s->uart_intr_state |= R_INTR_STATE_RX_WATERMARK_MASK;
    }

    ibex_uart_update_irqs(s);
@@ -93,8 +94,8 @@ static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
                               void *opaque)
{
    IbexUartState *s = opaque;
    uint8_t tx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_TXILVL)
                            >> FIFO_CTRL_TXILVL_SHIFT;
    uint8_t tx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_TXILVL_MASK)
                            >> R_FIFO_CTRL_TXILVL_SHIFT;
    int ret;

    /* instant drain the fifo when there's no back-end */
@@ -104,10 +105,10 @@ static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
    }

    if (!s->tx_level) {
        s->uart_status &= ~UART_STATUS_TXFULL;
        s->uart_status |= UART_STATUS_TXEMPTY;
        s->uart_intr_state |= INTR_STATE_TX_EMPTY;
        s->uart_intr_state &= ~INTR_STATE_TX_WATERMARK;
        s->uart_status &= ~R_STATUS_TXFULL_MASK;
        s->uart_status |= R_STATUS_TXEMPTY_MASK;
        s->uart_intr_state |= R_INTR_STATE_TX_EMPTY_MASK;
        s->uart_intr_state &= ~R_INTR_STATE_TX_WATERMARK_MASK;
        ibex_uart_update_irqs(s);
        return FALSE;
    }
@@ -130,18 +131,18 @@ static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,

    /* Clear the TX Full bit */
    if (s->tx_level != IBEX_UART_TX_FIFO_SIZE) {
        s->uart_status &= ~UART_STATUS_TXFULL;
        s->uart_status &= ~R_STATUS_TXFULL_MASK;
    }

    /* Disable the TX_WATERMARK IRQ */
    if (s->tx_level < tx_fifo_level) {
        s->uart_intr_state &= ~INTR_STATE_TX_WATERMARK;
        s->uart_intr_state &= ~R_INTR_STATE_TX_WATERMARK_MASK;
    }

    /* Set TX empty */
    if (s->tx_level == 0) {
        s->uart_status |= UART_STATUS_TXEMPTY;
        s->uart_intr_state |= INTR_STATE_TX_EMPTY;
        s->uart_status |= R_STATUS_TXEMPTY_MASK;
        s->uart_intr_state |= R_INTR_STATE_TX_EMPTY_MASK;
    }

    ibex_uart_update_irqs(s);
@@ -152,8 +153,8 @@ static void uart_write_tx_fifo(IbexUartState *s, const uint8_t *buf,
                               int size)
{
    uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    uint8_t tx_fifo_level = (s->uart_fifo_ctrl & FIFO_CTRL_TXILVL)
                            >> FIFO_CTRL_TXILVL_SHIFT;
    uint8_t tx_fifo_level = (s->uart_fifo_ctrl & R_FIFO_CTRL_TXILVL_MASK)
                            >> R_FIFO_CTRL_TXILVL_SHIFT;

    if (size > IBEX_UART_TX_FIFO_SIZE - s->tx_level) {
        size = IBEX_UART_TX_FIFO_SIZE - s->tx_level;
@@ -164,16 +165,16 @@ static void uart_write_tx_fifo(IbexUartState *s, const uint8_t *buf,
    s->tx_level += size;

    if (s->tx_level > 0) {
        s->uart_status &= ~UART_STATUS_TXEMPTY;
        s->uart_status &= ~R_STATUS_TXEMPTY_MASK;
    }

    if (s->tx_level >= tx_fifo_level) {
        s->uart_intr_state |= INTR_STATE_TX_WATERMARK;
        s->uart_intr_state |= R_INTR_STATE_TX_WATERMARK_MASK;
        ibex_uart_update_irqs(s);
    }

    if (s->tx_level == IBEX_UART_TX_FIFO_SIZE) {
        s->uart_status |= UART_STATUS_TXFULL;
        s->uart_status |= R_STATUS_TXFULL_MASK;
    }

    timer_mod(s->fifo_trigger_handle, current_time +
@@ -203,49 +204,60 @@ static void ibex_uart_reset(DeviceState *dev)
    ibex_uart_update_irqs(s);
}

static uint64_t ibex_uart_get_baud(IbexUartState *s)
{
    uint64_t baud;

    baud = ((s->uart_ctrl & R_CTRL_NCO_MASK) >> 16);
    baud *= clock_get_hz(s->f_clk);
    baud >>= 20;

    return baud;
}

static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
                                       unsigned int size)
{
    IbexUartState *s = opaque;
    uint64_t retvalue = 0;

    switch (addr) {
    case IBEX_UART_INTR_STATE:
    switch (addr >> 2) {
    case R_INTR_STATE:
        retvalue = s->uart_intr_state;
        break;
    case IBEX_UART_INTR_ENABLE:
    case R_INTR_ENABLE:
        retvalue = s->uart_intr_enable;
        break;
    case IBEX_UART_INTR_TEST:
    case R_INTR_TEST:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: wdata is write only\n", __func__);
        break;

    case IBEX_UART_CTRL:
    case R_CTRL:
        retvalue = s->uart_ctrl;
        break;
    case IBEX_UART_STATUS:
    case R_STATUS:
        retvalue = s->uart_status;
        break;

    case IBEX_UART_RDATA:
    case R_RDATA:
        retvalue = s->uart_rdata;
        if (s->uart_ctrl & UART_CTRL_RX_ENABLE) {
        if (s->uart_ctrl & R_CTRL_RX_ENABLE_MASK) {
            qemu_chr_fe_accept_input(&s->chr);

            s->uart_status |= UART_STATUS_RXIDLE;
            s->uart_status |= UART_STATUS_RXEMPTY;
            s->uart_status |= R_STATUS_RXIDLE_MASK;
            s->uart_status |= R_STATUS_RXEMPTY_MASK;
        }
        break;
    case IBEX_UART_WDATA:
    case R_WDATA:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: wdata is write only\n", __func__);
        break;

    case IBEX_UART_FIFO_CTRL:
    case R_FIFO_CTRL:
        retvalue = s->uart_fifo_ctrl;
        break;
    case IBEX_UART_FIFO_STATUS:
    case R_FIFO_STATUS:
        retvalue = s->uart_fifo_status;

        retvalue |= s->tx_level & 0x1F;
@@ -254,17 +266,17 @@ static uint64_t ibex_uart_read(void *opaque, hwaddr addr,
                      "%s: RX fifos are not supported\n", __func__);
        break;

    case IBEX_UART_OVRD:
    case R_OVRD:
        retvalue = s->uart_ovrd;
        qemu_log_mask(LOG_UNIMP,
                      "%s: ovrd is not supported\n", __func__);
        break;
    case IBEX_UART_VAL:
    case R_VAL:
        retvalue = s->uart_val;
        qemu_log_mask(LOG_UNIMP,
                      "%s: val is not supported\n", __func__);
        break;
    case IBEX_UART_TIMEOUT_CTRL:
    case R_TIMEOUT_CTRL:
        retvalue = s->uart_timeout_ctrl;
        qemu_log_mask(LOG_UNIMP,
                      "%s: timeout_ctrl is not supported\n", __func__);
@@ -284,97 +296,95 @@ static void ibex_uart_write(void *opaque, hwaddr addr,
    IbexUartState *s = opaque;
    uint32_t value = val64;

    switch (addr) {
    case IBEX_UART_INTR_STATE:
    switch (addr >> 2) {
    case R_INTR_STATE:
        /* Write 1 clear */
        s->uart_intr_state &= ~value;
        ibex_uart_update_irqs(s);
        break;
    case IBEX_UART_INTR_ENABLE:
    case R_INTR_ENABLE:
        s->uart_intr_enable = value;
        ibex_uart_update_irqs(s);
        break;
    case IBEX_UART_INTR_TEST:
    case R_INTR_TEST:
        s->uart_intr_state |= value;
        ibex_uart_update_irqs(s);
        break;

    case IBEX_UART_CTRL:
    case R_CTRL:
        s->uart_ctrl = value;

        if (value & UART_CTRL_NF) {
        if (value & R_CTRL_NF_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: UART_CTRL_NF is not supported\n", __func__);
        }
        if (value & UART_CTRL_SLPBK) {
        if (value & R_CTRL_SLPBK_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: UART_CTRL_SLPBK is not supported\n", __func__);
        }
        if (value & UART_CTRL_LLPBK) {
        if (value & R_CTRL_LLPBK_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: UART_CTRL_LLPBK is not supported\n", __func__);
        }
        if (value & UART_CTRL_PARITY_EN) {
        if (value & R_CTRL_PARITY_EN_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: UART_CTRL_PARITY_EN is not supported\n",
                          __func__);
        }
        if (value & UART_CTRL_PARITY_ODD) {
        if (value & R_CTRL_PARITY_ODD_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: UART_CTRL_PARITY_ODD is not supported\n",
                          __func__);
        }
        if (value & UART_CTRL_RXBLVL) {
        if (value & R_CTRL_RXBLVL_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: UART_CTRL_RXBLVL is not supported\n", __func__);
        }
        if (value & UART_CTRL_NCO) {
            uint64_t baud = ((value & UART_CTRL_NCO) >> 16);
            baud *= 1000;
            baud >>= 20;
        if (value & R_CTRL_NCO_MASK) {
            uint64_t baud = ibex_uart_get_baud(s);

            s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10;
        }
        break;
    case IBEX_UART_STATUS:
    case R_STATUS:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: status is read only\n", __func__);
        break;

    case IBEX_UART_RDATA:
    case R_RDATA:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: rdata is read only\n", __func__);
        break;
    case IBEX_UART_WDATA:
    case R_WDATA:
        uart_write_tx_fifo(s, (uint8_t *) &value, 1);
        break;

    case IBEX_UART_FIFO_CTRL:
    case R_FIFO_CTRL:
        s->uart_fifo_ctrl = value;

        if (value & FIFO_CTRL_RXRST) {
        if (value & R_FIFO_CTRL_RXRST_MASK) {
            qemu_log_mask(LOG_UNIMP,
                          "%s: RX fifos are not supported\n", __func__);
        }
        if (value & FIFO_CTRL_TXRST) {
        if (value & R_FIFO_CTRL_TXRST_MASK) {
            s->tx_level = 0;
        }
        break;
    case IBEX_UART_FIFO_STATUS:
    case R_FIFO_STATUS:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: fifo_status is read only\n", __func__);
        break;

    case IBEX_UART_OVRD:
    case R_OVRD:
        s->uart_ovrd = value;
        qemu_log_mask(LOG_UNIMP,
                      "%s: ovrd is not supported\n", __func__);
        break;
    case IBEX_UART_VAL:
    case R_VAL:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: val is read only\n", __func__);
        break;
    case IBEX_UART_TIMEOUT_CTRL:
    case R_TIMEOUT_CTRL:
        s->uart_timeout_ctrl = value;
        qemu_log_mask(LOG_UNIMP,
                      "%s: timeout_ctrl is not supported\n", __func__);
@@ -385,11 +395,21 @@ static void ibex_uart_write(void *opaque, hwaddr addr,
    }
}

static void ibex_uart_clk_update(void *opaque)
{
    IbexUartState *s = opaque;

    /* recompute uart's speed on clock change */
    uint64_t baud = ibex_uart_get_baud(s);

    s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10;
}

static void fifo_trigger_update(void *opaque)
{
    IbexUartState *s = opaque;

    if (s->uart_ctrl & UART_CTRL_TX_ENABLE) {
    if (s->uart_ctrl & R_CTRL_TX_ENABLE_MASK) {
        ibex_uart_xmit(NULL, G_IO_OUT, s);
    }
}
@@ -444,6 +464,10 @@ static void ibex_uart_init(Object *obj)
{
    IbexUartState *s = IBEX_UART(obj);

    s->f_clk = qdev_init_clock_in(DEVICE(obj), "f_clock",
                                  ibex_uart_clk_update, s);
    clock_set_hz(s->f_clk, IBEX_UART_CLOCK);

    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark);
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rx_watermark);
    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_empty);
+107 −0
Original line number Diff line number Diff line
@@ -25,13 +25,19 @@
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/riscv/boot.h"
#include "hw/riscv/boot_opensbi.h"
#include "elf.h"
#include "sysemu/device_tree.h"
#include "sysemu/qtest.h"

#include <libfdt.h>

#if defined(TARGET_RISCV32)
# define KERNEL_BOOT_ADDRESS 0x80400000
#define fw_dynamic_info_data(__val)     cpu_to_le32(__val)
#else
# define KERNEL_BOOT_ADDRESS 0x80200000
#define fw_dynamic_info_data(__val)     cpu_to_le64(__val)
#endif

void riscv_find_and_load_firmware(MachineState *machine,
@@ -155,3 +161,104 @@ hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,

    return *start + size;
}

uint32_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
{
    uint32_t temp, fdt_addr;
    hwaddr dram_end = dram_base + mem_size;
    int fdtsize = fdt_totalsize(fdt);

    if (fdtsize <= 0) {
        error_report("invalid device-tree");
        exit(1);
    }

    /*
     * 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.
     */
    temp = MIN(dram_end, 4096 * MiB);
    fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);

    fdt_pack(fdt);
    /* copy in the device tree */
    qemu_fdt_dumpdtb(fdt, fdtsize);

    rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr,
                          &address_space_memory);

    return fdt_addr;
}

void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
                              uint32_t reset_vec_size, uint64_t kernel_entry)
{
    struct fw_dynamic_info dinfo;
    size_t dinfo_len;

    dinfo.magic = fw_dynamic_info_data(FW_DYNAMIC_INFO_MAGIC_VALUE);
    dinfo.version = fw_dynamic_info_data(FW_DYNAMIC_INFO_VERSION);
    dinfo.next_mode = fw_dynamic_info_data(FW_DYNAMIC_INFO_NEXT_MODE_S);
    dinfo.next_addr = fw_dynamic_info_data(kernel_entry);
    dinfo.options = 0;
    dinfo.boot_hart = 0;
    dinfo_len = sizeof(dinfo);

    /**
     * copy the dynamic firmware info. This information is specific to
     * OpenSBI but doesn't break any other firmware as long as they don't
     * expect any certain value in "a2" register.
     */
    if (dinfo_len > (rom_size - reset_vec_size)) {
        error_report("not enough space to store dynamic firmware info");
        exit(1);
    }

    rom_add_blob_fixed_as("mrom.finfo", &dinfo, dinfo_len,
                           rom_base + reset_vec_size,
                           &address_space_memory);
}

void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
                               hwaddr rom_size, uint64_t kernel_entry,
                               uint32_t fdt_load_addr, void *fdt)
{
    int i;
    uint32_t start_addr_hi32 = 0x00000000;

    #if defined(TARGET_RISCV64)
    start_addr_hi32 = start_addr >> 32;
    #endif
    /* reset vector */
    uint32_t reset_vec[10] = {
        0x00000297,                  /* 1:  auipc  t0, %pcrel_hi(fw_dyn) */
        0x02828613,                  /*     addi   a2, t0, %pcrel_lo(1b) */
        0xf1402573,                  /*     csrr   a0, mhartid  */
#if defined(TARGET_RISCV32)
        0x0202a583,                  /*     lw     a1, 32(t0) */
        0x0182a283,                  /*     lw     t0, 24(t0) */
#elif defined(TARGET_RISCV64)
        0x0202b583,                  /*     ld     a1, 32(t0) */
        0x0182b283,                  /*     ld     t0, 24(t0) */
#endif
        0x00028067,                  /*     jr     t0 */
        start_addr,                  /* start: .dword */
        start_addr_hi32,
        fdt_load_addr,               /* fdt_laddr: .dword */
        0x00000000,
                                     /* fw_dyn: */
    };

    /* copy in the reset vector in little_endian byte order */
    for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
        reset_vec[i] = cpu_to_le32(reset_vec[i]);
    }
    rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
                          rom_base, &address_space_memory);
    riscv_rom_copy_firmware_info(rom_base, rom_size, sizeof(reset_vec),
                                 kernel_entry);

    return;
}
+32 −21
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@
#include "sysemu/device_tree.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"

#include <libfdt.h>

@@ -71,7 +70,7 @@ static const struct MemmapEntry {
    hwaddr size;
} sifive_u_memmap[] = {
    [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
    [SIFIVE_U_MROM] =     {     0x1000,     0xf000 },
    [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
    [SIFIVE_U_L2LIM] =    {  0x8000000,  0x2000000 },
    [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
@@ -379,7 +378,10 @@ static void sifive_u_machine_init(MachineState *machine)
    MemoryRegion *main_mem = g_new(MemoryRegion, 1);
    MemoryRegion *flash0 = g_new(MemoryRegion, 1);
    target_ulong start_addr = memmap[SIFIVE_U_DRAM].base;
    uint32_t start_addr_hi32 = 0x00000000;
    int i;
    uint32_t fdt_load_addr;
    uint64_t kernel_entry;

    /* Initialize SoC */
    object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
@@ -436,8 +438,7 @@ static void sifive_u_machine_init(MachineState *machine)
    riscv_find_and_load_firmware(machine, BIOS_FILENAME, start_addr, NULL);

    if (machine->kernel_filename) {
        uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
                                                  NULL);
        kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);

        if (machine->initrd_filename) {
            hwaddr start;
@@ -449,42 +450,52 @@ static void sifive_u_machine_init(MachineState *machine)
            qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
                                  end);
        }
    } else {
       /*
        * If dynamic firmware is used, it doesn't know where is the next mode
        * if kernel argument is not set.
        */
        kernel_entry = 0;
    }

    /* Compute the fdt load address in dram */
    fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DRAM].base,
                                   machine->ram_size, s->fdt);
    #if defined(TARGET_RISCV64)
    start_addr_hi32 = start_addr >> 32;
    #endif

    /* reset vector */
    uint32_t reset_vec[8] = {
    uint32_t reset_vec[11] = {
        s->msel,                       /* MSEL pin state */
        0x00000297,                    /* 1:  auipc  t0, %pcrel_hi(dtb) */
        0x01c28593,                    /*     addi   a1, t0, %pcrel_lo(1b) */
        0x00000297,                    /* 1:  auipc  t0, %pcrel_hi(fw_dyn) */
        0x02828613,                    /*     addi   a2, t0, %pcrel_lo(1b) */
        0xf1402573,                    /*     csrr   a0, mhartid  */
#if defined(TARGET_RISCV32)
        0x0202a583,                    /*     lw     a1, 32(t0) */
        0x0182a283,                    /*     lw     t0, 24(t0) */
#elif defined(TARGET_RISCV64)
        0x0182e283,                    /*     lwu    t0, 24(t0) */
        0x0202b583,                    /*     ld     a1, 32(t0) */
        0x0182b283,                    /*     ld     t0, 24(t0) */
#endif
        0x00028067,                    /*     jr     t0 */
        0x00000000,
        start_addr,                    /* start: .dword */
                                       /* dtb: */
        start_addr_hi32,
        fdt_load_addr,                 /* fdt_laddr: .dword */
        0x00000000,
                                       /* fw_dyn: */
    };

    /* copy in the reset vector in little_endian byte order */
    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
    for (i = 0; i < ARRAY_SIZE(reset_vec); 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 */
    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);
    riscv_rom_copy_firmware_info(memmap[SIFIVE_U_MROM].base,
                                 memmap[SIFIVE_U_MROM].size,
                                 sizeof(reset_vec), kernel_entry);
}

static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp)
+18 −41
Original line number Diff line number Diff line
@@ -41,9 +41,6 @@
#include "sysemu/device_tree.h"
#include "sysemu/qtest.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"

#include <libfdt.h>

#if defined(TARGET_RISCV32)
# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf"
@@ -55,7 +52,7 @@ static const struct MemmapEntry {
    hwaddr base;
    hwaddr size;
} spike_memmap[] = {
    [SPIKE_MROM] =     {     0x1000,    0x11000 },
    [SPIKE_MROM] =     {     0x1000,     0xf000 },
    [SPIKE_CLINT] =    {  0x2000000,    0x10000 },
    [SPIKE_DRAM] =     { 0x80000000,        0x0 },
};
@@ -165,8 +162,9 @@ static void spike_board_init(MachineState *machine)
    MemoryRegion *system_memory = get_system_memory();
    MemoryRegion *main_mem = g_new(MemoryRegion, 1);
    MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
    int i;
    unsigned int smp_cpus = machine->smp.cpus;
    uint32_t fdt_load_addr;
    uint64_t kernel_entry;

    /* Initialize SOC */
    object_initialize_child(OBJECT(machine), "soc", &s->soc,
@@ -197,7 +195,7 @@ static void spike_board_init(MachineState *machine)
                                 htif_symbol_callback);

    if (machine->kernel_filename) {
        uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
        kernel_entry = riscv_load_kernel(machine->kernel_filename,
                                         htif_symbol_callback);

        if (machine->initrd_filename) {
@@ -210,42 +208,21 @@ static void spike_board_init(MachineState *machine)
            qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
                                  end);
        }
    } else {
       /*
        * If dynamic firmware is used, it doesn't know where is the next mode
        * if kernel argument is not set.
        */
        kernel_entry = 0;
    }

    /* reset vector */
    uint32_t reset_vec[8] = {
        0x00000297,                  /* 1:  auipc  t0, %pcrel_hi(dtb) */
        0x02028593,                  /*     addi   a1, t0, %pcrel_lo(1b) */
        0xf1402573,                  /*     csrr   a0, mhartid  */
#if defined(TARGET_RISCV32)
        0x0182a283,                  /*     lw     t0, 24(t0) */
#elif defined(TARGET_RISCV64)
        0x0182b283,                  /*     ld     t0, 24(t0) */
#endif
        0x00028067,                  /*     jr     t0 */
        0x00000000,
        memmap[SPIKE_DRAM].base,     /* start: .dword DRAM_BASE */
        0x00000000,
                                     /* dtb: */
    };

    /* 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 */
    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);
    /* Compute the fdt load address in dram */
    fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
                                   machine->ram_size, s->fdt);
    /* load the reset vector */
    riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base,
                              memmap[SPIKE_MROM].size, kernel_entry,
                              fdt_load_addr, s->fdt);

    /* initialize HTIF using symbols found in load_kernel */
    htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0));
Loading