A collection of RISC-V fixes for the next QEMU release.
This includes: - Improvements to logging output - Hypervisor instruction fixups - The ability to load a noMMU kernel - SiFive OTP support -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAl+S8zUACgkQIeENKd+X cFR79wf/UjQulwFofCgOh8Fsrh5tlbRVYSXEHCWkEg6V8yfA+WYkkup94wBJK0V6 tJglht7v8aovUFWRyEL+yB+zXmT88ZugW20D3NtP5aaTTuPWij2qlYDTJQK9FGEf 1rW5mFZ4VkULEEHeO6MoJ/0t50Cs4ViA//Qz6Un4Z+zVqYjkItT5NNYx9j+czLIJ KBre/ziJXu8yIxYaxqy4Lb4IepVL5T9/pjIw5nbNbWE+DfnfqiUPVifXx73gFRPZ zRfgDD+Dbn/bbmDl137PkpPa2hk5CNUAL8/9rEhnjji2Lrb6SH+gFc0GvnZk7DJm duKXhegU/ATZlI+1bLqL1D1z8Do6qQ== =H9Qu -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20201023' into staging A collection of RISC-V fixes for the next QEMU release. This includes: - Improvements to logging output - Hypervisor instruction fixups - The ability to load a noMMU kernel - SiFive OTP support # gpg: Signature made Fri 23 Oct 2020 16:13:57 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-20201023: hw/misc/sifive_u_otp: Add backend drive support hw/misc/sifive_u_otp: Add write function and write-once protection target/riscv: raise exception to HS-mode at get_physical_address hw/riscv: Load the kernel after the firmware hw/riscv: Add a riscv_is_32_bit() function hw/riscv: Return the end address of the loaded firmware hw/riscv: sifive_u: Allow specifying the CPU target/riscv: Fix implementation of HLVX.WU instruction target/riscv: Fix update of hstatus.GVA in riscv_cpu_do_interrupt target/riscv: Fix update of hstatus.SPVP hw/intc: Move sifive_plic.h to the include directory riscv: Convert interrupt logs to use qemu_log_mask() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
288a1cc634
@ -19,11 +19,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "hw/misc/sifive_u_otp.h"
|
#include "hw/misc/sifive_u_otp.h"
|
||||||
|
#include "sysemu/blockdev.h"
|
||||||
|
#include "sysemu/block-backend.h"
|
||||||
|
|
||||||
|
#define WRITTEN_BIT_ON 0x1
|
||||||
|
|
||||||
|
#define SET_FUSEARRAY_BIT(map, i, off, bit) \
|
||||||
|
map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(0x1 << off))
|
||||||
|
|
||||||
|
#define GET_FUSEARRAY_BIT(map, i, off) \
|
||||||
|
((map[i] >> off) & 0x1)
|
||||||
|
|
||||||
static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
|
static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
|
||||||
{
|
{
|
||||||
@ -46,6 +57,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
|
|||||||
if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
|
if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
|
||||||
(s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
|
(s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
|
||||||
(s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
|
(s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
|
||||||
|
|
||||||
|
/* read from backend */
|
||||||
|
if (s->blk) {
|
||||||
|
int32_t buf;
|
||||||
|
|
||||||
|
blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
|
||||||
|
SIFIVE_U_OTP_FUSE_WORD);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
|
return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
|
||||||
} else {
|
} else {
|
||||||
return 0xff;
|
return 0xff;
|
||||||
@ -123,7 +144,30 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
|
|||||||
s->ptrim = val32;
|
s->ptrim = val32;
|
||||||
break;
|
break;
|
||||||
case SIFIVE_U_OTP_PWE:
|
case SIFIVE_U_OTP_PWE:
|
||||||
s->pwe = val32;
|
s->pwe = val32 & SIFIVE_U_OTP_PWE_EN;
|
||||||
|
|
||||||
|
/* PWE is enabled. Ignore PAS=1 (no redundancy cell) */
|
||||||
|
if (s->pwe && !s->pas) {
|
||||||
|
if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"write once error: idx<%u>, bit<%u>\n",
|
||||||
|
s->pa, s->paio);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write bit data */
|
||||||
|
SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update written bit */
|
||||||
|
SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
|
||||||
@ -143,16 +187,48 @@ static const MemoryRegionOps sifive_u_otp_ops = {
|
|||||||
|
|
||||||
static Property sifive_u_otp_properties[] = {
|
static Property sifive_u_otp_properties[] = {
|
||||||
DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
|
DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
|
||||||
|
DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
|
static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
|
SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
|
||||||
|
DriveInfo *dinfo;
|
||||||
|
|
||||||
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
|
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
|
||||||
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
|
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
|
||||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
|
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
|
||||||
|
|
||||||
|
dinfo = drive_get_next(IF_NONE);
|
||||||
|
if (dinfo) {
|
||||||
|
int ret;
|
||||||
|
uint64_t perm;
|
||||||
|
int filesize;
|
||||||
|
BlockBackend *blk;
|
||||||
|
|
||||||
|
blk = blk_by_legacy_dinfo(dinfo);
|
||||||
|
filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD;
|
||||||
|
if (blk_getlength(blk) < filesize) {
|
||||||
|
error_setg(errp, "OTP drive size < 16K");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdev_prop_set_drive_err(dev, "drive", blk, errp);
|
||||||
|
|
||||||
|
if (s->blk) {
|
||||||
|
perm = BLK_PERM_CONSISTENT_READ |
|
||||||
|
(blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
|
||||||
|
ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
|
||||||
|
error_setg(errp, "failed to read the initial flash content");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sifive_u_otp_reset(DeviceState *dev)
|
static void sifive_u_otp_reset(DeviceState *dev)
|
||||||
@ -165,6 +241,23 @@ static void sifive_u_otp_reset(DeviceState *dev)
|
|||||||
/* Make a valid content of serial number */
|
/* Make a valid content of serial number */
|
||||||
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial;
|
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial;
|
||||||
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial);
|
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial);
|
||||||
|
|
||||||
|
if (s->blk) {
|
||||||
|
/* Put serial number to backend as well*/
|
||||||
|
uint32_t serial_data;
|
||||||
|
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);
|
||||||
|
|
||||||
|
serial_data = ~(s->serial);
|
||||||
|
blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
|
||||||
|
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize write-once map */
|
||||||
|
memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sifive_u_otp_class_init(ObjectClass *klass, void *data)
|
static void sifive_u_otp_class_init(ObjectClass *klass, void *data)
|
||||||
|
@ -33,19 +33,36 @@
|
|||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
#if defined(TARGET_RISCV32)
|
#if defined(TARGET_RISCV32)
|
||||||
# define KERNEL_BOOT_ADDRESS 0x80400000
|
|
||||||
#define fw_dynamic_info_data(__val) cpu_to_le32(__val)
|
#define fw_dynamic_info_data(__val) cpu_to_le32(__val)
|
||||||
#else
|
#else
|
||||||
# define KERNEL_BOOT_ADDRESS 0x80200000
|
|
||||||
#define fw_dynamic_info_data(__val) cpu_to_le64(__val)
|
#define fw_dynamic_info_data(__val) cpu_to_le64(__val)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void riscv_find_and_load_firmware(MachineState *machine,
|
bool riscv_is_32_bit(MachineState *machine)
|
||||||
|
{
|
||||||
|
if (!strncmp(machine->cpu_type, "rv32", 4)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
|
||||||
|
target_ulong firmware_end_addr) {
|
||||||
|
if (riscv_is_32_bit(machine)) {
|
||||||
|
return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB);
|
||||||
|
} else {
|
||||||
|
return QEMU_ALIGN_UP(firmware_end_addr, 2 * MiB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||||
const char *default_machine_firmware,
|
const char *default_machine_firmware,
|
||||||
hwaddr firmware_load_addr,
|
hwaddr firmware_load_addr,
|
||||||
symbol_fn_t sym_cb)
|
symbol_fn_t sym_cb)
|
||||||
{
|
{
|
||||||
char *firmware_filename = NULL;
|
char *firmware_filename = NULL;
|
||||||
|
target_ulong firmware_end_addr = firmware_load_addr;
|
||||||
|
|
||||||
if ((!machine->firmware) || (!strcmp(machine->firmware, "default"))) {
|
if ((!machine->firmware) || (!strcmp(machine->firmware, "default"))) {
|
||||||
/*
|
/*
|
||||||
@ -60,9 +77,12 @@ void riscv_find_and_load_firmware(MachineState *machine,
|
|||||||
|
|
||||||
if (firmware_filename) {
|
if (firmware_filename) {
|
||||||
/* If not "none" load the firmware */
|
/* If not "none" load the firmware */
|
||||||
riscv_load_firmware(firmware_filename, firmware_load_addr, sym_cb);
|
firmware_end_addr = riscv_load_firmware(firmware_filename,
|
||||||
|
firmware_load_addr, sym_cb);
|
||||||
g_free(firmware_filename);
|
g_free(firmware_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return firmware_end_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *riscv_find_firmware(const char *firmware_filename)
|
char *riscv_find_firmware(const char *firmware_filename)
|
||||||
@ -91,24 +111,28 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
|
|||||||
hwaddr firmware_load_addr,
|
hwaddr firmware_load_addr,
|
||||||
symbol_fn_t sym_cb)
|
symbol_fn_t sym_cb)
|
||||||
{
|
{
|
||||||
uint64_t firmware_entry;
|
uint64_t firmware_entry, firmware_size, firmware_end;
|
||||||
|
|
||||||
if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
|
if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
|
||||||
&firmware_entry, NULL, NULL, NULL,
|
&firmware_entry, NULL, &firmware_end, NULL,
|
||||||
0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
|
0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
|
||||||
return firmware_entry;
|
return firmware_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_image_targphys_as(firmware_filename, firmware_load_addr,
|
firmware_size = load_image_targphys_as(firmware_filename,
|
||||||
ram_size, NULL) > 0) {
|
firmware_load_addr, ram_size, NULL);
|
||||||
return firmware_load_addr;
|
|
||||||
|
if (firmware_size > 0) {
|
||||||
|
return firmware_load_addr + firmware_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_report("could not load firmware '%s'", firmware_filename);
|
error_report("could not load firmware '%s'", firmware_filename);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
|
target_ulong riscv_load_kernel(const char *kernel_filename,
|
||||||
|
target_ulong kernel_start_addr,
|
||||||
|
symbol_fn_t sym_cb)
|
||||||
{
|
{
|
||||||
uint64_t kernel_entry;
|
uint64_t kernel_entry;
|
||||||
|
|
||||||
@ -123,9 +147,9 @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
|
|||||||
return kernel_entry;
|
return kernel_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_image_targphys_as(kernel_filename, KERNEL_BOOT_ADDRESS,
|
if (load_image_targphys_as(kernel_filename, kernel_start_addr,
|
||||||
ram_size, NULL) > 0) {
|
ram_size, NULL) > 0) {
|
||||||
return KERNEL_BOOT_ADDRESS;
|
return kernel_start_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_report("could not load kernel '%s'", kernel_filename);
|
error_report("could not load kernel '%s'", kernel_filename);
|
||||||
|
@ -75,7 +75,8 @@ static void opentitan_board_init(MachineState *machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
riscv_load_kernel(machine->kernel_filename, NULL);
|
riscv_load_kernel(machine->kernel_filename,
|
||||||
|
memmap[IBEX_DEV_RAM].base, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,8 @@ static void sifive_e_machine_init(MachineState *machine)
|
|||||||
memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory);
|
memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory);
|
||||||
|
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
riscv_load_kernel(machine->kernel_filename, NULL);
|
riscv_load_kernel(machine->kernel_filename,
|
||||||
|
memmap[SIFIVE_E_DEV_DTIM].base, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +415,7 @@ static void sifive_u_machine_init(MachineState *machine)
|
|||||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
|
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
|
||||||
target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
|
target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
|
||||||
|
target_ulong firmware_end_addr, kernel_start_addr;
|
||||||
uint32_t start_addr_hi32 = 0x00000000;
|
uint32_t start_addr_hi32 = 0x00000000;
|
||||||
int i;
|
int i;
|
||||||
uint32_t fdt_load_addr;
|
uint32_t fdt_load_addr;
|
||||||
@ -424,6 +425,8 @@ static void sifive_u_machine_init(MachineState *machine)
|
|||||||
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
|
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
|
||||||
object_property_set_uint(OBJECT(&s->soc), "serial", s->serial,
|
object_property_set_uint(OBJECT(&s->soc), "serial", s->serial,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
|
object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type,
|
||||||
|
&error_abort);
|
||||||
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
|
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
|
||||||
|
|
||||||
/* register RAM */
|
/* register RAM */
|
||||||
@ -472,10 +475,15 @@ static void sifive_u_machine_init(MachineState *machine)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
riscv_find_and_load_firmware(machine, BIOS_FILENAME, start_addr, NULL);
|
firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
|
||||||
|
start_addr, NULL);
|
||||||
|
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
|
kernel_start_addr = riscv_calc_kernel_start_addr(machine,
|
||||||
|
firmware_end_addr);
|
||||||
|
|
||||||
|
kernel_entry = riscv_load_kernel(machine->kernel_filename,
|
||||||
|
kernel_start_addr, NULL);
|
||||||
|
|
||||||
if (machine->initrd_filename) {
|
if (machine->initrd_filename) {
|
||||||
hwaddr start;
|
hwaddr start;
|
||||||
@ -590,6 +598,11 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
|
|||||||
mc->init = sifive_u_machine_init;
|
mc->init = sifive_u_machine_init;
|
||||||
mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
|
mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
|
||||||
mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
|
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_cpus = mc->min_cpus;
|
mc->default_cpus = mc->min_cpus;
|
||||||
|
|
||||||
object_class_property_add_bool(oc, "start-in-flash",
|
object_class_property_add_bool(oc, "start-in-flash",
|
||||||
@ -618,7 +631,6 @@ type_init(sifive_u_machine_init_register_types)
|
|||||||
|
|
||||||
static void sifive_u_soc_instance_init(Object *obj)
|
static void sifive_u_soc_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
MachineState *ms = MACHINE(qdev_get_machine());
|
|
||||||
SiFiveUSoCState *s = RISCV_U_SOC(obj);
|
SiFiveUSoCState *s = RISCV_U_SOC(obj);
|
||||||
|
|
||||||
object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER);
|
object_initialize_child(obj, "e-cluster", &s->e_cluster, TYPE_CPU_CLUSTER);
|
||||||
@ -636,10 +648,6 @@ static void sifive_u_soc_instance_init(Object *obj)
|
|||||||
|
|
||||||
object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus,
|
object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", &s->u_cpus,
|
||||||
TYPE_RISCV_HART_ARRAY);
|
TYPE_RISCV_HART_ARRAY);
|
||||||
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
|
|
||||||
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
|
|
||||||
qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU);
|
|
||||||
qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004);
|
|
||||||
|
|
||||||
object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI);
|
object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI);
|
||||||
object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP);
|
object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP);
|
||||||
@ -661,6 +669,11 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
int i;
|
int i;
|
||||||
NICInfo *nd = &nd_table[0];
|
NICInfo *nd = &nd_table[0];
|
||||||
|
|
||||||
|
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1);
|
||||||
|
qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1);
|
||||||
|
qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", s->cpu_type);
|
||||||
|
qdev_prop_set_uint64(DEVICE(&s->u_cpus), "resetvec", 0x1004);
|
||||||
|
|
||||||
sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort);
|
sysbus_realize(SYS_BUS_DEVICE(&s->e_cpus), &error_abort);
|
||||||
sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort);
|
sysbus_realize(SYS_BUS_DEVICE(&s->u_cpus), &error_abort);
|
||||||
/*
|
/*
|
||||||
@ -792,6 +805,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
static Property sifive_u_soc_props[] = {
|
static Property sifive_u_soc_props[] = {
|
||||||
DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL),
|
DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL),
|
||||||
|
DEFINE_PROP_STRING("cpu-type", SiFiveUSoCState, cpu_type),
|
||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ static void spike_board_init(MachineState *machine)
|
|||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||||
|
target_ulong firmware_end_addr, kernel_start_addr;
|
||||||
uint32_t fdt_load_addr;
|
uint32_t fdt_load_addr;
|
||||||
uint64_t kernel_entry;
|
uint64_t kernel_entry;
|
||||||
char *soc_name;
|
char *soc_name;
|
||||||
@ -261,12 +262,16 @@ static void spike_board_init(MachineState *machine)
|
|||||||
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
|
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
|
||||||
mask_rom);
|
mask_rom);
|
||||||
|
|
||||||
riscv_find_and_load_firmware(machine, BIOS_FILENAME,
|
firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
|
||||||
memmap[SPIKE_DRAM].base,
|
memmap[SPIKE_DRAM].base,
|
||||||
htif_symbol_callback);
|
htif_symbol_callback);
|
||||||
|
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
|
kernel_start_addr = riscv_calc_kernel_start_addr(machine,
|
||||||
|
firmware_end_addr);
|
||||||
|
|
||||||
kernel_entry = riscv_load_kernel(machine->kernel_filename,
|
kernel_entry = riscv_load_kernel(machine->kernel_filename,
|
||||||
|
kernel_start_addr,
|
||||||
htif_symbol_callback);
|
htif_symbol_callback);
|
||||||
|
|
||||||
if (machine->initrd_filename) {
|
if (machine->initrd_filename) {
|
||||||
|
@ -493,6 +493,7 @@ static void virt_machine_init(MachineState *machine)
|
|||||||
char *plic_hart_config, *soc_name;
|
char *plic_hart_config, *soc_name;
|
||||||
size_t plic_hart_config_len;
|
size_t plic_hart_config_len;
|
||||||
target_ulong start_addr = memmap[VIRT_DRAM].base;
|
target_ulong start_addr = memmap[VIRT_DRAM].base;
|
||||||
|
target_ulong firmware_end_addr, kernel_start_addr;
|
||||||
uint32_t fdt_load_addr;
|
uint32_t fdt_load_addr;
|
||||||
uint64_t kernel_entry;
|
uint64_t kernel_entry;
|
||||||
DeviceState *mmio_plic, *virtio_plic, *pcie_plic;
|
DeviceState *mmio_plic, *virtio_plic, *pcie_plic;
|
||||||
@ -602,11 +603,15 @@ static void virt_machine_init(MachineState *machine)
|
|||||||
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
|
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
|
||||||
mask_rom);
|
mask_rom);
|
||||||
|
|
||||||
riscv_find_and_load_firmware(machine, BIOS_FILENAME,
|
firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
|
||||||
memmap[VIRT_DRAM].base, NULL);
|
start_addr, NULL);
|
||||||
|
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
|
kernel_start_addr = riscv_calc_kernel_start_addr(machine,
|
||||||
|
firmware_end_addr);
|
||||||
|
|
||||||
|
kernel_entry = riscv_load_kernel(machine->kernel_filename,
|
||||||
|
kernel_start_addr, NULL);
|
||||||
|
|
||||||
if (machine->initrd_filename) {
|
if (machine->initrd_filename) {
|
||||||
hwaddr start;
|
hwaddr start;
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
#define SIFIVE_U_OTP_PTRIM 0x34
|
#define SIFIVE_U_OTP_PTRIM 0x34
|
||||||
#define SIFIVE_U_OTP_PWE 0x38
|
#define SIFIVE_U_OTP_PWE 0x38
|
||||||
|
|
||||||
|
#define SIFIVE_U_OTP_PWE_EN (1 << 0)
|
||||||
|
|
||||||
#define SIFIVE_U_OTP_PCE_EN (1 << 0)
|
#define SIFIVE_U_OTP_PCE_EN (1 << 0)
|
||||||
|
|
||||||
#define SIFIVE_U_OTP_PDSTB_EN (1 << 0)
|
#define SIFIVE_U_OTP_PDSTB_EN (1 << 0)
|
||||||
@ -44,6 +46,7 @@
|
|||||||
|
|
||||||
#define SIFIVE_U_OTP_PA_MASK 0xfff
|
#define SIFIVE_U_OTP_PA_MASK 0xfff
|
||||||
#define SIFIVE_U_OTP_NUM_FUSES 0x1000
|
#define SIFIVE_U_OTP_NUM_FUSES 0x1000
|
||||||
|
#define SIFIVE_U_OTP_FUSE_WORD 4
|
||||||
#define SIFIVE_U_OTP_SERIAL_ADDR 0xfc
|
#define SIFIVE_U_OTP_SERIAL_ADDR 0xfc
|
||||||
|
|
||||||
#define SIFIVE_U_OTP_REG_SIZE 0x1000
|
#define SIFIVE_U_OTP_REG_SIZE 0x1000
|
||||||
@ -75,8 +78,10 @@ struct SiFiveUOTPState {
|
|||||||
uint32_t ptrim;
|
uint32_t ptrim;
|
||||||
uint32_t pwe;
|
uint32_t pwe;
|
||||||
uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
|
uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
|
||||||
|
uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES];
|
||||||
/* config */
|
/* config */
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
|
BlockBackend *blk;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HW_SIFIVE_U_OTP_H */
|
#endif /* HW_SIFIVE_U_OTP_H */
|
||||||
|
@ -23,7 +23,11 @@
|
|||||||
#include "exec/cpu-defs.h"
|
#include "exec/cpu-defs.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
|
|
||||||
void riscv_find_and_load_firmware(MachineState *machine,
|
bool riscv_is_32_bit(MachineState *machine);
|
||||||
|
|
||||||
|
target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
|
||||||
|
target_ulong firmware_end_addr);
|
||||||
|
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||||
const char *default_machine_firmware,
|
const char *default_machine_firmware,
|
||||||
hwaddr firmware_load_addr,
|
hwaddr firmware_load_addr,
|
||||||
symbol_fn_t sym_cb);
|
symbol_fn_t sym_cb);
|
||||||
@ -32,6 +36,7 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
|
|||||||
hwaddr firmware_load_addr,
|
hwaddr firmware_load_addr,
|
||||||
symbol_fn_t sym_cb);
|
symbol_fn_t sym_cb);
|
||||||
target_ulong riscv_load_kernel(const char *kernel_filename,
|
target_ulong riscv_load_kernel(const char *kernel_filename,
|
||||||
|
target_ulong firmware_end_addr,
|
||||||
symbol_fn_t sym_cb);
|
symbol_fn_t sym_cb);
|
||||||
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
|
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
|
||||||
uint64_t kernel_entry, hwaddr *start);
|
uint64_t kernel_entry, hwaddr *start);
|
||||||
|
@ -48,6 +48,7 @@ typedef struct SiFiveUSoCState {
|
|||||||
CadenceGEMState gem;
|
CadenceGEMState gem;
|
||||||
|
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
|
char *cpu_type;
|
||||||
} SiFiveUSoCState;
|
} SiFiveUSoCState;
|
||||||
|
|
||||||
#define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u")
|
#define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u")
|
||||||
|
@ -82,9 +82,13 @@ enum {
|
|||||||
|
|
||||||
#define VEXT_VERSION_0_07_1 0x00000701
|
#define VEXT_VERSION_0_07_1 0x00000701
|
||||||
|
|
||||||
#define TRANSLATE_PMP_FAIL 2
|
enum {
|
||||||
#define TRANSLATE_FAIL 1
|
TRANSLATE_SUCCESS,
|
||||||
#define TRANSLATE_SUCCESS 0
|
TRANSLATE_FAIL,
|
||||||
|
TRANSLATE_PMP_FAIL,
|
||||||
|
TRANSLATE_G_STAGE_FAIL
|
||||||
|
};
|
||||||
|
|
||||||
#define MMU_USER_IDX 3
|
#define MMU_USER_IDX 3
|
||||||
|
|
||||||
#define MAX_RISCV_PMPS (16)
|
#define MAX_RISCV_PMPS (16)
|
||||||
|
@ -316,6 +316,9 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
|
|||||||
* @physical: This will be set to the calculated physical address
|
* @physical: This will be set to the calculated physical address
|
||||||
* @prot: The returned protection attributes
|
* @prot: The returned protection attributes
|
||||||
* @addr: The virtual address to be translated
|
* @addr: The virtual address to be translated
|
||||||
|
* @fault_pte_addr: If not NULL, this will be set to fault pte address
|
||||||
|
* when a error occurs on pte address translation.
|
||||||
|
* This will already be shifted to match htval.
|
||||||
* @access_type: The type of MMU access
|
* @access_type: The type of MMU access
|
||||||
* @mmu_idx: Indicates current privilege level
|
* @mmu_idx: Indicates current privilege level
|
||||||
* @first_stage: Are we in first stage translation?
|
* @first_stage: Are we in first stage translation?
|
||||||
@ -324,6 +327,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
|
|||||||
*/
|
*/
|
||||||
static int get_physical_address(CPURISCVState *env, hwaddr *physical,
|
static int get_physical_address(CPURISCVState *env, hwaddr *physical,
|
||||||
int *prot, target_ulong addr,
|
int *prot, target_ulong addr,
|
||||||
|
target_ulong *fault_pte_addr,
|
||||||
int access_type, int mmu_idx,
|
int access_type, int mmu_idx,
|
||||||
bool first_stage, bool two_stage)
|
bool first_stage, bool two_stage)
|
||||||
{
|
{
|
||||||
@ -447,11 +451,14 @@ restart:
|
|||||||
|
|
||||||
/* Do the second stage translation on the base PTE address. */
|
/* Do the second stage translation on the base PTE address. */
|
||||||
int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
|
int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
|
||||||
base, MMU_DATA_LOAD,
|
base, NULL, MMU_DATA_LOAD,
|
||||||
mmu_idx, false, true);
|
mmu_idx, false, true);
|
||||||
|
|
||||||
if (vbase_ret != TRANSLATE_SUCCESS) {
|
if (vbase_ret != TRANSLATE_SUCCESS) {
|
||||||
return vbase_ret;
|
if (fault_pte_addr) {
|
||||||
|
*fault_pte_addr = (base + idx * ptesize) >> 2;
|
||||||
|
}
|
||||||
|
return TRANSLATE_G_STAGE_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_addr = vbase + idx * ptesize;
|
pte_addr = vbase + idx * ptesize;
|
||||||
@ -632,13 +639,13 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
|||||||
int prot;
|
int prot;
|
||||||
int mmu_idx = cpu_mmu_index(&cpu->env, false);
|
int mmu_idx = cpu_mmu_index(&cpu->env, false);
|
||||||
|
|
||||||
if (get_physical_address(env, &phys_addr, &prot, addr, 0, mmu_idx,
|
if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx,
|
||||||
true, riscv_cpu_virt_enabled(env))) {
|
true, riscv_cpu_virt_enabled(env))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riscv_cpu_virt_enabled(env)) {
|
if (riscv_cpu_virt_enabled(env)) {
|
||||||
if (get_physical_address(env, &phys_addr, &prot, phys_addr,
|
if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL,
|
||||||
0, mmu_idx, false, true)) {
|
0, mmu_idx, false, true)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -727,19 +734,30 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||||||
if (riscv_cpu_virt_enabled(env) ||
|
if (riscv_cpu_virt_enabled(env) ||
|
||||||
(riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) {
|
(riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) {
|
||||||
/* Two stage lookup */
|
/* Two stage lookup */
|
||||||
ret = get_physical_address(env, &pa, &prot, address, access_type,
|
ret = get_physical_address(env, &pa, &prot, address,
|
||||||
|
&env->guest_phys_fault_addr, access_type,
|
||||||
mmu_idx, true, true);
|
mmu_idx, true, true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A G-stage exception may be triggered during two state lookup.
|
||||||
|
* And the env->guest_phys_fault_addr has already been set in
|
||||||
|
* get_physical_address().
|
||||||
|
*/
|
||||||
|
if (ret == TRANSLATE_G_STAGE_FAIL) {
|
||||||
|
first_stage_error = false;
|
||||||
|
access_type = MMU_DATA_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_MMU,
|
qemu_log_mask(CPU_LOG_MMU,
|
||||||
"%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
|
"%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
|
||||||
TARGET_FMT_plx " prot %d\n",
|
TARGET_FMT_plx " prot %d\n",
|
||||||
__func__, address, ret, pa, prot);
|
__func__, address, ret, pa, prot);
|
||||||
|
|
||||||
if (ret != TRANSLATE_FAIL) {
|
if (ret == TRANSLATE_SUCCESS) {
|
||||||
/* Second stage lookup */
|
/* Second stage lookup */
|
||||||
im_address = pa;
|
im_address = pa;
|
||||||
|
|
||||||
ret = get_physical_address(env, &pa, &prot2, im_address,
|
ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
|
||||||
access_type, mmu_idx, false, true);
|
access_type, mmu_idx, false, true);
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_MMU,
|
qemu_log_mask(CPU_LOG_MMU,
|
||||||
@ -768,8 +786,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Single stage lookup */
|
/* Single stage lookup */
|
||||||
ret = get_physical_address(env, &pa, &prot, address, access_type,
|
ret = get_physical_address(env, &pa, &prot, address, NULL,
|
||||||
mmu_idx, true, false);
|
access_type, mmu_idx, true, false);
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_MMU,
|
qemu_log_mask(CPU_LOG_MMU,
|
||||||
"%s address=%" VADDR_PRIx " ret %d physical "
|
"%s address=%" VADDR_PRIx " ret %d physical "
|
||||||
@ -852,6 +870,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
|
bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG);
|
||||||
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
|
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
|
||||||
target_ulong deleg = async ? env->mideleg : env->medeleg;
|
target_ulong deleg = async ? env->mideleg : env->medeleg;
|
||||||
|
bool write_tval = false;
|
||||||
target_ulong tval = 0;
|
target_ulong tval = 0;
|
||||||
target_ulong htval = 0;
|
target_ulong htval = 0;
|
||||||
target_ulong mtval2 = 0;
|
target_ulong mtval2 = 0;
|
||||||
@ -873,6 +892,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
case RISCV_EXCP_INST_PAGE_FAULT:
|
case RISCV_EXCP_INST_PAGE_FAULT:
|
||||||
case RISCV_EXCP_LOAD_PAGE_FAULT:
|
case RISCV_EXCP_LOAD_PAGE_FAULT:
|
||||||
case RISCV_EXCP_STORE_PAGE_FAULT:
|
case RISCV_EXCP_STORE_PAGE_FAULT:
|
||||||
|
write_tval = true;
|
||||||
tval = env->badaddr;
|
tval = env->badaddr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -897,6 +917,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
trace_riscv_trap(env->mhartid, async, cause, env->pc, tval,
|
trace_riscv_trap(env->mhartid, async, cause, env->pc, tval,
|
||||||
riscv_cpu_get_trap_name(cause, async));
|
riscv_cpu_get_trap_name(cause, async));
|
||||||
|
|
||||||
|
qemu_log_mask(CPU_LOG_INT,
|
||||||
|
"%s: hart:"TARGET_FMT_ld", async:%d, cause:"TARGET_FMT_lx", "
|
||||||
|
"epc:0x"TARGET_FMT_lx", tval:0x"TARGET_FMT_lx", desc=%s\n",
|
||||||
|
__func__, env->mhartid, async, cause, env->pc, tval,
|
||||||
|
riscv_cpu_get_trap_name(cause, async));
|
||||||
|
|
||||||
if (env->priv <= PRV_S &&
|
if (env->priv <= PRV_S &&
|
||||||
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
|
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
|
||||||
/* handle the trap in S-mode */
|
/* handle the trap in S-mode */
|
||||||
@ -904,7 +930,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
|
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
|
||||||
|
|
||||||
if ((riscv_cpu_virt_enabled(env) ||
|
if ((riscv_cpu_virt_enabled(env) ||
|
||||||
riscv_cpu_two_stage_lookup(env)) && tval) {
|
riscv_cpu_two_stage_lookup(env)) && write_tval) {
|
||||||
/*
|
/*
|
||||||
* If we are writing a guest virtual address to stval, set
|
* If we are writing a guest virtual address to stval, set
|
||||||
* this to 1. If we are trapping to VS we will set this to 0
|
* this to 1. If we are trapping to VS we will set this to 0
|
||||||
@ -932,7 +958,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
/* Trap into HS mode, from virt */
|
/* Trap into HS mode, from virt */
|
||||||
riscv_cpu_swap_hypervisor_regs(env);
|
riscv_cpu_swap_hypervisor_regs(env);
|
||||||
env->hstatus = set_field(env->hstatus, HSTATUS_SPVP,
|
env->hstatus = set_field(env->hstatus, HSTATUS_SPVP,
|
||||||
get_field(env->mstatus, SSTATUS_SPP));
|
env->priv);
|
||||||
env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
|
env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
|
||||||
riscv_cpu_virt_enabled(env));
|
riscv_cpu_virt_enabled(env));
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
|
|||||||
uint32_t exception, uintptr_t pc)
|
uint32_t exception, uintptr_t pc)
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
|
|
||||||
cs->exception_index = exception;
|
cs->exception_index = exception;
|
||||||
cpu_loop_exit_restore(cs, pc);
|
cpu_loop_exit_restore(cs, pc);
|
||||||
}
|
}
|
||||||
@ -334,12 +333,12 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
|
|||||||
riscv_cpu_set_two_stage_lookup(env, true);
|
riscv_cpu_set_two_stage_lookup(env, true);
|
||||||
|
|
||||||
switch (memop) {
|
switch (memop) {
|
||||||
case MO_TEUL:
|
|
||||||
pte = cpu_ldub_data_ra(env, address, GETPC());
|
|
||||||
break;
|
|
||||||
case MO_TEUW:
|
case MO_TEUW:
|
||||||
pte = cpu_lduw_data_ra(env, address, GETPC());
|
pte = cpu_lduw_data_ra(env, address, GETPC());
|
||||||
break;
|
break;
|
||||||
|
case MO_TEUL:
|
||||||
|
pte = cpu_ldl_data_ra(env, address, GETPC());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user