Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-5.…
Browse files Browse the repository at this point in the history
…0-sf3' into staging

RISC-V Patches for the 5.0 Soft Freeze, Part 3

This pull request is almost entirely an implementation of the draft hypervisor
extension.  This extension is still in draft and is expected to have
incompatible changes before being frozen, but we've had good luck managing
other RISC-V draft extensions in QEMU so far.

Additionally, there's a fix to PCI addressing and some improvements to the
M-mode timer.

This boots linux and passes make check for me.

# gpg: Signature made Tue 03 Mar 2020 00:23:20 GMT
# gpg:                using RSA key 2B3C3747446843B24A943A7A2E1319F35FBB1889
# gpg:                issuer "palmer@dabbelt.com"
# gpg: Good signature from "Palmer Dabbelt <palmer@dabbelt.com>" [unknown]
# gpg:                 aka "Palmer Dabbelt <palmer@sifive.com>" [unknown]
# gpg:                 aka "Palmer Dabbelt <palmerdabbelt@google.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 00CE 76D1 8349 60DF CE88  6DF8 EF4C A150 2CCB AB41
#      Subkey fingerprint: 2B3C 3747 4468 43B2 4A94  3A7A 2E13 19F3 5FBB 1889

* remotes/palmer/tags/riscv-for-master-5.0-sf3: (38 commits)
  hw/riscv: Provide rdtime callback for TCG in CLINT emulation
  target/riscv: Emulate TIME CSRs for privileged mode
  riscv: virt: Allow PCI address 0
  target/riscv: Allow enabling the Hypervisor extension
  target/riscv: Add the MSTATUS_MPV_ISSET helper macro
  target/riscv: Add support for the 32-bit MSTATUSH CSR
  target/riscv: Set htval and mtval2 on execptions
  target/riscv: Raise the new execptions when 2nd stage translation fails
  target/riscv: Implement second stage MMU
  target/riscv: Allow specifying MMU stage
  target/riscv: Respect MPRV and SPRV for floating point ops
  target/riscv: Mark both sstatus and msstatus_hs as dirty
  target/riscv: Disable guest FP support based on virtual status
  target/riscv: Only set TB flags with FP status if enabled
  target/riscv: Remove the hret instruction
  target/riscv: Add hfence instructions
  target/riscv: Add Hypervisor trap return support
  target/riscv: Add hypvervisor trap support
  target/riscv: Generate illegal instruction on WFI when V=1
  target/ricsv: Flush the TLB on virtulisation mode changes
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Mar 3, 2020
2 parents c81acb6 + 5f3616c commit 2ac031d
Show file tree
Hide file tree
Showing 16 changed files with 1,240 additions and 141 deletions.
6 changes: 5 additions & 1 deletion hw/riscv/sifive_clint.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ type_init(sifive_clint_register_types)
* Create CLINT device.
*/
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts,
uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base)
uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base,
bool provide_rdtime)
{
int i;
for (i = 0; i < num_harts; i++) {
Expand All @@ -236,6 +237,9 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts,
if (!env) {
continue;
}
if (provide_rdtime) {
riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc);
}
env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
&sifive_clint_timer_cb, cpu);
env->timecmp = 0;
Expand Down
2 changes: 1 addition & 1 deletion hw/riscv/sifive_e.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)
memmap[SIFIVE_E_PLIC].size);
sifive_clint_create(memmap[SIFIVE_E_CLINT].base,
memmap[SIFIVE_E_CLINT].size, ms->smp.cpus,
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
create_unimplemented_device("riscv.sifive.e.aon",
memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size);
sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base);
Expand Down
2 changes: 1 addition & 1 deletion hw/riscv/sifive_u.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
memmap[SIFIVE_U_CLINT].size, ms->smp.cpus,
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);

object_property_set_bool(OBJECT(&s->prci), true, "realized", &err);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base);
Expand Down
9 changes: 6 additions & 3 deletions hw/riscv/spike.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ static void spike_board_init(MachineState *machine)

/* Core Local Interruptor (timer and IPI) */
sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
false);
}

static void spike_v1_10_0_board_init(MachineState *machine)
Expand Down Expand Up @@ -316,7 +317,8 @@ static void spike_v1_10_0_board_init(MachineState *machine)

/* Core Local Interruptor (timer and IPI) */
sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
false);
}

static void spike_v1_09_1_board_init(MachineState *machine)
Expand Down Expand Up @@ -424,7 +426,8 @@ static void spike_v1_09_1_board_init(MachineState *machine)

/* Core Local Interruptor (timer and IPI) */
sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
false);

g_free(config_string);
}
Expand Down
3 changes: 2 additions & 1 deletion hw/riscv/virt.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ static void riscv_virt_board_init(MachineState *machine)
memmap[VIRT_PLIC].size);
sifive_clint_create(memmap[VIRT_CLINT].base,
memmap[VIRT_CLINT].size, smp_cpus,
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true);
sifive_test_create(memmap[VIRT_TEST].base);

for (i = 0; i < VIRTIO_COUNT; i++) {
Expand Down Expand Up @@ -641,6 +641,7 @@ static void riscv_virt_machine_class_init(ObjectClass *oc, void *data)
mc->init = riscv_virt_board_init;
mc->max_cpus = 8;
mc->default_cpu_type = VIRT_CPU;
mc->pci_allow_0_address = true;
}

static const TypeInfo riscv_virt_machine_typeinfo = {
Expand Down
3 changes: 2 additions & 1 deletion include/hw/riscv/sifive_clint.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ typedef struct SiFiveCLINTState {
} SiFiveCLINTState;

DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t num_harts,
uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base);
uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base,
bool provide_rdtime);

