12 changes: 7 additions & 5 deletions hw/char/riscv_htif.c
Expand Up @@ -30,6 +30,7 @@
#include "qemu/timer.h"
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "exec/tswap.h"
#include "sysemu/dma.h"

#define RISCV_DEBUG_HTIF 0
Expand Down Expand Up @@ -209,11 +210,11 @@ static void htif_handle_tohost_write(HTIFState *s, uint64_t val_written)
} else {
uint64_t syscall[8];
cpu_physical_memory_read(payload, syscall, sizeof(syscall));
if (syscall[0] == PK_SYS_WRITE &&
syscall[1] == HTIF_DEV_CONSOLE &&
syscall[3] == HTIF_CONSOLE_CMD_PUTC) {
if (tswap64(syscall[0]) == PK_SYS_WRITE &&
tswap64(syscall[1]) == HTIF_DEV_CONSOLE &&
tswap64(syscall[3]) == HTIF_CONSOLE_CMD_PUTC) {
uint8_t ch;
cpu_physical_memory_read(syscall[2], &ch, 1);
cpu_physical_memory_read(tswap64(syscall[2]), &ch, 1);
qemu_chr_fe_write(&s->chr, &ch, 1);
resp = 0x100 | (uint8_t)payload;
} else {
Expand All @@ -232,7 +233,8 @@ static void htif_handle_tohost_write(HTIFState *s, uint64_t val_written)
s->tohost = 0; /* clear to indicate we read */
return;
} else if (cmd == HTIF_CONSOLE_CMD_PUTC) {
qemu_chr_fe_write(&s->chr, (uint8_t *)&payload, 1);
uint8_t ch = (uint8_t)payload;
qemu_chr_fe_write(&s->chr, &ch, 1);
resp = 0x100 | (uint8_t)payload;
} else {
qemu_log("HTIF device %d: unknown command\n", device);
Expand Down
11 changes: 6 additions & 5 deletions hw/intc/riscv_aclint.c
Expand Up @@ -64,13 +64,13 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
uint64_t next;
uint64_t diff;

uint64_t rtc_r = cpu_riscv_read_rtc(mtimer);
uint64_t rtc = cpu_riscv_read_rtc(mtimer);

/* Compute the relative hartid w.r.t the socket */
hartid = hartid - mtimer->hartid_base;

mtimer->timecmp[hartid] = value;
if (mtimer->timecmp[hartid] <= rtc_r) {
if (mtimer->timecmp[hartid] <= rtc) {
/*
* If we're setting an MTIMECMP value in the "past",
* immediately raise the timer interrupt
Expand All @@ -81,7 +81,7 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,

/* otherwise, set up the future timer interrupt */
qemu_irq_lower(mtimer->timer_irqs[hartid]);
diff = mtimer->timecmp[hartid] - rtc_r;
diff = mtimer->timecmp[hartid] - rtc;
/* back to ns (note args switched in muldiv64) */
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);

Expand Down Expand Up @@ -208,19 +208,20 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
return;
} else if (addr == mtimer->time_base || addr == mtimer->time_base + 4) {
uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq);
uint64_t rtc = cpu_riscv_read_rtc(mtimer);

if (addr == mtimer->time_base) {
if (size == 4) {
/* time_lo for RV32/RV64 */
mtimer->time_delta = ((rtc_r & ~0xFFFFFFFFULL) | value) - rtc_r;
mtimer->time_delta = ((rtc & ~0xFFFFFFFFULL) | value) - rtc_r;
} else {
/* time for RV64 */
mtimer->time_delta = value - rtc_r;
}
} else {
if (size == 4) {
/* time_hi for RV32/RV64 */
mtimer->time_delta = (value << 32 | (rtc_r & 0xFFFFFFFF)) - rtc_r;
mtimer->time_delta = (value << 32 | (rtc & 0xFFFFFFFF)) - rtc_r;
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"aclint-mtimer: invalid time_hi write: %08x",
Expand Down
2 changes: 1 addition & 1 deletion hw/riscv/virt.c
Expand Up @@ -732,7 +732,7 @@ static void create_fdt_pmu(RISCVVirtState *s)
MachineState *ms = MACHINE(s);
RISCVCPU hart = s->soc[0].harts[0];

pmu_name = g_strdup_printf("/soc/pmu");
pmu_name = g_strdup_printf("/pmu");
qemu_fdt_add_subnode(ms->fdt, pmu_name);
qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu");
riscv_pmu_generate_fdt_node(ms->fdt, hart.cfg.pmu_num, pmu_name);
Expand Down
45 changes: 40 additions & 5 deletions hw/virtio/virtio.c
Expand Up @@ -2825,8 +2825,9 @@ static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
}

/* A wrapper for use as a VMState .get function */
static int virtio_device_get(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field)
static int coroutine_mixed_fn
virtio_device_get(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
DeviceClass *dc = DEVICE_CLASS(VIRTIO_DEVICE_GET_CLASS(vdev));
Expand All @@ -2853,6 +2854,39 @@ static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val)
return bad ? -1 : 0;
}

typedef struct VirtioSetFeaturesNocheckData {
Coroutine *co;
VirtIODevice *vdev;
uint64_t val;
int ret;
} VirtioSetFeaturesNocheckData;

static void virtio_set_features_nocheck_bh(void *opaque)
{
VirtioSetFeaturesNocheckData *data = opaque;

data->ret = virtio_set_features_nocheck(data->vdev, data->val);
aio_co_wake(data->co);
}

static int coroutine_mixed_fn
virtio_set_features_nocheck_maybe_co(VirtIODevice *vdev, uint64_t val)
{
if (qemu_in_coroutine()) {
VirtioSetFeaturesNocheckData data = {
.co = qemu_coroutine_self(),
.vdev = vdev,
.val = val,
};
aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
virtio_set_features_nocheck_bh, &data);
qemu_coroutine_yield();
return data.ret;
} else {
return virtio_set_features_nocheck(vdev, val);
}
}

int virtio_set_features(VirtIODevice *vdev, uint64_t val)
{
int ret;
Expand Down Expand Up @@ -2906,7 +2940,8 @@ size_t virtio_get_config_size(const VirtIOConfigSizeParams *params,
return config_size;
}

int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
int coroutine_mixed_fn
virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
{
int i, ret;
int32_t config_len;
Expand Down Expand Up @@ -3023,14 +3058,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
* host_features.
*/
uint64_t features64 = vdev->guest_features;
if (virtio_set_features_nocheck(vdev, features64) < 0) {
if (virtio_set_features_nocheck_maybe_co(vdev, features64) < 0) {
error_report("Features 0x%" PRIx64 " unsupported. "
"Allowed features: 0x%" PRIx64,
features64, vdev->host_features);
return -1;
}
} else {
if (virtio_set_features_nocheck(vdev, features) < 0) {
if (virtio_set_features_nocheck_maybe_co(vdev, features) < 0) {
error_report("Features 0x%x unsupported. "
"Allowed features: 0x%" PRIx64,
features, vdev->host_features);
Expand Down
4 changes: 2 additions & 2 deletions linux-user/riscv/signal.c
Expand Up @@ -38,8 +38,8 @@ struct target_sigcontext {
}; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */

struct target_ucontext {
unsigned long uc_flags;
struct target_ucontext *uc_link;
abi_ulong uc_flags;
abi_ptr uc_link;
target_stack_t uc_stack;
target_sigset_t uc_sigmask;
uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
Expand Down
1 change: 1 addition & 0 deletions target/arm/kvm64.c
Expand Up @@ -674,6 +674,7 @@ typedef struct CPRegStateLevel {
*/
static const CPRegStateLevel non_runtime_cpregs[] = {
{ KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
{ KVM_REG_ARM_PTIMER_CNT, KVM_PUT_FULL_STATE },
};

int kvm_arm_cpreg_level(uint64_t regidx)
Expand Down
32 changes: 28 additions & 4 deletions target/riscv/cpu.c
Expand Up @@ -88,6 +88,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
ISA_EXT_DATA_ENTRY(zfbfmin, PRIV_VERSION_1_12_0, ext_zfbfmin),
Expand Down Expand Up @@ -298,6 +299,17 @@ static uint8_t satp_mode_from_str(const char *satp_mode_str)

uint8_t satp_mode_max_from_map(uint32_t map)
{
/*
* 'map = 0' will make us return (31 - 32), which C will
* happily overflow to UINT_MAX. There's no good result to
* return if 'map = 0' (e.g. returning 0 will be ambiguous
* with the result for 'map = 1').
*
* Assert out if map = 0. Callers will have to deal with
* it outside of this function.
*/
g_assert(map > 0);

/* map here has at least one bit set, so no problem with clz */
return 31 - __builtin_clz(map);
}
Expand Down Expand Up @@ -904,7 +916,7 @@ static void riscv_cpu_reset_hold(Object *obj)

#ifndef CONFIG_USER_ONLY
if (cpu->cfg.debug) {
riscv_trigger_init(env);
riscv_trigger_reset_hold(env);
}

if (kvm_enabled()) {
Expand Down Expand Up @@ -1303,9 +1315,15 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
{
bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
uint8_t satp_mode_map_max;
uint8_t satp_mode_supported_max =
satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
uint8_t satp_mode_map_max, satp_mode_supported_max;

/* The CPU wants the OS to decide which satp mode to use */
if (cpu->cfg.satp_mode.supported == 0) {
return;
}

satp_mode_supported_max =
satp_mode_max_from_map(cpu->cfg.satp_mode.supported);

if (cpu->cfg.satp_mode.map == 0) {
if (cpu->cfg.satp_mode.init == 0) {
Expand Down Expand Up @@ -1473,6 +1491,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)

riscv_cpu_register_gdb_regs_for_features(cs);

#ifndef CONFIG_USER_ONLY
if (cpu->cfg.debug) {
riscv_trigger_realize(&cpu->env);
}
#endif

qemu_init_vcpu(cs);
cpu_reset(cs);

Expand Down
15 changes: 12 additions & 3 deletions target/riscv/debug.c
Expand Up @@ -903,7 +903,17 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
return false;
}

void riscv_trigger_init(CPURISCVState *env)
void riscv_trigger_realize(CPURISCVState *env)
{
int i;

for (i = 0; i < RV_MAX_TRIGGERS; i++) {
env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
riscv_itrigger_timer_cb, env);
}
}

void riscv_trigger_reset_hold(CPURISCVState *env)
{
target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
int i;
Expand All @@ -928,7 +938,6 @@ void riscv_trigger_init(CPURISCVState *env)
env->tdata3[i] = 0;
env->cpu_breakpoint[i] = NULL;
env->cpu_watchpoint[i] = NULL;
env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
riscv_itrigger_timer_cb, env);
timer_del(env->itrigger_timer[i]);
}
}
3 changes: 2 additions & 1 deletion target/riscv/debug.h
Expand Up @@ -143,7 +143,8 @@ void riscv_cpu_debug_excp_handler(CPUState *cs);
bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);

void riscv_trigger_init(CPURISCVState *env);
void riscv_trigger_realize(CPURISCVState *env);
void riscv_trigger_reset_hold(CPURISCVState *env);

bool riscv_itrigger_enabled(CPURISCVState *env);
void riscv_itrigger_update_priv(CPURISCVState *env);
Expand Down
4 changes: 2 additions & 2 deletions target/riscv/insn_trans/trans_rvzfa.c.inc
Expand Up @@ -470,7 +470,7 @@ bool trans_fleq_d(DisasContext *ctx, arg_fleq_d *a)
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);

gen_helper_fltq_s(dest, cpu_env, src1, src2);
gen_helper_fleq_d(dest, cpu_env, src1, src2);
gen_set_gpr(ctx, a->rd, dest);
return true;
}
Expand All @@ -485,7 +485,7 @@ bool trans_fltq_d(DisasContext *ctx, arg_fltq_d *a)
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
TCGv_i64 src2 = get_fpr_hs(ctx, a->rs2);

gen_helper_fltq_s(dest, cpu_env, src1, src2);
gen_helper_fltq_d(dest, cpu_env, src1, src2);
gen_set_gpr(ctx, a->rd, dest);
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions target/riscv/pmp.c
Expand Up @@ -44,6 +44,10 @@ static inline uint8_t pmp_get_a_field(uint8_t cfg)
*/
static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
{
/* mseccfg.RLB is set */
if (MSECCFG_RLB_ISSET(env)) {
return 0;
}

if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
return 1;
Expand Down
2 changes: 1 addition & 1 deletion target/riscv/vector_helper.c
Expand Up @@ -583,7 +583,7 @@ vext_ldff(void *vd, void *v0, target_ulong base,
cpu_mmu_index(env, false));
if (host) {
#ifdef CONFIG_USER_ONLY
if (page_check_range(addr, offset, PAGE_READ)) {
if (!page_check_range(addr, offset, PAGE_READ)) {
vl = i;
goto ProbeSuccess;
}
Expand Down