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:
Peter Maydell 2020-10-26 11:27:40 +00:00
commit 288a1cc634
14 changed files with 238 additions and 55 deletions

View File

@ -19,11 +19,22 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "qemu/log.h"
#include "qemu/module.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)
{
@ -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) &&
(s->pdstb & SIFIVE_U_OTP_PDSTB_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];
} else {
return 0xff;
@ -123,7 +144,30 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
s->ptrim = val32;
break;
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;
default:
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[] = {
DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk),
DEFINE_PROP_END_OF_LIST(),
};
static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
{
SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
DriveInfo *dinfo;
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
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)
@ -165,6 +241,23 @@ static void sifive_u_otp_reset(DeviceState *dev)
/* Make a valid content of serial number */
s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = 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)

View File

@ -33,19 +33,36 @@
#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,
const char *default_machine_firmware,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb)
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,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb)
{
char *firmware_filename = NULL;
target_ulong firmware_end_addr = firmware_load_addr;
if ((!machine->firmware) || (!strcmp(machine->firmware, "default"))) {
/*
@ -60,9 +77,12 @@ void riscv_find_and_load_firmware(MachineState *machine,
if (firmware_filename) {
/* 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);
}
return firmware_end_addr;
}
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,
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,
&firmware_entry, NULL, NULL, NULL,
&firmware_entry, NULL, &firmware_end, NULL,
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,
ram_size, NULL) > 0) {
return firmware_load_addr;
firmware_size = load_image_targphys_as(firmware_filename,
firmware_load_addr, ram_size, NULL);
if (firmware_size > 0) {
return firmware_load_addr + firmware_size;
}
error_report("could not load firmware '%s'", firmware_filename);
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;
@ -123,9 +147,9 @@ target_ulong riscv_load_kernel(const char *kernel_filename, symbol_fn_t sym_cb)
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) {
return KERNEL_BOOT_ADDRESS;
return kernel_start_addr;
}
error_report("could not load kernel '%s'", kernel_filename);

View File

@ -75,7 +75,8 @@ static void opentitan_board_init(MachineState *machine)
}
if (machine->kernel_filename) {
riscv_load_kernel(machine->kernel_filename, NULL);
riscv_load_kernel(machine->kernel_filename,
memmap[IBEX_DEV_RAM].base, NULL);
}
}

View File

@ -114,7 +114,8 @@ static void sifive_e_machine_init(MachineState *machine)
memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory);
if (machine->kernel_filename) {
riscv_load_kernel(machine->kernel_filename, NULL);
riscv_load_kernel(machine->kernel_filename,
memmap[SIFIVE_E_DEV_DTIM].base, NULL);
}
}

View File

@ -415,6 +415,7 @@ 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_DEV_DRAM].base;
target_ulong firmware_end_addr, kernel_start_addr;
uint32_t start_addr_hi32 = 0x00000000;
int i;
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_property_set_uint(OBJECT(&s->soc), "serial", s->serial,
&error_abort);
object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type,
&error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
/* register RAM */
@ -472,10 +475,15 @@ static void sifive_u_machine_init(MachineState *machine)
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) {
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) {
hwaddr start;
@ -590,6 +598,11 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
mc->init = sifive_u_machine_init;
mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
#if defined(TARGET_RISCV32)
mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U34;
#elif defined(TARGET_RISCV64)
mc->default_cpu_type = TYPE_RISCV_CPU_SIFIVE_U54;
#endif
mc->default_cpus = mc->min_cpus;
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)
{
MachineState *ms = MACHINE(qdev_get_machine());
SiFiveUSoCState *s = RISCV_U_SOC(obj);
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,
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, "otp", &s->otp, TYPE_SIFIVE_U_OTP);
@ -661,6 +669,11 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
int i;
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->u_cpus), &error_abort);
/*
@ -792,6 +805,7 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
static Property sifive_u_soc_props[] = {
DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL),
DEFINE_PROP_STRING("cpu-type", SiFiveUSoCState, cpu_type),
DEFINE_PROP_END_OF_LIST()
};

View File

@ -195,6 +195,7 @@ 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);
target_ulong firmware_end_addr, kernel_start_addr;
uint32_t fdt_load_addr;
uint64_t kernel_entry;
char *soc_name;
@ -261,12 +262,16 @@ static void spike_board_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
riscv_find_and_load_firmware(machine, BIOS_FILENAME,
memmap[SPIKE_DRAM].base,
htif_symbol_callback);
firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
memmap[SPIKE_DRAM].base,
htif_symbol_callback);
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_start_addr,
htif_symbol_callback);
if (machine->initrd_filename) {

View File

@ -493,6 +493,7 @@ static void virt_machine_init(MachineState *machine)
char *plic_hart_config, *soc_name;
size_t plic_hart_config_len;
target_ulong start_addr = memmap[VIRT_DRAM].base;
target_ulong firmware_end_addr, kernel_start_addr;
uint32_t fdt_load_addr;
uint64_t kernel_entry;
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,
mask_rom);
riscv_find_and_load_firmware(machine, BIOS_FILENAME,
memmap[VIRT_DRAM].base, NULL);
firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
start_addr, NULL);
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) {
hwaddr start;

View File

@ -36,6 +36,8 @@
#define SIFIVE_U_OTP_PTRIM 0x34
#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_PDSTB_EN (1 << 0)
@ -44,6 +46,7 @@
#define SIFIVE_U_OTP_PA_MASK 0xfff
#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_REG_SIZE 0x1000
@ -75,8 +78,10 @@ struct SiFiveUOTPState {
uint32_t ptrim;
uint32_t pwe;
uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES];
/* config */
uint32_t serial;
BlockBackend *blk;
};
#endif /* HW_SIFIVE_U_OTP_H */