enum {
SIFIVE_SIP_BASE = 0x0,
Expand Down
57 changes: 53 additions & 4 deletions target/riscv/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,27 @@ const char * const riscv_excp_names[] = {
"load_page_fault",
"reserved",
"store_page_fault"
"reserved",
"reserved",
"reserved",
"reserved",
"guest_exec_page_fault",
"guest_load_page_fault",
"reserved",
"guest_store_page_fault"
};

const char * const riscv_intr_names[] = {
"u_software",
"s_software",
"h_software",
"vs_software",
"m_software",
"u_timer",
"s_timer",
"h_timer",
"vs_timer",
"m_timer",
"u_external",
"s_external",
"vs_external",
"h_external",
"m_external",
"reserved",
Expand Down Expand Up @@ -220,17 +228,53 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
CPURISCVState *env = &cpu->env;
int i;

#if !defined(CONFIG_USER_ONLY)
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s %d\n", "V = ", riscv_cpu_virt_enabled(env));
}
#endif
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc);
#ifndef CONFIG_USER_ONLY
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
qemu_fprintf(f, " %s 0x%x\n", "mip ", env->mip);
#ifdef TARGET_RISCV32
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", env->mstatush);
#endif
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", env->mtvec);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec ", env->stvec);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec ", env->vstvec);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", env->mepc);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc ", env->sepc);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc ", env->vsepc);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause ", env->mcause);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause ", env->scause);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->sbadaddr);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2);
}
#endif

for (i = 0; i < 32; i++) {
Expand Down Expand Up @@ -409,6 +453,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
if (cpu->cfg.ext_u) {
target_misa |= RVU;
}
if (cpu->cfg.ext_h) {
target_misa |= RVH;
}

set_misa(env, RVXLEN | target_misa);
}
Expand Down Expand Up @@ -444,6 +491,8 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true),
DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
/* This is experimental so mark with 'x-' */
DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
Expand Down
63 changes: 61 additions & 2 deletions target/riscv/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#define RVC RV('C')
#define RVS RV('S')
#define RVU RV('U')
#define RVH RV('H')

/* S extension denotes that Supervisor mode exists, however it is possible
to have a core that support S mode but does not have an MMU and there
Expand Down Expand Up @@ -103,6 +104,7 @@ struct CPURISCVState {
target_ulong frm;

target_ulong badaddr;
target_ulong guest_phys_fault_addr;

target_ulong priv_ver;
target_ulong misa;
Expand All @@ -116,12 +118,19 @@ struct CPURISCVState {

#ifndef CONFIG_USER_ONLY
target_ulong priv;
/* This contains QEMU specific information about the virt state. */
target_ulong virt;
target_ulong resetvec;

target_ulong mhartid;
target_ulong mstatus;

uint32_t mip;
target_ulong mip;

#ifdef TARGET_RISCV32
target_ulong mstatush;
#endif

uint32_t miclaim;

target_ulong mie;
Expand All @@ -142,6 +151,43 @@ struct CPURISCVState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */

/* Hypervisor CSRs */
target_ulong hstatus;
target_ulong hedeleg;
target_ulong hideleg;
target_ulong hcounteren;
target_ulong htval;
target_ulong htinst;
target_ulong hgatp;
uint64_t htimedelta;

/* Virtual CSRs */
target_ulong vsstatus;
target_ulong vstvec;
target_ulong vsscratch;
target_ulong vsepc;
target_ulong vscause;
target_ulong vstval;
target_ulong vsatp;
#ifdef TARGET_RISCV32
target_ulong vsstatush;
#endif

target_ulong mtval2;
target_ulong mtinst;

/* HS Backup CSRs */
target_ulong stvec_hs;
target_ulong sscratch_hs;
target_ulong sepc_hs;
target_ulong scause_hs;
target_ulong stval_hs;
target_ulong satp_hs;
target_ulong mstatus_hs;
#ifdef TARGET_RISCV32
target_ulong mstatush_hs;
#endif

target_ulong scounteren;
target_ulong mcounteren;

Expand All @@ -156,6 +202,9 @@ struct CPURISCVState {
/* physical memory protection */
pmp_table_t pmp_state;

/* machine specific rdtime callback */
uint64_t (*rdtime_fn)(void);

/* True if in debugger mode. */
bool debugger;
#endif
Expand Down Expand Up @@ -213,6 +262,7 @@ typedef struct RISCVCPU {
bool ext_c;
bool ext_s;
bool ext_u;
bool ext_h;
bool ext_counters;
bool ext_ifencei;
bool ext_icsr;
Expand Down Expand Up @@ -247,6 +297,10 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
bool riscv_cpu_fp_enabled(CPURISCVState *env);
bool riscv_cpu_virt_enabled(CPURISCVState *env);
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
Expand All @@ -268,9 +322,11 @@ void riscv_cpu_list(void);
#define cpu_mmu_index riscv_cpu_mmu_index

#ifndef CONFIG_USER_ONLY
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void));
#endif
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);

Expand All @@ -293,7 +349,10 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
#ifdef CONFIG_USER_ONLY
*flags = TB_FLAGS_MSTATUS_FS;
#else
*flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
*flags = cpu_mmu_index(env, 0);
if (riscv_cpu_fp_enabled(env)) {
*flags |= env->mstatus & MSTATUS_FS;
}
#endif
}

Expand Down
Loading

0 comments on commit 2ac031d

Please sign in to comment.