Merge tag 'pull-riscv-to-apply-20220108' of github.com:alistair23/qemu into staging

Second RISC-V PR for QEMU 7.0

 - Fix illegal instruction when PMP is disabled
 - SiFive PDMA 64-bit support
 - SiFive PLIC cleanups
 - Mark Hypervisor extension as non experimental
 - Enable Hypervisor extension by default
 - Support 32 cores on the virt machine
 - Corrections for the Vector extension
 - Experimental support for 128-bit CPUs
 - stval and mtval support for illegal instructions

# gpg: Signature made Fri 07 Jan 2022 09:50:11 PM PST
# gpg:                using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [undefined]
# 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: F6C4 AC46 D493 4868 D3B8  CE8F 21E1 0D29 DF97 7054

* tag 'pull-riscv-to-apply-20220108' of github.com:alistair23/qemu: (37 commits)
  target/riscv: Implement the stval/mtval illegal instruction
  target/riscv: Fixup setting GVA
  target/riscv: Set the opcode in DisasContext
  target/riscv: actual functions to realize crs 128-bit insns
  target/riscv: modification of the trans_csrxx for 128-bit support
  target/riscv: helper functions to wrap calls to 128-bit csr insns
  target/riscv: adding high part of some csrs
  target/riscv: support for 128-bit M extension
  target/riscv: support for 128-bit arithmetic instructions
  target/riscv: support for 128-bit shift instructions
  target/riscv: support for 128-bit U-type instructions
  target/riscv: support for 128-bit bitwise instructions
  target/riscv: accessors to registers upper part and 128-bit load/store
  target/riscv: moving some insns close to similar insns
  target/riscv: setup everything for rv64 to support rv128 execution
  target/riscv: array for the 64 upper bits of 128-bit registers
  target/riscv: separation of bitwise logic and arithmetic helpers
  target/riscv: additional macros to check instruction support
  qemu/int128: addition of div/rem 128-bit operations
  exec/memop: Adding signed quad and octo defines
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2022-01-07 22:09:24 -08:00
81 changed files with 2345 additions and 777 deletions
+15 -15
View File
@@ -1885,9 +1885,9 @@ load_memop(const void *haddr, MemOp op)
return (uint32_t)ldl_be_p(haddr);
case MO_LEUL:
return (uint32_t)ldl_le_p(haddr);
case MO_BEQ:
case MO_BEUQ:
return ldq_be_p(haddr);
case MO_LEQ:
case MO_LEUQ:
return ldq_le_p(haddr);
default:
qemu_build_not_reached();
@@ -2081,16 +2081,16 @@ tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEQ);
return load_helper(env, addr, oi, retaddr, MO_LEQ, false,
validate_memop(oi, MO_LEUQ);
return load_helper(env, addr, oi, retaddr, MO_LEUQ, false,
helper_le_ldq_mmu);
}
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEQ);
return load_helper(env, addr, oi, retaddr, MO_BEQ, false,
validate_memop(oi, MO_BEUQ);
return load_helper(env, addr, oi, retaddr, MO_BEUQ, false,
helper_be_ldq_mmu);
}
@@ -2166,7 +2166,7 @@ uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
MemOpIdx oi, uintptr_t ra)
{
return cpu_load_helper(env, addr, oi, MO_BEQ, helper_be_ldq_mmu);
return cpu_load_helper(env, addr, oi, MO_BEUQ, helper_be_ldq_mmu);
}
uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
@@ -2210,10 +2210,10 @@ store_memop(void *haddr, uint64_t val, MemOp op)
case MO_LEUL:
stl_le_p(haddr, val);
break;
case MO_BEQ:
case MO_BEUQ:
stq_be_p(haddr, val);
break;
case MO_LEQ:
case MO_LEUQ:
stq_le_p(haddr, val);
break;
default:
@@ -2465,15 +2465,15 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_LEQ);
store_helper(env, addr, val, oi, retaddr, MO_LEQ);
validate_memop(oi, MO_LEUQ);
store_helper(env, addr, val, oi, retaddr, MO_LEUQ);
}
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr)
{
validate_memop(oi, MO_BEQ);
store_helper(env, addr, val, oi, retaddr, MO_BEQ);
validate_memop(oi, MO_BEUQ);
store_helper(env, addr, val, oi, retaddr, MO_BEUQ);
}
/*
@@ -2609,11 +2609,11 @@ uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr)
static uint64_t full_ldq_code(CPUArchState *env, target_ulong addr,
MemOpIdx oi, uintptr_t retaddr)
{
return load_helper(env, addr, oi, retaddr, MO_TEQ, true, full_ldq_code);
return load_helper(env, addr, oi, retaddr, MO_TEUQ, true, full_ldq_code);
}
uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
{
MemOpIdx oi = make_memop_idx(MO_TEQ, cpu_mmu_index(env, true));
MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true));
return full_ldq_code(env, addr, oi, 0);
}
+4 -4
View File
@@ -45,7 +45,7 @@ uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
return cpu_ldq_be_mmu(env, addr, oi, ra);
}
@@ -72,7 +72,7 @@ uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
return cpu_ldq_le_mmu(env, addr, oi, ra);
}
@@ -100,7 +100,7 @@ void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
cpu_stq_be_mmu(env, addr, val, oi, ra);
}
@@ -121,7 +121,7 @@ void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
int mmu_idx, uintptr_t ra)
{
MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
cpu_stq_le_mmu(env, addr, val, oi, ra);
}
+4 -4
View File
@@ -294,7 +294,7 @@ uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
void *haddr;
uint64_t ret;
validate_memop(oi, MO_BEQ);
validate_memop(oi, MO_BEUQ);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldq_be_p(haddr);
@@ -339,7 +339,7 @@ uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
void *haddr;
uint64_t ret;
validate_memop(oi, MO_LEQ);
validate_memop(oi, MO_LEUQ);
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
ret = ldq_le_p(haddr);
@@ -392,7 +392,7 @@ void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
{
void *haddr;
validate_memop(oi, MO_BEQ);
validate_memop(oi, MO_BEUQ);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stq_be_p(haddr, val);
@@ -431,7 +431,7 @@ void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
{
void *haddr;
validate_memop(oi, MO_LEQ);
validate_memop(oi, MO_LEUQ);
trace_guest_st_before_exec(env_cpu(env), addr, oi);
haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
stq_le_p(haddr, val);
+5
View File
@@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv64);
}
int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info)
{
return print_insn_riscv(memaddr, info, rv128);
}
+181 -44
View File
@@ -177,6 +177,101 @@ static inline void sifive_pdma_update_irq(SiFivePDMAState *s, int ch)
s->chan[ch].state = DMA_CHAN_STATE_IDLE;
}
static uint64_t sifive_pdma_readq(SiFivePDMAState *s, int ch, hwaddr offset)
{
uint64_t val = 0;
offset &= 0xfff;
switch (offset) {
case DMA_NEXT_BYTES:
val = s->chan[ch].next_bytes;
break;
case DMA_NEXT_DST:
val = s->chan[ch].next_dst;
break;
case DMA_NEXT_SRC:
val = s->chan[ch].next_src;
break;
case DMA_EXEC_BYTES:
val = s->chan[ch].exec_bytes;
break;
case DMA_EXEC_DST:
val = s->chan[ch].exec_dst;
break;
case DMA_EXEC_SRC:
val = s->chan[ch].exec_src;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
return val;
}
static uint32_t sifive_pdma_readl(SiFivePDMAState *s, int ch, hwaddr offset)
{
uint32_t val = 0;
offset &= 0xfff;
switch (offset) {
case DMA_CONTROL:
val = s->chan[ch].control;
break;
case DMA_NEXT_CONFIG:
val = s->chan[ch].next_config;
break;
case DMA_NEXT_BYTES:
val = extract64(s->chan[ch].next_bytes, 0, 32);
break;
case DMA_NEXT_BYTES + 4:
val = extract64(s->chan[ch].next_bytes, 32, 32);
break;
case DMA_NEXT_DST:
val = extract64(s->chan[ch].next_dst, 0, 32);
break;
case DMA_NEXT_DST + 4:
val = extract64(s->chan[ch].next_dst, 32, 32);
break;
case DMA_NEXT_SRC:
val = extract64(s->chan[ch].next_src, 0, 32);
break;
case DMA_NEXT_SRC + 4:
val = extract64(s->chan[ch].next_src, 32, 32);
break;
case DMA_EXEC_CONFIG:
val = s->chan[ch].exec_config;
break;
case DMA_EXEC_BYTES:
val = extract64(s->chan[ch].exec_bytes, 0, 32);
break;
case DMA_EXEC_BYTES + 4:
val = extract64(s->chan[ch].exec_bytes, 32, 32);
break;
case DMA_EXEC_DST:
val = extract64(s->chan[ch].exec_dst, 0, 32);
break;
case DMA_EXEC_DST + 4:
val = extract64(s->chan[ch].exec_dst, 32, 32);
break;
case DMA_EXEC_SRC:
val = extract64(s->chan[ch].exec_src, 0, 32);
break;
case DMA_EXEC_SRC + 4:
val = extract64(s->chan[ch].exec_src, 32, 32);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 32-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
return val;
}
static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size)
{
SiFivePDMAState *s = opaque;
@@ -189,56 +284,53 @@ static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size)
return 0;
}
offset &= 0xfff;
switch (offset) {
case DMA_CONTROL:
val = s->chan[ch].control;
switch (size) {
case 8:
val = sifive_pdma_readq(s, ch, offset);
break;
case DMA_NEXT_CONFIG:
val = s->chan[ch].next_config;
break;
case DMA_NEXT_BYTES:
val = s->chan[ch].next_bytes;
break;
case DMA_NEXT_DST:
val = s->chan[ch].next_dst;
break;
case DMA_NEXT_SRC:
val = s->chan[ch].next_src;
break;
case DMA_EXEC_CONFIG:
val = s->chan[ch].exec_config;
break;
case DMA_EXEC_BYTES:
val = s->chan[ch].exec_bytes;
break;
case DMA_EXEC_DST:
val = s->chan[ch].exec_dst;
break;
case DMA_EXEC_SRC:
val = s->chan[ch].exec_src;
case 4:
val = sifive_pdma_readl(s, ch, offset);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid read size %u to PDMA\n",
__func__, size);
return 0;
}
return val;
}
static void sifive_pdma_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
static void sifive_pdma_writeq(SiFivePDMAState *s, int ch,
hwaddr offset, uint64_t value)
{
SiFivePDMAState *s = opaque;
int ch = SIFIVE_PDMA_CHAN_NO(offset);
bool claimed, run;
if (ch >= SIFIVE_PDMA_CHANS) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
__func__, ch);
return;
offset &= 0xfff;
switch (offset) {
case DMA_NEXT_BYTES:
s->chan[ch].next_bytes = value;
break;
case DMA_NEXT_DST:
s->chan[ch].next_dst = value;
break;
case DMA_NEXT_SRC:
s->chan[ch].next_src = value;
break;
case DMA_EXEC_BYTES:
case DMA_EXEC_DST:
case DMA_EXEC_SRC:
/* these are read-only registers */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
}
static void sifive_pdma_writel(SiFivePDMAState *s, int ch,
hwaddr offset, uint32_t value)
{
bool claimed, run;
offset &= 0xfff;
switch (offset) {
@@ -282,27 +374,68 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
s->chan[ch].next_config = value;
break;
case DMA_NEXT_BYTES:
s->chan[ch].next_bytes = value;
s->chan[ch].next_bytes =
deposit64(s->chan[ch].next_bytes, 0, 32, value);
break;
case DMA_NEXT_BYTES + 4:
s->chan[ch].next_bytes =
deposit64(s->chan[ch].next_bytes, 32, 32, value);
break;
case DMA_NEXT_DST:
s->chan[ch].next_dst = value;
s->chan[ch].next_dst = deposit64(s->chan[ch].next_dst, 0, 32, value);
break;
case DMA_NEXT_DST + 4:
s->chan[ch].next_dst = deposit64(s->chan[ch].next_dst, 32, 32, value);
break;
case DMA_NEXT_SRC:
s->chan[ch].next_src = value;
s->chan[ch].next_src = deposit64(s->chan[ch].next_src, 0, 32, value);
break;
case DMA_NEXT_SRC + 4:
s->chan[ch].next_src = deposit64(s->chan[ch].next_src, 32, 32, value);
break;
case DMA_EXEC_CONFIG:
case DMA_EXEC_BYTES:
case DMA_EXEC_BYTES + 4:
case DMA_EXEC_DST:
case DMA_EXEC_DST + 4:
case DMA_EXEC_SRC:
case DMA_EXEC_SRC + 4:
/* these are read-only registers */
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unexpected 32-bit access to 0x%" HWADDR_PRIX "\n",
__func__, offset);
break;
}
}
static void sifive_pdma_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
SiFivePDMAState *s = opaque;
int ch = SIFIVE_PDMA_CHAN_NO(offset);
if (ch >= SIFIVE_PDMA_CHANS) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
__func__, ch);
return;
}
switch (size) {
case 8:
sifive_pdma_writeq(s, ch, offset, value);
break;
case 4:
sifive_pdma_writel(s, ch, offset, (uint32_t) value);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid write size %u to PDMA\n",
__func__, size);
break;
}
}
static const MemoryRegionOps sifive_pdma_ops = {
.read = sifive_pdma_read,
.write = sifive_pdma_write,
@@ -311,6 +444,10 @@ static const MemoryRegionOps sifive_pdma_ops = {
.impl = {
.min_access_size = 4,
.max_access_size = 8,
},
.valid = {
.min_access_size = 4,
.max_access_size = 8,
}
};
+76 -178
View File
@@ -31,7 +31,10 @@
#include "migration/vmstate.h"
#include "hw/irq.h"
#define RISCV_DEBUG_PLIC 0
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
{
return addr >= base && addr - base < num;
}
static PLICMode char_to_mode(char c)
{
@@ -46,47 +49,6 @@ static PLICMode char_to_mode(char c)
}
}
static char mode_to_char(PLICMode m)
{
switch (m) {
case PLICMode_U: return 'U';
case PLICMode_S: return 'S';
case PLICMode_H: return 'H';
case PLICMode_M: return 'M';
default: return '?';
}
}
static void sifive_plic_print_state(SiFivePLICState *plic)
{
int i;
int addrid;
/* pending */
qemu_log("pending : ");
for (i = plic->bitfield_words - 1; i >= 0; i--) {
qemu_log("%08x", plic->pending[i]);
}
qemu_log("\n");
/* pending */
qemu_log("claimed : ");
for (i = plic->bitfield_words - 1; i >= 0; i--) {
qemu_log("%08x", plic->claimed[i]);
}
qemu_log("\n");
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
qemu_log("hart%d-%c enable: ",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode));
for (i = plic->bitfield_words - 1; i >= 0; i--) {
qemu_log("%08x", plic->enable[addrid * plic->bitfield_words + i]);
}
qemu_log("\n");
}
}
static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value)
{
uint32_t old, new, cmp = qatomic_read(a);
@@ -110,26 +72,34 @@ static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level)
atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level);
}
static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
static uint32_t sifive_plic_claimed(SiFivePLICState *plic, uint32_t addrid)
{
uint32_t max_irq = 0;
uint32_t max_prio = plic->target_priority[addrid];
int i, j;
for (i = 0; i < plic->bitfield_words; i++) {
uint32_t pending_enabled_not_claimed =
(plic->pending[i] & ~plic->claimed[i]) &
plic->enable[addrid * plic->bitfield_words + i];
(plic->pending[i] & ~plic->claimed[i]) &
plic->enable[addrid * plic->bitfield_words + i];
if (!pending_enabled_not_claimed) {
continue;
}
for (j = 0; j < 32; j++) {
int irq = (i << 5) + j;
uint32_t prio = plic->source_priority[irq];
int enabled = pending_enabled_not_claimed & (1 << j);
if (enabled && prio > plic->target_priority[addrid]) {
return 1;
if (enabled && prio > max_prio) {
max_irq = irq;
max_prio = prio;
}
}
}
return 0;
return max_irq;
}
static void sifive_plic_update(SiFivePLICState *plic)
@@ -140,7 +110,7 @@ static void sifive_plic_update(SiFivePLICState *plic)
for (addrid = 0; addrid < plic->num_addrs; addrid++) {
uint32_t hartid = plic->addr_config[addrid].hartid;
PLICMode mode = plic->addr_config[addrid].mode;
int level = sifive_plic_irqs_pending(plic, addrid);
bool level = !!sifive_plic_claimed(plic, addrid);
switch (mode) {
case PLICMode_M:
@@ -153,111 +123,48 @@ static void sifive_plic_update(SiFivePLICState *plic)
break;
}
}
if (RISCV_DEBUG_PLIC) {
sifive_plic_print_state(plic);
}
}
static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid)
{
int i, j;
uint32_t max_irq = 0;
uint32_t max_prio = plic->target_priority[addrid];
for (i = 0; i < plic->bitfield_words; i++) {
uint32_t pending_enabled_not_claimed =
(plic->pending[i] & ~plic->claimed[i]) &
plic->enable[addrid * plic->bitfield_words + i];
if (!pending_enabled_not_claimed) {
continue;
}
for (j = 0; j < 32; j++) {
int irq = (i << 5) + j;
uint32_t prio = plic->source_priority[irq];
int enabled = pending_enabled_not_claimed & (1 << j);
if (enabled && prio > max_prio) {
max_irq = irq;
max_prio = prio;
}
}
}
if (max_irq) {
sifive_plic_set_pending(plic, max_irq, false);
sifive_plic_set_claimed(plic, max_irq, true);
}
return max_irq;
}
static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size)
{
SiFivePLICState *plic = opaque;
/* writes must be 4 byte words */
if ((addr & 0x3) != 0) {
goto err;
}
if (addr >= plic->priority_base && /* 4 bytes per source */
addr < plic->priority_base + (plic->num_sources << 2))
{
if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read priority: irq=%d priority=%d\n",
irq, plic->source_priority[irq]);
}
return plic->source_priority[irq];
} else if (addr >= plic->pending_base && /* 1 bit per source */
addr < plic->pending_base + (plic->num_sources >> 3))
{
} else if (addr_between(addr, plic->pending_base, plic->num_sources >> 3)) {
uint32_t word = (addr - plic->pending_base) >> 2;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read pending: word=%d value=%d\n",
word, plic->pending[word]);
}
return plic->pending[word];
} else if (addr >= plic->enable_base && /* 1 bit per source */
addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
{
} else if (addr_between(addr, plic->enable_base,
plic->num_addrs * plic->enable_stride)) {
uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
if (wordid < plic->bitfield_words) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read enable: hart%d-%c word=%d value=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode), wordid,
plic->enable[addrid * plic->bitfield_words + wordid]);
}
return plic->enable[addrid * plic->bitfield_words + wordid];
}
} else if (addr >= plic->context_base && /* 1 bit per source */
addr < plic->context_base + plic->num_addrs * plic->context_stride)
{
} else if (addr_between(addr, plic->context_base,
plic->num_addrs * plic->context_stride)) {
uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
uint32_t contextid = (addr & (plic->context_stride - 1));
if (contextid == 0) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read priority: hart%d-%c priority=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
plic->target_priority[addrid]);
}
return plic->target_priority[addrid];
} else if (contextid == 4) {
uint32_t value = sifive_plic_claim(plic, addrid);
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: read claim: hart%d-%c irq=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
value);
uint32_t max_irq = sifive_plic_claimed(plic, addrid);
if (max_irq) {
sifive_plic_set_pending(plic, max_irq, false);
sifive_plic_set_claimed(plic, max_irq, true);
}
sifive_plic_update(plic);
return value;
return max_irq;
}
}
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register read 0x%" HWADDR_PRIx "\n",
__func__, addr);
@@ -269,80 +176,53 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value,
{
SiFivePLICState *plic = opaque;
/* writes must be 4 byte words */
if ((addr & 0x3) != 0) {
goto err;
}
if (addr >= plic->priority_base && /* 4 bytes per source */
addr < plic->priority_base + (plic->num_sources << 2))
{
if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) {
uint32_t irq = ((addr - plic->priority_base) >> 2) + 1;
plic->source_priority[irq] = value & 7;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write priority: irq=%d priority=%d\n",
irq, plic->source_priority[irq]);
}
sifive_plic_update(plic);
return;
} else if (addr >= plic->pending_base && /* 1 bit per source */
addr < plic->pending_base + (plic->num_sources >> 3))
{
} else if (addr_between(addr, plic->pending_base,
plic->num_sources >> 3)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid pending write: 0x%" HWADDR_PRIx "",
__func__, addr);
return;
} else if (addr >= plic->enable_base && /* 1 bit per source */
addr < plic->enable_base + plic->num_addrs * plic->enable_stride)
{
} else if (addr_between(addr, plic->enable_base,
plic->num_addrs * plic->enable_stride)) {
uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride;
uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2;
if (wordid < plic->bitfield_words) {
plic->enable[addrid * plic->bitfield_words + wordid] = value;
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write enable: hart%d-%c word=%d value=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode), wordid,
plic->enable[addrid * plic->bitfield_words + wordid]);
}
return;
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid enable write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
} else if (addr >= plic->context_base && /* 4 bytes per reg */
addr < plic->context_base + plic->num_addrs * plic->context_stride)
{
} else if (addr_between(addr, plic->context_base,
plic->num_addrs * plic->context_stride)) {
uint32_t addrid = (addr - plic->context_base) / plic->context_stride;
uint32_t contextid = (addr & (plic->context_stride - 1));
if (contextid == 0) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write priority: hart%d-%c priority=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
plic->target_priority[addrid]);
}
if (value <= plic->num_priorities) {
plic->target_priority[addrid] = value;
sifive_plic_update(plic);
}
return;
} else if (contextid == 4) {
if (RISCV_DEBUG_PLIC) {
qemu_log("plic: write claim: hart%d-%c irq=%x\n",
plic->addr_config[addrid].hartid,
mode_to_char(plic->addr_config[addrid].mode),
(uint32_t)value);
}
if (value < plic->num_sources) {
sifive_plic_set_claimed(plic, value, false);
sifive_plic_update(plic);
}
return;
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid context write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
static const MemoryRegionOps sifive_plic_ops = {
@@ -355,6 +235,23 @@ static const MemoryRegionOps sifive_plic_ops = {
}
};
static void sifive_plic_reset(DeviceState *dev)
{
SiFivePLICState *s = SIFIVE_PLIC(dev);
int i;
memset(s->source_priority, 0, sizeof(uint32_t) * s->num_sources);
memset(s->target_priority, 0, sizeof(uint32_t) * s->num_addrs);
memset(s->pending, 0, sizeof(uint32_t) * s->bitfield_words);
memset(s->claimed, 0, sizeof(uint32_t) * s->bitfield_words);
memset(s->enable, 0, sizeof(uint32_t) * s->num_enables);
for (i = 0; i < s->num_harts; i++) {
qemu_set_irq(s->m_external_irqs[i], 0);
qemu_set_irq(s->s_external_irqs[i], 0);
}
}
/*
* parse PLIC hart/mode address offset config
*
@@ -501,6 +398,7 @@ static void sifive_plic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = sifive_plic_reset;
device_class_set_props(dc, sifive_plic_properties);
dc->realize = sifive_plic_realize;
dc->vmsd = &vmstate_sifive_plic;
+1 -1
View File
@@ -471,7 +471,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc,
TYPE_MICROCHIP_PFSOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* Split RAM into low and high regions using aliases to machine->ram */
mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size;
+1 -1
View File
@@ -80,7 +80,7 @@ static void opentitan_board_init(MachineState *machine)
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc,
TYPE_RISCV_IBEX_SOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
memory_region_add_subregion(sys_mem,
memmap[IBEX_DEV_RAM].base, machine->ram);
+1 -1
View File
@@ -88,7 +88,7 @@ static void sifive_e_machine_init(MachineState *machine)
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
/* Data Tightly Integrated Memory */
memory_region_add_subregion(sys_mem,
+1 -1
View File
@@ -547,7 +547,7 @@ static void sifive_u_machine_init(MachineState *machine)
&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_fatal);
/* register RAM */
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base,
+1
View File
@@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*);
int print_insn_xtensa (bfd_vma, disassemble_info*);
int print_insn_riscv32 (bfd_vma, disassemble_info*);
int print_insn_riscv64 (bfd_vma, disassemble_info*);
int print_insn_riscv128 (bfd_vma, disassemble_info*);
int print_insn_rx(bfd_vma, disassemble_info *);
int print_insn_hexagon(bfd_vma, disassemble_info *);
+11 -4
View File
@@ -85,29 +85,36 @@ typedef enum MemOp {
MO_UB = MO_8,
MO_UW = MO_16,
MO_UL = MO_32,
MO_UQ = MO_64,
MO_UO = MO_128,
MO_SB = MO_SIGN | MO_8,
MO_SW = MO_SIGN | MO_16,
MO_SL = MO_SIGN | MO_32,
MO_Q = MO_64,
MO_SQ = MO_SIGN | MO_64,
MO_SO = MO_SIGN | MO_128,
MO_LEUW = MO_LE | MO_UW,
MO_LEUL = MO_LE | MO_UL,
MO_LEUQ = MO_LE | MO_UQ,
MO_LESW = MO_LE | MO_SW,
MO_LESL = MO_LE | MO_SL,
MO_LEQ = MO_LE | MO_Q,
MO_LESQ = MO_LE | MO_SQ,
MO_BEUW = MO_BE | MO_UW,
MO_BEUL = MO_BE | MO_UL,
MO_BEUQ = MO_BE | MO_UQ,
MO_BESW = MO_BE | MO_SW,
MO_BESL = MO_BE | MO_SL,
MO_BEQ = MO_BE | MO_Q,
MO_BESQ = MO_BE | MO_SQ,
#ifdef NEED_CPU_H
MO_TEUW = MO_TE | MO_UW,
MO_TEUL = MO_TE | MO_UL,
MO_TEUQ = MO_TE | MO_UQ,
MO_TEUO = MO_TE | MO_UO,
MO_TESW = MO_TE | MO_SW,
MO_TESL = MO_TE | MO_SL,
MO_TEQ = MO_TE | MO_Q,
MO_TESQ = MO_TE | MO_SQ,
#endif
MO_SSIZE = MO_SIZE | MO_SIGN,
+1 -1
View File
@@ -24,7 +24,7 @@
#include "hw/block/flash.h"
#include "qom/object.h"
#define VIRT_CPUS_MAX 8
#define VIRT_CPUS_MAX 32
#define VIRT_SOCKETS_MAX 8
#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+27
View File
@@ -172,6 +172,26 @@ static inline Int128 bswap128(Int128 a)
#endif
}
static inline Int128 int128_divu(Int128 a, Int128 b)
{
return (__uint128_t)a / (__uint128_t)b;
}
static inline Int128 int128_remu(Int128 a, Int128 b)
{
return (__uint128_t)a % (__uint128_t)b;
}
static inline Int128 int128_divs(Int128 a, Int128 b)
{
return a / b;
}
static inline Int128 int128_rems(Int128 a, Int128 b)
{
return a % b;
}
#else /* !CONFIG_INT128 */
typedef struct Int128 Int128;
@@ -379,6 +399,11 @@ static inline Int128 bswap128(Int128 a)
return int128_make128(bswap64(a.hi), bswap64(a.lo));
}
Int128 int128_divu(Int128, Int128);
Int128 int128_remu(Int128, Int128);
Int128 int128_divs(Int128, Int128);
Int128 int128_rems(Int128, Int128);
#endif /* CONFIG_INT128 */
static inline void bswap128s(Int128 *s)
@@ -386,4 +411,6 @@ static inline void bswap128s(Int128 *s)
*s = bswap128(*s);
}
#define UINT128_MAX int128_make128(~0LL, ~0LL)
#endif /* INT128_H */
+2 -2
View File
@@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
{
tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ);
tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ);
}
static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
@@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
{
tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ);
tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ);
}
void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More