View File

@ -23,15 +23,20 @@
#include "exec/cpu-defs.h"
#include "hw/loader.h"
void riscv_find_and_load_firmware(MachineState *machine,
const char *default_machine_firmware,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb);
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,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb);
char *riscv_find_firmware(const char *firmware_filename);
target_ulong riscv_load_firmware(const char *firmware_filename,
hwaddr firmware_load_addr,
symbol_fn_t sym_cb);
target_ulong riscv_load_kernel(const char *kernel_filename,
target_ulong firmware_end_addr,
symbol_fn_t sym_cb);
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
uint64_t kernel_entry, hwaddr *start);

View File

@ -48,6 +48,7 @@ typedef struct SiFiveUSoCState {
CadenceGEMState gem;
uint32_t serial;
char *cpu_type;
} SiFiveUSoCState;
#define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u")

View File

@ -82,9 +82,13 @@ enum {
#define VEXT_VERSION_0_07_1 0x00000701
#define TRANSLATE_PMP_FAIL 2
#define TRANSLATE_FAIL 1
#define TRANSLATE_SUCCESS 0
enum {
TRANSLATE_SUCCESS,
TRANSLATE_FAIL,
TRANSLATE_PMP_FAIL,
TRANSLATE_G_STAGE_FAIL
};
#define MMU_USER_IDX 3
#define MAX_RISCV_PMPS (16)

View File

@ -316,6 +316,9 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
* @physical: This will be set to the calculated physical address
* @prot: The returned protection attributes
* @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
* @mmu_idx: Indicates current privilege level
* @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,
int *prot, target_ulong addr,
target_ulong *fault_pte_addr,
int access_type, int mmu_idx,
bool first_stage, bool two_stage)
{
@ -447,11 +451,14 @@ restart:
/* Do the second stage translation on the base PTE address. */
int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
base, MMU_DATA_LOAD,
base, NULL, MMU_DATA_LOAD,
mmu_idx, false, true);
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;
@ -632,13 +639,13 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
int prot;
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))) {
return -1;
}
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)) {
return -1;
}
@ -727,19 +734,30 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
if (riscv_cpu_virt_enabled(env) ||
(riscv_cpu_two_stage_lookup(env) && access_type != MMU_INST_FETCH)) {
/* 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);
/*
* 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,
"%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
TARGET_FMT_plx " prot %d\n",
__func__, address, ret, pa, prot);
if (ret != TRANSLATE_FAIL) {
if (ret == TRANSLATE_SUCCESS) {
/* Second stage lookup */
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);
qemu_log_mask(CPU_LOG_MMU,
@ -768,8 +786,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
} else {
/* Single stage lookup */
ret = get_physical_address(env, &pa, &prot, address, access_type,
mmu_idx, true, false);
ret = get_physical_address(env, &pa, &prot, address, NULL,
access_type, mmu_idx, true, false);
qemu_log_mask(CPU_LOG_MMU,
"%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);
target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
target_ulong deleg = async ? env->mideleg : env->medeleg;
bool write_tval = false;
target_ulong tval = 0;
target_ulong htval = 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_LOAD_PAGE_FAULT:
case RISCV_EXCP_STORE_PAGE_FAULT:
write_tval = true;
tval = env->badaddr;
break;
default:
@ -895,7 +915,13 @@ void riscv_cpu_do_interrupt(CPUState *cs)
}
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 &&
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
@ -904,7 +930,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
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
* 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 */
riscv_cpu_swap_hypervisor_regs(env);
env->hstatus = set_field(env->hstatus, HSTATUS_SPVP,
get_field(env->mstatus, SSTATUS_SPP));
env->priv);
env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
riscv_cpu_virt_enabled(env));

View File

@ -29,7 +29,6 @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
uint32_t exception, uintptr_t pc)
{
CPUState *cs = env_cpu(env);
qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
cs->exception_index = exception;
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);
switch (memop) {
case MO_TEUL:
pte = cpu_ldub_data_ra(env, address, GETPC());
break;
case MO_TEUW:
pte = cpu_lduw_data_ra(env, address, GETPC());
break;
case MO_TEUL:
pte = cpu_ldl_data_ra(env, address, GETPC());
break;
default:
g_assert_not_reached();
}