Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches:
- Add qemu-storage-daemon documentation
- hw/block/nand: Decommission the NAND museum
- vpc: Clean up some buffer abuse
- nfs: fix int overflow in nfs_client_open_qdict
- Several iotests fixes
# gpg: Signature made Fri 18 Dec 2020 12:07:30 GMT
# gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg: issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6
* remotes/kevin/tags/for-upstream:
block/vpc: Use sizeof() instead of HEADER_SIZE for footer size
block/vpc: Pass footer buffers as VHDFooter * instead of uint8_t *
block/vpc: Pad VHDFooter, replace uint8_t[] buffers
block/vpc: Use sizeof() instead of 1024 for dynamic header size
block/vpc: Pad VHDDynDiskHeader, replace uint8_t[] buffers
block/vpc: Make vpc_checksum() take void *
block/vpc: Don't abuse the footer buffer for dynamic header
block/vpc: Don't abuse the footer buffer as BAT sector buffer
block/vpc: Make vpc_open() read the full dynamic header
iotests:172: use _filter_qom_path
iotests: make _filter_qom_path more strict
MAINTAINERS: add Kevin Wolf as storage daemon maintainer
docs: add qemu-storage-daemon(1) man page
docs: generate qemu-storage-daemon-qmp-ref(7) man page
block/nfs: fix int overflow in nfs_client_open_qdict
hw/block/nand: Decommission the NAND museum
iotests/210: Fix reference output
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 4ebe254..293ee86 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -49,7 +49,8 @@
/* exit the current TB from a signal handler. The host registers are
restored in a state compatible with the CPU emulator
*/
-static void cpu_exit_tb_from_sighandler(CPUState *cpu, sigset_t *old_set)
+static void QEMU_NORETURN cpu_exit_tb_from_sighandler(CPUState *cpu,
+ sigset_t *old_set)
{
/* XXX: use siglongjmp ? */
sigprocmask(SIG_SETMASK, old_set, NULL);
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0a918e8..9c700c6 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -512,6 +512,7 @@
case 0x141:
if (bsd_type != target_freebsd)
goto badtrap;
+ /* fallthrough */
case 0x100:
#endif
syscall_nr = env->gregs[1];
diff --git a/configure b/configure
index c228f7c..881af4b 100755
--- a/configure
+++ b/configure
@@ -2023,6 +2023,7 @@
add_to warn_flags -Wnested-externs
add_to warn_flags -Wendif-labels
add_to warn_flags -Wexpansion-to-defined
+add_to warn_flags -Wimplicit-fallthrough=2
nowarn_flags=
add_to nowarn_flags -Wno-initializer-overrides
diff --git a/disas/libvixl/vixl/a64/disasm-a64.cc b/disas/libvixl/vixl/a64/disasm-a64.cc
index 7a58a5c..f34d1d6 100644
--- a/disas/libvixl/vixl/a64/disasm-a64.cc
+++ b/disas/libvixl/vixl/a64/disasm-a64.cc
@@ -2985,6 +2985,10 @@
}
return 3;
}
+ default: {
+ VIXL_UNIMPLEMENTED();
+ return 0;
+ }
}
}
case 'C': { // ICondB - Immediate Conditional Branch.
diff --git a/disas/libvixl/vixl/globals.h b/disas/libvixl/vixl/globals.h
index 61dc9f7..7099aa5 100644
--- a/disas/libvixl/vixl/globals.h
+++ b/disas/libvixl/vixl/globals.h
@@ -108,10 +108,12 @@
#define __has_warning(x) 0
#endif
-// Note: This option is only available for Clang. And will only be enabled for
-// C++11(201103L).
+// Fallthrough annotation for Clang and C++11(201103L).
#if __has_warning("-Wimplicit-fallthrough") && __cplusplus >= 201103L
#define VIXL_FALLTHROUGH() [[clang::fallthrough]] //NOLINT
+// Fallthrough annotation for GCC >= 7.
+#elif __GNUC__ >= 7
+ #define VIXL_FALLTHROUGH() __attribute__((fallthrough))
#else
#define VIXL_FALLTHROUGH() do {} while (0)
#endif
diff --git a/docs/devel/migration.rst b/docs/devel/migration.rst
index 49112bb..ad381b8 100644
--- a/docs/devel/migration.rst
+++ b/docs/devel/migration.rst
@@ -53,22 +53,23 @@
Debugging
=========
-The migration stream can be analyzed thanks to `scripts/analyze_migration.py`.
+The migration stream can be analyzed thanks to `scripts/analyze-migration.py`.
Example usage:
.. code-block:: shell
- $ qemu-system-x86_64
- (qemu) migrate "exec:cat > mig"
- $ ./scripts/analyze_migration.py -f mig
+ $ qemu-system-x86_64 -display none -monitor stdio
+ (qemu) migrate "exec:cat > mig"
+ (qemu) q
+ $ ./scripts/analyze-migration.py -f mig
{
"ram (3)": {
"section sizes": {
"pc.ram": "0x0000000008000000",
...
-See also ``analyze_migration.py -h`` help for more options.
+See also ``analyze-migration.py -h`` help for more options.
Common infrastructure
=====================
diff --git a/docs/user/main.rst b/docs/user/main.rst
index bd99b0f..8dfe232 100644
--- a/docs/user/main.rst
+++ b/docs/user/main.rst
@@ -170,68 +170,81 @@
Other binaries
~~~~~~~~~~~~~~
-user mode (Alpha)
-``qemu-alpha`` TODO.
+- user mode (Alpha)
-user mode (Arm)
-``qemu-armeb`` TODO.
+ * ``qemu-alpha`` TODO.
-user mode (Arm)
-``qemu-arm`` is also capable of running Arm \"Angel\" semihosted ELF
-binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
-configurations), and arm-uclinux bFLT format binaries.
+- user mode (Arm)
-user mode (ColdFire)
-user mode (M68K)
-``qemu-m68k`` is capable of running semihosted binaries using the BDM
-(m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
-coldfire uClinux bFLT format binaries.
+ * ``qemu-armeb`` TODO.
-The binary format is detected automatically.
+ * ``qemu-arm`` is also capable of running Arm \"Angel\" semihosted ELF
+ binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
+ configurations), and arm-uclinux bFLT format binaries.
-user mode (Cris)
-``qemu-cris`` TODO.
+- user mode (ColdFire)
-user mode (i386)
-``qemu-i386`` TODO. ``qemu-x86_64`` TODO.
+- user mode (M68K)
-user mode (Microblaze)
-``qemu-microblaze`` TODO.
+ * ``qemu-m68k`` is capable of running semihosted binaries using the BDM
+ (m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
+ coldfire uClinux bFLT format binaries.
-user mode (MIPS)
-``qemu-mips`` executes 32-bit big endian MIPS binaries (MIPS O32 ABI).
+ The binary format is detected automatically.
-``qemu-mipsel`` executes 32-bit little endian MIPS binaries (MIPS O32
-ABI).
+- user mode (Cris)
-``qemu-mips64`` executes 64-bit big endian MIPS binaries (MIPS N64 ABI).
+ * ``qemu-cris`` TODO.
-``qemu-mips64el`` executes 64-bit little endian MIPS binaries (MIPS N64
-ABI).
+- user mode (i386)
-``qemu-mipsn32`` executes 32-bit big endian MIPS binaries (MIPS N32
-ABI).
+ * ``qemu-i386`` TODO.
+ * ``qemu-x86_64`` TODO.
-``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
-ABI).
+- user mode (Microblaze)
-user mode (NiosII)
-``qemu-nios2`` TODO.
+ * ``qemu-microblaze`` TODO.
-user mode (PowerPC)
-``qemu-ppc64abi32`` TODO. ``qemu-ppc64`` TODO. ``qemu-ppc`` TODO.
+- user mode (MIPS)
-user mode (SH4)
-``qemu-sh4eb`` TODO. ``qemu-sh4`` TODO.
+ * ``qemu-mips`` executes 32-bit big endian MIPS binaries (MIPS O32 ABI).
-user mode (SPARC)
-``qemu-sparc`` can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).
+ * ``qemu-mipsel`` executes 32-bit little endian MIPS binaries (MIPS O32 ABI).
-``qemu-sparc32plus`` can execute Sparc32 and SPARC32PLUS binaries
-(Sparc64 CPU, 32 bit ABI).
+ * ``qemu-mips64`` executes 64-bit big endian MIPS binaries (MIPS N64 ABI).
-``qemu-sparc64`` can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
-SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
+ * ``qemu-mips64el`` executes 64-bit little endian MIPS binaries (MIPS N64
+ ABI).
+
+ * ``qemu-mipsn32`` executes 32-bit big endian MIPS binaries (MIPS N32 ABI).
+
+ * ``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
+ ABI).
+
+- user mode (NiosII)
+
+ * ``qemu-nios2`` TODO.
+
+- user mode (PowerPC)
+
+ * ``qemu-ppc64abi32`` TODO.
+ * ``qemu-ppc64`` TODO.
+ * ``qemu-ppc`` TODO.
+
+- user mode (SH4)
+
+ * ``qemu-sh4eb`` TODO.
+ * ``qemu-sh4`` TODO.
+
+- user mode (SPARC)
+
+ * ``qemu-sparc`` can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).
+
+ * ``qemu-sparc32plus`` can execute Sparc32 and SPARC32PLUS binaries
+ (Sparc64 CPU, 32 bit ABI).
+
+ * ``qemu-sparc64`` can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
+ SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
BSD User space emulator
-----------------------
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 470a420..73e0832 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -40,7 +40,7 @@
ERST
{
- .name = "q|quit",
+ .name = "quit|q",
.args_type = "",
.params = "",
.help = "quit the emulator",
@@ -49,7 +49,7 @@
},
SRST
-``q`` or ``quit``
+``quit`` or ``q``
Quit the emulator.
ERST
@@ -401,7 +401,7 @@
ERST
{
- .name = "c|cont",
+ .name = "cont|c",
.args_type = "",
.params = "",
.help = "resume emulation",
@@ -409,7 +409,7 @@
},
SRST
-``c`` or ``cont``
+``cont`` or ``c``
Resume emulation.
ERST
@@ -554,7 +554,7 @@
ERST
{
- .name = "p|print",
+ .name = "print|p",
.args_type = "fmt:/,val:l",
.params = "/fmt expr",
.help = "print expression value (use $reg for CPU register access)",
@@ -562,7 +562,7 @@
},
SRST
-``p`` or ``print/``\ *fmt* *expr*
+``print`` or ``p/``\ *fmt* *expr*
Print expression value. Only the *format* part of *fmt* is
used.
ERST
diff --git a/hw/core/register.c b/hw/core/register.c
index 3600ef5..d6f8c20 100644
--- a/hw/core/register.c
+++ b/hw/core/register.c
@@ -80,7 +80,7 @@
if (!ac || !ac->name) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
- "(written value: %#" PRIx64 ")\n", prefix, val);
+ "(written value: 0x%" PRIx64 ")\n", prefix, val);
return;
}
@@ -89,14 +89,14 @@
test = (old_val ^ val) & ac->rsvd;
if (test) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
- "fields: %#" PRIx64 ")\n", prefix, test);
+ "fields: 0x%" PRIx64 ")\n", prefix, test);
}
test = val & ac->unimp;
if (test) {
qemu_log_mask(LOG_UNIMP,
- "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
- " %#" PRIx64 "\n",
+ "%s:%s writing 0x%" PRIx64 " to unimplemented bits:" \
+ " 0x%" PRIx64 "\n",
prefix, reg->access->name, val, ac->unimp);
}
@@ -112,7 +112,7 @@
}
if (debug) {
- qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
+ qemu_log("%s:%s: write of value 0x%" PRIx64 "\n", prefix, ac->name,
new_val);
}
@@ -150,7 +150,7 @@
}
if (debug) {
- qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
+ qemu_log("%s:%s: read of value 0x%" PRIx64 "\n", prefix,
ac->name, ret);
}
@@ -193,7 +193,7 @@
if (!reg) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
- "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
+ "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
return;
}
@@ -222,7 +222,7 @@
if (!reg) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \
- "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
+ "at address: 0x%" PRIx64 "\n", reg_array->prefix, addr);
return 0;
}
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 187eb05..d040a5d 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -478,9 +478,11 @@
kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, true);
reg64 = c->icc_apr[GICV3_G0][2];
kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, true);
+ /* fall through */
case 6:
reg64 = c->icc_apr[GICV3_G0][1];
kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
+ /* fall through */
default:
reg64 = c->icc_apr[GICV3_G0][0];
kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, true);
@@ -492,9 +494,11 @@
kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, true);
reg64 = c->icc_apr[GICV3_G1NS][2];
kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
+ /* fall through */
case 6:
reg64 = c->icc_apr[GICV3_G1NS][1];
kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
+ /* fall through */
default:
reg64 = c->icc_apr[GICV3_G1NS][0];
kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, true);
@@ -631,9 +635,11 @@
c->icc_apr[GICV3_G0][3] = reg64;
kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, false);
c->icc_apr[GICV3_G0][2] = reg64;
+ /* fall through */
case 6:
kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, false);
c->icc_apr[GICV3_G0][1] = reg64;
+ /* fall through */
default:
kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, false);
c->icc_apr[GICV3_G0][0] = reg64;
@@ -645,9 +651,11 @@
c->icc_apr[GICV3_G1NS][3] = reg64;
kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, false);
c->icc_apr[GICV3_G1NS][2] = reg64;
+ /* fall through */
case 6:
kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, false);
c->icc_apr[GICV3_G1NS][1] = reg64;
+ /* fall through */
default:
kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, false);
c->icc_apr[GICV3_G1NS][0] = reg64;
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
index 341c9db..c1b72fc 100644
--- a/hw/intc/ibex_plic.c
+++ b/hw/intc/ibex_plic.c
@@ -43,16 +43,23 @@
{
int pending_num = irq / 32;
+ if (!level) {
+ /*
+ * If the level is low make sure we clear the hidden_pending.
+ */
+ s->hidden_pending[pending_num] &= ~(1 << (irq % 32));
+ }
+
if (s->claimed[pending_num] & 1 << (irq % 32)) {
/*
* The interrupt has been claimed, but not completed.
* The pending bit can't be set.
+ * Save the pending level for after the interrupt is completed.
*/
s->hidden_pending[pending_num] |= level << (irq % 32);
- return;
+ } else {
+ s->pending[pending_num] |= level << (irq % 32);
}
-
- s->pending[pending_num] |= level << (irq % 32);
}
static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index d62f3dc..83586ae 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -33,24 +33,16 @@
#include <libfdt.h>
-#if defined(TARGET_RISCV32)
-#define fw_dynamic_info_data(__val) cpu_to_le32(__val)
-#else
-#define fw_dynamic_info_data(__val) cpu_to_le64(__val)
-#endif
-
-bool riscv_is_32_bit(MachineState *machine)
+bool riscv_is_32bit(RISCVHartArrayState harts)
{
- if (!strncmp(machine->cpu_type, "rv32", 4)) {
- return true;
- } else {
- return false;
- }
+ RISCVCPU hart = harts.harts[0];
+
+ return riscv_cpu_is_32bit(&hart.env);
}
-target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
+target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState harts,
target_ulong firmware_end_addr) {
- if (riscv_is_32_bit(machine)) {
+ if (riscv_is_32bit(harts)) {
return QEMU_ALIGN_UP(firmware_end_addr, 4 * MiB);
} else {
return QEMU_ALIGN_UP(firmware_end_addr, 2 * MiB);
@@ -218,16 +210,24 @@
return fdt_addr;
}
-void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
- uint32_t reset_vec_size, uint64_t kernel_entry)
+void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+ hwaddr rom_size, uint32_t reset_vec_size,
+ uint64_t kernel_entry)
{
struct fw_dynamic_info dinfo;
size_t dinfo_len;
- dinfo.magic = fw_dynamic_info_data(FW_DYNAMIC_INFO_MAGIC_VALUE);
- dinfo.version = fw_dynamic_info_data(FW_DYNAMIC_INFO_VERSION);
- dinfo.next_mode = fw_dynamic_info_data(FW_DYNAMIC_INFO_NEXT_MODE_S);
- dinfo.next_addr = fw_dynamic_info_data(kernel_entry);
+ if (sizeof(dinfo.magic) == 4) {
+ dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+ dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+ dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+ dinfo.next_addr = cpu_to_le32(kernel_entry);
+ } else {
+ dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
+ dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
+ dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
+ dinfo.next_addr = cpu_to_le64(kernel_entry);
+ }
dinfo.options = 0;
dinfo.boot_hart = 0;
dinfo_len = sizeof(dinfo);
@@ -247,28 +247,25 @@
&address_space_memory);
}
-void riscv_setup_rom_reset_vec(hwaddr start_addr, hwaddr rom_base,
- hwaddr rom_size, uint64_t kernel_entry,
+void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState harts,
+ hwaddr start_addr,
+ hwaddr rom_base, hwaddr rom_size,
+ uint64_t kernel_entry,
uint32_t fdt_load_addr, void *fdt)
{
int i;
uint32_t start_addr_hi32 = 0x00000000;
- #if defined(TARGET_RISCV64)
- start_addr_hi32 = start_addr >> 32;
- #endif
+ if (!riscv_is_32bit(harts)) {
+ start_addr_hi32 = start_addr >> 32;
+ }
/* reset vector */
uint32_t reset_vec[10] = {
0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
0x02828613, /* addi a2, t0, %pcrel_lo(1b) */
0xf1402573, /* csrr a0, mhartid */
-#if defined(TARGET_RISCV32)
- 0x0202a583, /* lw a1, 32(t0) */
- 0x0182a283, /* lw t0, 24(t0) */
-#elif defined(TARGET_RISCV64)
- 0x0202b583, /* ld a1, 32(t0) */
- 0x0182b283, /* ld t0, 24(t0) */
-#endif
+ 0,
+ 0,
0x00028067, /* jr t0 */
start_addr, /* start: .dword */
start_addr_hi32,
@@ -276,6 +273,13 @@
0x00000000,
/* fw_dyn: */
};
+ if (riscv_is_32bit(harts)) {
+ reset_vec[3] = 0x0202a583; /* lw a1, 32(t0) */
+ reset_vec[4] = 0x0182a283; /* lw t0, 24(t0) */
+ } else {
+ reset_vec[3] = 0x0202b583; /* ld a1, 32(t0) */
+ reset_vec[4] = 0x0182b283; /* ld t0, 24(t0) */
+ }
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
@@ -283,7 +287,7 @@
}
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
rom_base, &address_space_memory);
- riscv_rom_copy_firmware_info(rom_base, rom_size, sizeof(reset_vec),
+ riscv_rom_copy_firmware_info(machine, rom_base, rom_size, sizeof(reset_vec),
kernel_entry);
return;
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 37ac46a..e952b49 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -113,6 +113,8 @@
[MICROCHIP_PFSOC_MMUART2] = { 0x20102000, 0x1000 },
[MICROCHIP_PFSOC_MMUART3] = { 0x20104000, 0x1000 },
[MICROCHIP_PFSOC_MMUART4] = { 0x20106000, 0x1000 },
+ [MICROCHIP_PFSOC_SPI0] = { 0x20108000, 0x1000 },
+ [MICROCHIP_PFSOC_SPI1] = { 0x20109000, 0x1000 },
[MICROCHIP_PFSOC_I2C1] = { 0x2010b000, 0x1000 },
[MICROCHIP_PFSOC_GEM0] = { 0x20110000, 0x2000 },
[MICROCHIP_PFSOC_GEM1] = { 0x20112000, 0x2000 },
@@ -121,6 +123,7 @@
[MICROCHIP_PFSOC_GPIO2] = { 0x20122000, 0x1000 },
[MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 },
[MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 },
+ [MICROCHIP_PFSOC_QSPI_XIP] = { 0x21000000, 0x1000000 },
[MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 },
[MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 },
[MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 },
@@ -185,6 +188,7 @@
MemoryRegion *e51_dtim_mem = g_new(MemoryRegion, 1);
MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
MemoryRegion *envm_data = g_new(MemoryRegion, 1);
+ MemoryRegion *qspi_xip_mem = g_new(MemoryRegion, 1);
char *plic_hart_config;
size_t plic_hart_config_len;
NICInfo *nd;
@@ -344,6 +348,14 @@
qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART4_IRQ),
serial_hd(4));
+ /* SPI */
+ create_unimplemented_device("microchip.pfsoc.spi0",
+ memmap[MICROCHIP_PFSOC_SPI0].base,
+ memmap[MICROCHIP_PFSOC_SPI0].size);
+ create_unimplemented_device("microchip.pfsoc.spi1",
+ memmap[MICROCHIP_PFSOC_SPI1].base,
+ memmap[MICROCHIP_PFSOC_SPI1].size);
+
/* I2C1 */
create_unimplemented_device("microchip.pfsoc.i2c1",
memmap[MICROCHIP_PFSOC_I2C1].base,
@@ -401,6 +413,15 @@
sysbus_realize(SYS_BUS_DEVICE(&s->ioscb), errp);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0,
memmap[MICROCHIP_PFSOC_IOSCB].base);
+
+ /* QSPI Flash */
+ memory_region_init_rom(qspi_xip_mem, OBJECT(dev),
+ "microchip.pfsoc.qspi_xip",
+ memmap[MICROCHIP_PFSOC_QSPI_XIP].size,
+ &error_fatal);
+ memory_region_add_subregion(system_memory,
+ memmap[MICROCHIP_PFSOC_QSPI_XIP].base,
+ qspi_xip_mem);
}
static void microchip_pfsoc_soc_class_init(ObjectClass *oc, void *data)
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index cc758b7..af34569 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -35,22 +35,33 @@
[IBEX_DEV_ROM] = { 0x00008000, 16 * KiB },
[IBEX_DEV_RAM] = { 0x10000000, 0x10000 },
[IBEX_DEV_FLASH] = { 0x20000000, 0x80000 },
- [IBEX_DEV_UART] = { 0x40000000, 0x10000 },
- [IBEX_DEV_GPIO] = { 0x40010000, 0x10000 },
- [IBEX_DEV_SPI] = { 0x40020000, 0x10000 },
- [IBEX_DEV_FLASH_CTRL] = { 0x40030000, 0x10000 },
- [IBEX_DEV_PINMUX] = { 0x40070000, 0x10000 },
- [IBEX_DEV_RV_TIMER] = { 0x40080000, 0x10000 },
- [IBEX_DEV_PLIC] = { 0x40090000, 0x10000 },
- [IBEX_DEV_PWRMGR] = { 0x400A0000, 0x10000 },
- [IBEX_DEV_RSTMGR] = { 0x400B0000, 0x10000 },
- [IBEX_DEV_CLKMGR] = { 0x400C0000, 0x10000 },
- [IBEX_DEV_AES] = { 0x40110000, 0x10000 },
- [IBEX_DEV_HMAC] = { 0x40120000, 0x10000 },
- [IBEX_DEV_ALERT_HANDLER] = { 0x40130000, 0x10000 },
- [IBEX_DEV_NMI_GEN] = { 0x40140000, 0x10000 },
- [IBEX_DEV_USBDEV] = { 0x40150000, 0x10000 },
- [IBEX_DEV_PADCTRL] = { 0x40160000, 0x10000 }
+ [IBEX_DEV_UART] = { 0x40000000, 0x1000 },
+ [IBEX_DEV_GPIO] = { 0x40040000, 0x1000 },
+ [IBEX_DEV_SPI] = { 0x40050000, 0x1000 },
+ [IBEX_DEV_I2C] = { 0x40080000, 0x1000 },
+ [IBEX_DEV_PATTGEN] = { 0x400e0000, 0x1000 },
+ [IBEX_DEV_RV_TIMER] = { 0x40100000, 0x1000 },
+ [IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
+ [IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
+ [IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
+ [IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
+ [IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
+ [IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
+ [IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 },
+ [IBEX_DEV_USBDEV] = { 0x40500000, 0x1000 },
+ [IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 },
+ [IBEX_DEV_PLIC] = { 0x41010000, 0x1000 },
+ [IBEX_DEV_AES] = { 0x41100000, 0x1000 },
+ [IBEX_DEV_HMAC] = { 0x41110000, 0x1000 },
+ [IBEX_DEV_KMAC] = { 0x41120000, 0x1000 },
+ [IBEX_DEV_KEYMGR] = { 0x41130000, 0x1000 },
+ [IBEX_DEV_CSRNG] = { 0x41150000, 0x1000 },
+ [IBEX_DEV_ENTROPY] = { 0x41160000, 0x1000 },
+ [IBEX_DEV_EDNO] = { 0x41170000, 0x1000 },
+ [IBEX_DEV_EDN1] = { 0x41180000, 0x1000 },
+ [IBEX_DEV_ALERT_HANDLER] = { 0x411b0000, 0x1000 },
+ [IBEX_DEV_NMI_GEN] = { 0x411c0000, 0x1000 },
+ [IBEX_DEV_OTBN] = { 0x411d0000, 0x10000 },
};
static void opentitan_board_init(MachineState *machine)
@@ -156,30 +167,52 @@
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi",
memmap[IBEX_DEV_SPI].base, memmap[IBEX_DEV_SPI].size);
- create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl",
- memmap[IBEX_DEV_FLASH_CTRL].base, memmap[IBEX_DEV_FLASH_CTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.i2c",
+ memmap[IBEX_DEV_I2C].base, memmap[IBEX_DEV_I2C].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.pattgen",
+ memmap[IBEX_DEV_PATTGEN].base, memmap[IBEX_DEV_PATTGEN].size);
create_unimplemented_device("riscv.lowrisc.ibex.rv_timer",
memmap[IBEX_DEV_RV_TIMER].base, memmap[IBEX_DEV_RV_TIMER].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.sensor_ctrl",
+ memmap[IBEX_DEV_SENSOR_CTRL].base, memmap[IBEX_DEV_SENSOR_CTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.otp_ctrl",
+ memmap[IBEX_DEV_OTP_CTRL].base, memmap[IBEX_DEV_OTP_CTRL].size);
create_unimplemented_device("riscv.lowrisc.ibex.pwrmgr",
memmap[IBEX_DEV_PWRMGR].base, memmap[IBEX_DEV_PWRMGR].size);
create_unimplemented_device("riscv.lowrisc.ibex.rstmgr",
memmap[IBEX_DEV_RSTMGR].base, memmap[IBEX_DEV_RSTMGR].size);
create_unimplemented_device("riscv.lowrisc.ibex.clkmgr",
memmap[IBEX_DEV_CLKMGR].base, memmap[IBEX_DEV_CLKMGR].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
+ memmap[IBEX_DEV_PINMUX].base, memmap[IBEX_DEV_PINMUX].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.padctrl",
+ memmap[IBEX_DEV_PADCTRL].base, memmap[IBEX_DEV_PADCTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.usbdev",
+ memmap[IBEX_DEV_USBDEV].base, memmap[IBEX_DEV_USBDEV].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.flash_ctrl",
+ memmap[IBEX_DEV_FLASH_CTRL].base, memmap[IBEX_DEV_FLASH_CTRL].size);
create_unimplemented_device("riscv.lowrisc.ibex.aes",
memmap[IBEX_DEV_AES].base, memmap[IBEX_DEV_AES].size);
create_unimplemented_device("riscv.lowrisc.ibex.hmac",
memmap[IBEX_DEV_HMAC].base, memmap[IBEX_DEV_HMAC].size);
- create_unimplemented_device("riscv.lowrisc.ibex.pinmux",
- memmap[IBEX_DEV_PINMUX].base, memmap[IBEX_DEV_PINMUX].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.kmac",
+ memmap[IBEX_DEV_KMAC].base, memmap[IBEX_DEV_KMAC].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.keymgr",
+ memmap[IBEX_DEV_KEYMGR].base, memmap[IBEX_DEV_KEYMGR].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.csrng",
+ memmap[IBEX_DEV_CSRNG].base, memmap[IBEX_DEV_CSRNG].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.entropy",
+ memmap[IBEX_DEV_ENTROPY].base, memmap[IBEX_DEV_ENTROPY].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.edn0",
+ memmap[IBEX_DEV_EDNO].base, memmap[IBEX_DEV_EDNO].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.edn1",
+ memmap[IBEX_DEV_EDN1].base, memmap[IBEX_DEV_EDN1].size);
create_unimplemented_device("riscv.lowrisc.ibex.alert_handler",
memmap[IBEX_DEV_ALERT_HANDLER].base, memmap[IBEX_DEV_ALERT_HANDLER].size);
create_unimplemented_device("riscv.lowrisc.ibex.nmi_gen",
memmap[IBEX_DEV_NMI_GEN].base, memmap[IBEX_DEV_NMI_GEN].size);
- create_unimplemented_device("riscv.lowrisc.ibex.usbdev",
- memmap[IBEX_DEV_USBDEV].base, memmap[IBEX_DEV_USBDEV].size);
- create_unimplemented_device("riscv.lowrisc.ibex.padctrl",
- memmap[IBEX_DEV_PADCTRL].base, memmap[IBEX_DEV_PADCTRL].size);
+ create_unimplemented_device("riscv.lowrisc.ibex.otbn",
+ memmap[IBEX_DEV_OTBN].base, memmap[IBEX_DEV_OTBN].size);
}
static void lowrisc_ibex_soc_class_init(ObjectClass *oc, void *data)
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index e7f6dc5..f5c400d 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -60,12 +60,6 @@
#include <libfdt.h>
-#if defined(TARGET_RISCV32)
-# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin"
-#else
-# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin"
-#endif
-
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -93,7 +87,7 @@
#define GEM_REVISION 0x10070109
static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
- uint64_t mem_size, const char *cmdline)
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
{
MachineState *ms = MACHINE(qdev_get_machine());
void *fdt;
@@ -176,11 +170,11 @@
qemu_fdt_add_subnode(fdt, nodename);
/* cpu 0 is the management hart that does not have mmu */
if (cpu != 0) {
-#if defined(TARGET_RISCV32)
- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
-#else
- qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
-#endif
+ if (is_32_bit) {
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
+ } else {
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
+ }
isa = riscv_isa_string(&s->soc.u_cpus.harts[cpu - 1]);
} else {
isa = riscv_isa_string(&s->soc.e_cpus.harts[0]);
@@ -386,6 +380,21 @@
g_free(nodename);
nodename = g_strdup_printf("/soc/serial@%lx",
+ (long)memmap[SIFIVE_U_DEV_UART1].base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0");
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
+ 0x0, memmap[SIFIVE_U_DEV_UART1].base,
+ 0x0, memmap[SIFIVE_U_DEV_UART1].size);
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
+ prci_phandle, PRCI_CLK_TLCLK);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_UART1_IRQ);
+
+ qemu_fdt_setprop_string(fdt, "/aliases", "serial1", nodename);
+ g_free(nodename);
+
+ nodename = g_strdup_printf("/soc/serial@%lx",
(long)memmap[SIFIVE_U_DEV_UART0].base);
qemu_fdt_add_subnode(fdt, nodename);
qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0");
@@ -456,7 +465,8 @@
qemu_allocate_irq(sifive_u_machine_reset, NULL, 0));
/* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(s->soc.u_cpus));
if (s->start_in_flash) {
/*
@@ -485,11 +495,18 @@
break;
}
- firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- start_addr, NULL);
+ if (riscv_is_32bit(s->soc.u_cpus)) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv32-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv64-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ }
if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ kernel_start_addr = riscv_calc_kernel_start_addr(s->soc.u_cpus,
firmware_end_addr);
kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -516,9 +533,9 @@
/* Compute the fdt load address in dram */
fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DEV_DRAM].base,
machine->ram_size, s->fdt);
- #if defined(TARGET_RISCV64)
- start_addr_hi32 = start_addr >> 32;
- #endif
+ if (!riscv_is_32bit(s->soc.u_cpus)) {
+ start_addr_hi32 = (uint64_t)start_addr >> 32;
+ }
/* reset vector */
uint32_t reset_vec[11] = {
@@ -526,13 +543,8 @@
0x00000297, /* 1: auipc t0, %pcrel_hi(fw_dyn) */
0x02828613, /* addi a2, t0, %pcrel_lo(1b) */
0xf1402573, /* csrr a0, mhartid */
-#if defined(TARGET_RISCV32)
- 0x0202a583, /* lw a1, 32(t0) */
- 0x0182a283, /* lw t0, 24(t0) */
-#elif defined(TARGET_RISCV64)
- 0x0202b583, /* ld a1, 32(t0) */
- 0x0182b283, /* ld t0, 24(t0) */
-#endif
+ 0,
+ 0,
0x00028067, /* jr t0 */
start_addr, /* start: .dword */
start_addr_hi32,
@@ -540,6 +552,14 @@
0x00000000,
/* fw_dyn: */
};
+ if (riscv_is_32bit(s->soc.u_cpus)) {
+ reset_vec[4] = 0x0202a583; /* lw a1, 32(t0) */
+ reset_vec[5] = 0x0182a283; /* lw t0, 24(t0) */
+ } else {
+ reset_vec[4] = 0x0202b583; /* ld a1, 32(t0) */
+ reset_vec[5] = 0x0182b283; /* ld t0, 24(t0) */
+ }
+
/* copy in the reset vector in little_endian byte order */
for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
@@ -548,7 +568,7 @@
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
memmap[SIFIVE_U_DEV_MROM].base, &address_space_memory);
- riscv_rom_copy_firmware_info(memmap[SIFIVE_U_DEV_MROM].base,
+ riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
memmap[SIFIVE_U_DEV_MROM].size,
sizeof(reset_vec), kernel_entry);
}
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index facac6e..e723ca0 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -43,17 +43,6 @@
#include "sysemu/qtest.h"
#include "sysemu/sysemu.h"
-/*
- * Not like other RISC-V machines that use plain binary bios images,
- * keeping ELF files here was intentional because BIN files don't work
- * for the Spike machine as HTIF emulation depends on ELF parsing.
- */
-#if defined(TARGET_RISCV32)
-# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.elf"
-#else
-# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.elf"
-#endif
-
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -64,7 +53,7 @@
};
static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
- uint64_t mem_size, const char *cmdline)
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
{
void *fdt;
uint64_t addr, size;
@@ -115,11 +104,11 @@
cpu_name = g_strdup_printf("/cpus/cpu@%d",
s->soc[socket].hartid_base + cpu);
qemu_fdt_add_subnode(fdt, cpu_name);
-#if defined(TARGET_RISCV32)
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
-#else
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
-#endif
+ if (is_32_bit) {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
+ } else {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
+ }
name = riscv_isa_string(&s->soc[socket].harts[cpu]);
qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
g_free(name);
@@ -254,7 +243,8 @@
main_mem);
/* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(s->soc[0]));
/* boot rom */
memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
@@ -262,12 +252,25 @@
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
- firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- memmap[SPIKE_DRAM].base,
- htif_symbol_callback);
+ /*
+ * Not like other RISC-V machines that use plain binary bios images,
+ * keeping ELF files here was intentional because BIN files don't work
+ * for the Spike machine as HTIF emulation depends on ELF parsing.
+ */
+ if (riscv_is_32bit(s->soc[0])) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv32-generic-fw_dynamic.elf",
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv64-generic-fw_dynamic.elf",
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
+ }
if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ kernel_start_addr = riscv_calc_kernel_start_addr(s->soc[0],
firmware_end_addr);
kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -296,7 +299,8 @@
fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base,
machine->ram_size, s->fdt);
/* load the reset vector */
- riscv_setup_rom_reset_vec(memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base,
+ riscv_setup_rom_reset_vec(machine, s->soc[0], memmap[SPIKE_DRAM].base,
+ memmap[SPIKE_MROM].base,
memmap[SPIKE_MROM].size, kernel_entry,
fdt_load_addr, s->fdt);
@@ -317,7 +321,7 @@
mc->init = spike_board_init;
mc->max_cpus = SPIKE_CPUS_MAX;
mc->is_default = true;
- mc->default_cpu_type = SPIKE_V1_10_0_CPU;
+ mc->default_cpu_type = TYPE_RISCV_CPU_BASE;
mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids;
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 3cc18a7..8de4c35 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -43,12 +43,6 @@
#include "hw/pci/pci.h"
#include "hw/pci-host/gpex.h"
-#if defined(TARGET_RISCV32)
-# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin"
-#else
-# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin"
-#endif
-
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -177,7 +171,7 @@
}
static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
- uint64_t mem_size, const char *cmdline)
+ uint64_t mem_size, const char *cmdline, bool is_32_bit)
{
void *fdt;
int i, cpu, socket;
@@ -240,11 +234,11 @@
cpu_name = g_strdup_printf("/cpus/cpu@%d",
s->soc[socket].hartid_base + cpu);
qemu_fdt_add_subnode(fdt, cpu_name);
-#if defined(TARGET_RISCV32)
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
-#else
- qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
-#endif
+ if (is_32_bit) {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv32");
+ } else {
+ qemu_fdt_setprop_string(fdt, cpu_name, "mmu-type", "riscv,sv48");
+ }
name = riscv_isa_string(&s->soc[socket].harts[cpu]);
qemu_fdt_setprop_string(fdt, cpu_name, "riscv,isa", name);
g_free(name);
@@ -606,7 +600,8 @@
main_mem);
/* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(s->soc[0]));
/* boot rom */
memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
@@ -614,11 +609,18 @@
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
- firmware_end_addr = riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- start_addr, NULL);
+ if (riscv_is_32bit(s->soc[0])) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv32-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ "opensbi-riscv64-generic-fw_dynamic.bin",
+ start_addr, NULL);
+ }
if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(machine,
+ kernel_start_addr = riscv_calc_kernel_start_addr(s->soc[0],
firmware_end_addr);
kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -654,7 +656,8 @@
fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
machine->ram_size, s->fdt);
/* load the reset vector */
- riscv_setup_rom_reset_vec(start_addr, virt_memmap[VIRT_MROM].base,
+ riscv_setup_rom_reset_vec(machine, s->soc[0], start_addr,
+ virt_memmap[VIRT_MROM].base,
virt_memmap[VIRT_MROM].size, kernel_entry,
fdt_load_addr, s->fdt);
@@ -704,7 +707,7 @@
mc->desc = "RISC-V VirtIO board";
mc->init = virt_machine_init;
mc->max_cpus = VIRT_CPUS_MAX;
- mc->default_cpu_type = VIRT_CPU;
+ mc->default_cpu_type = TYPE_RISCV_CPU_BASE;
mc->pci_allow_0_address = true;
mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids;
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c
index f838913..006d75e 100644
--- a/hw/rtc/twl92230.c
+++ b/hw/rtc/twl92230.c
@@ -271,37 +271,23 @@
static uint8_t menelaus_read(void *opaque, uint8_t addr)
{
MenelausState *s = (MenelausState *) opaque;
- int reg = 0;
switch (addr) {
case MENELAUS_REV:
return 0x22;
- case MENELAUS_VCORE_CTRL5: reg ++;
- case MENELAUS_VCORE_CTRL4: reg ++;
- case MENELAUS_VCORE_CTRL3: reg ++;
- case MENELAUS_VCORE_CTRL2: reg ++;
- case MENELAUS_VCORE_CTRL1:
- return s->vcore[reg];
+ case MENELAUS_VCORE_CTRL1 ... MENELAUS_VCORE_CTRL5:
+ return s->vcore[addr - MENELAUS_VCORE_CTRL1];
- case MENELAUS_DCDC_CTRL3: reg ++;
- case MENELAUS_DCDC_CTRL2: reg ++;
- case MENELAUS_DCDC_CTRL1:
- return s->dcdc[reg];
+ case MENELAUS_DCDC_CTRL1 ... MENELAUS_DCDC_CTRL3:
+ return s->dcdc[addr - MENELAUS_DCDC_CTRL1];
- case MENELAUS_LDO_CTRL8: reg ++;
- case MENELAUS_LDO_CTRL7: reg ++;
- case MENELAUS_LDO_CTRL6: reg ++;
- case MENELAUS_LDO_CTRL5: reg ++;
- case MENELAUS_LDO_CTRL4: reg ++;
- case MENELAUS_LDO_CTRL3: reg ++;
- case MENELAUS_LDO_CTRL2: reg ++;
- case MENELAUS_LDO_CTRL1:
- return s->ldo[reg];
+ case MENELAUS_LDO_CTRL1 ... MENELAUS_LDO_CTRL8:
+ return s->ldo[addr - MENELAUS_LDO_CTRL1];
- case MENELAUS_SLEEP_CTRL2: reg ++;
case MENELAUS_SLEEP_CTRL1:
- return s->sleep[reg];
+ case MENELAUS_SLEEP_CTRL2:
+ return s->sleep[addr - MENELAUS_SLEEP_CTRL1];
case MENELAUS_DEVICE_OFF:
return 0;
@@ -395,10 +381,8 @@
case MENELAUS_S2_PULL_DIR:
return s->pull[3];
- case MENELAUS_MCT_CTRL3: reg ++;
- case MENELAUS_MCT_CTRL2: reg ++;
- case MENELAUS_MCT_CTRL1:
- return s->mmc_ctrl[reg];
+ case MENELAUS_MCT_CTRL1 ... MENELAUS_MCT_CTRL3:
+ return s->mmc_ctrl[addr - MENELAUS_MCT_CTRL1];
case MENELAUS_MCT_PIN_ST:
/* TODO: return the real Card Detect */
return 0;
@@ -418,7 +402,6 @@
{
MenelausState *s = (MenelausState *) opaque;
int line;
- int reg = 0;
struct tm tm;
switch (addr) {
@@ -496,9 +479,9 @@
s->ldo[7] = value & 3;
break;
- case MENELAUS_SLEEP_CTRL2: reg ++;
case MENELAUS_SLEEP_CTRL1:
- s->sleep[reg] = value;
+ case MENELAUS_SLEEP_CTRL2:
+ s->sleep[addr - MENELAUS_SLEEP_CTRL1] = value;
break;
case MENELAUS_DEVICE_OFF:
@@ -714,6 +697,7 @@
#ifdef VERBOSE
printf("%s: unknown register %02x\n", __func__, addr);
#endif
+ break;
}
}
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
index 446f2ea..e03a815 100644
--- a/hw/timer/renesas_tmr.c
+++ b/hw/timer/renesas_tmr.c
@@ -221,6 +221,7 @@
} else if (ch == 0) {
return concat_reg(tmr->tcora);
}
+ /* fall through */
case A_TCORB:
if (size == 1) {
return tmr->tcorb[ch];
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index 0b01988..20ff5fe 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -22,10 +22,11 @@
#include "exec/cpu-defs.h"
#include "hw/loader.h"
+#include "hw/riscv/riscv_hart.h"
-bool riscv_is_32_bit(MachineState *machine);
+bool riscv_is_32bit(RISCVHartArrayState harts);
-target_ulong riscv_calc_kernel_start_addr(MachineState *machine,
+target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState harts,
target_ulong firmware_end_addr);
target_ulong riscv_find_and_load_firmware(MachineState *machine,
const char *default_machine_firmware,
@@ -41,10 +42,13 @@
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
uint64_t kernel_entry, hwaddr *start);
uint32_t riscv_load_fdt(hwaddr dram_start, uint64_t dram_size, void *fdt);
-void riscv_setup_rom_reset_vec(hwaddr saddr, hwaddr rom_base,
- hwaddr rom_size, uint64_t kernel_entry,
+void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState harts,
+ hwaddr saddr,
+ hwaddr rom_base, hwaddr rom_size,
+ uint64_t kernel_entry,
uint32_t fdt_load_addr, void *fdt);
-void riscv_rom_copy_firmware_info(hwaddr rom_base, hwaddr rom_size,
+void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+ hwaddr rom_size,
uint32_t reset_vec_size,
uint64_t kernel_entry);
diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h
index 51d4463..d0c666a 100644
--- a/include/hw/riscv/microchip_pfsoc.h
+++ b/include/hw/riscv/microchip_pfsoc.h
@@ -97,6 +97,8 @@
MICROCHIP_PFSOC_MMUART2,
MICROCHIP_PFSOC_MMUART3,
MICROCHIP_PFSOC_MMUART4,
+ MICROCHIP_PFSOC_SPI0,
+ MICROCHIP_PFSOC_SPI1,
MICROCHIP_PFSOC_I2C1,
MICROCHIP_PFSOC_GEM0,
MICROCHIP_PFSOC_GEM1,
@@ -105,6 +107,7 @@
MICROCHIP_PFSOC_GPIO2,
MICROCHIP_PFSOC_ENVM_CFG,
MICROCHIP_PFSOC_ENVM_DATA,
+ MICROCHIP_PFSOC_QSPI_XIP,
MICROCHIP_PFSOC_IOSCB,
MICROCHIP_PFSOC_DRAM_LO,
MICROCHIP_PFSOC_DRAM_LO_ALIAS,
diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h
index 5ff0c0f..a5ea3a5 100644
--- a/include/hw/riscv/opentitan.h
+++ b/include/hw/riscv/opentitan.h
@@ -55,19 +55,30 @@
IBEX_DEV_UART,
IBEX_DEV_GPIO,
IBEX_DEV_SPI,
- IBEX_DEV_FLASH_CTRL,
+ IBEX_DEV_I2C,
+ IBEX_DEV_PATTGEN,
IBEX_DEV_RV_TIMER,
- IBEX_DEV_AES,
- IBEX_DEV_HMAC,
- IBEX_DEV_PLIC,
+ IBEX_DEV_SENSOR_CTRL,
+ IBEX_DEV_OTP_CTRL,
IBEX_DEV_PWRMGR,
IBEX_DEV_RSTMGR,
IBEX_DEV_CLKMGR,
IBEX_DEV_PINMUX,
+ IBEX_DEV_PADCTRL,
+ IBEX_DEV_USBDEV,
+ IBEX_DEV_FLASH_CTRL,
+ IBEX_DEV_PLIC,
+ IBEX_DEV_AES,
+ IBEX_DEV_HMAC,
+ IBEX_DEV_KMAC,
+ IBEX_DEV_KEYMGR,
+ IBEX_DEV_CSRNG,
+ IBEX_DEV_ENTROPY,
+ IBEX_DEV_EDNO,
+ IBEX_DEV_EDN1,
IBEX_DEV_ALERT_HANDLER,
IBEX_DEV_NMI_GEN,
- IBEX_DEV_USBDEV,
- IBEX_DEV_PADCTRL,
+ IBEX_DEV_OTBN,
};
enum {
diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h
index cddeca2..cdd1a13 100644
--- a/include/hw/riscv/spike.h
+++ b/include/hw/riscv/spike.h
@@ -47,10 +47,4 @@
SPIKE_DRAM
};
-#if defined(TARGET_RISCV32)
-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE32
-#elif defined(TARGET_RISCV64)
-#define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_BASE64
-#endif
-
#endif
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index b4ed9a3..84b7a38 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -89,10 +89,4 @@
#define FDT_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + \
FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS)
-#if defined(TARGET_RISCV32)
-#define VIRT_CPU TYPE_RISCV_CPU_BASE32
-#elif defined(TARGET_RISCV64)
-#define VIRT_CPU TYPE_RISCV_CPU_BASE64
-#endif
-
#endif
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 1b9e58e..df9ec08 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -222,4 +222,15 @@
#define qemu_build_not_reached() g_assert_not_reached()
#endif
+/**
+ * In most cases, normal "fallthrough" comments are good enough for
+ * switch-case statements, but sometimes the compiler has problems
+ * with those. In that case you can use QEMU_FALLTHROUGH instead.
+ */
+#if __has_attribute(fallthrough)
+# define QEMU_FALLTHROUGH __attribute__((fallthrough))
+#else
+# define QEMU_FALLTHROUGH do {} while (0) /* fallthrough */
+#endif
+
#endif /* COMPILER_H */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0b02a92..a640507 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -7,6 +7,7 @@
#include "qemu.h"
#include "disas/disas.h"
+#include "qemu/bitops.h"
#include "qemu/path.h"
#include "qemu/queue.h"
#include "qemu/guest-random.h"
@@ -985,26 +986,54 @@
enum {
HWCAP_MIPS_R6 = (1 << 0),
HWCAP_MIPS_MSA = (1 << 1),
+ HWCAP_MIPS_CRC32 = (1 << 2),
+ HWCAP_MIPS_MIPS16 = (1 << 3),
+ HWCAP_MIPS_MDMX = (1 << 4),
+ HWCAP_MIPS_MIPS3D = (1 << 5),
+ HWCAP_MIPS_SMARTMIPS = (1 << 6),
+ HWCAP_MIPS_DSP = (1 << 7),
+ HWCAP_MIPS_DSP2 = (1 << 8),
+ HWCAP_MIPS_DSP3 = (1 << 9),
+ HWCAP_MIPS_MIPS16E2 = (1 << 10),
+ HWCAP_LOONGSON_MMI = (1 << 11),
+ HWCAP_LOONGSON_EXT = (1 << 12),
+ HWCAP_LOONGSON_EXT2 = (1 << 13),
+ HWCAP_LOONGSON_CPUCFG = (1 << 14),
};
#define ELF_HWCAP get_elf_hwcap()
+#define GET_FEATURE_INSN(_flag, _hwcap) \
+ do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0)
+
+#define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \
+ do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0)
+
+#define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \
+ do { \
+ if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \
+ hwcaps |= _hwcap; \
+ } \
+ } while (0)
+
static uint32_t get_elf_hwcap(void)
{
MIPSCPU *cpu = MIPS_CPU(thread_cpu);
uint32_t hwcaps = 0;
-#define GET_FEATURE(flag, hwcap) \
- do { if (cpu->env.insn_flags & (flag)) { hwcaps |= hwcap; } } while (0)
-
- GET_FEATURE(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
- GET_FEATURE(ASE_MSA, HWCAP_MIPS_MSA);
-
-#undef GET_FEATURE
+ GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH,
+ 2, HWCAP_MIPS_R6);
+ GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA);
+ GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI);
+ GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT);
return hwcaps;
}
+#undef GET_FEATURE_REG_EQU
+#undef GET_FEATURE_REG_SET
+#undef GET_FEATURE_INSN
+
#endif /* TARGET_MIPS */
#ifdef TARGET_MICROBLAZE
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 8efb4d3..661b5da 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -720,3 +720,49 @@
IOCTL(KCOV_DISABLE, 0, TYPE_NULL)
IOCTL(KCOV_INIT_TRACE, IOC_R, TYPE_ULONG)
#endif
+
+ IOCTL(TUNSETDEBUG, IOC_W, TYPE_INT)
+ IOCTL(TUNSETIFF, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+ IOCTL(TUNSETPERSIST, IOC_W, TYPE_INT)
+ IOCTL(TUNSETOWNER, IOC_W, TYPE_INT)
+ IOCTL(TUNSETLINK, IOC_W, TYPE_INT)
+ IOCTL(TUNSETGROUP, IOC_W, TYPE_INT)
+ IOCTL(TUNGETFEATURES, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETOFFLOAD, IOC_W, TYPE_LONG)
+ IOCTL_SPECIAL(TUNSETTXFILTER, IOC_W, do_ioctl_TUNSETTXFILTER,
+ /*
+ * We can't represent `struct tun_filter` in thunk so leaving
+ * it uninterpreted. do_ioctl_TUNSETTXFILTER will do the
+ * conversion.
+ */
+ TYPE_PTRVOID)
+ IOCTL(TUNGETIFF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+ IOCTL(TUNGETSNDBUF, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETSNDBUF, IOC_W, MK_PTR(TYPE_INT))
+ /*
+ * TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
+ * user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
+ */
+ IOCTL(TUNGETVNETHDRSZ, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETVNETHDRSZ, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TUNSETQUEUE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
+ IOCTL(TUNSETIFINDEX , IOC_W, MK_PTR(TYPE_INT))
+ /* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
+ IOCTL(TUNSETVNETLE, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TUNGETVNETLE, IOC_R, MK_PTR(TYPE_INT))
+#ifdef TUNSETVNETBE
+ IOCTL(TUNSETVNETBE, IOC_W, MK_PTR(TYPE_INT))
+ IOCTL(TUNGETVNETBE, IOC_R, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNSETSTEERINGEBPF
+ IOCTL(TUNSETSTEERINGEBPF, IOC_W, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNSETFILTEREBPF
+ IOCTL(TUNSETFILTEREBPF, IOC_W, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNSETCARRIER
+ IOCTL(TUNSETCARRIER, IOC_W, MK_PTR(TYPE_INT))
+#endif
+#ifdef TUNGETDEVNETNS
+ IOCTL(TUNGETDEVNETNS, IOC_R, TYPE_NULL)
+#endif
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 00c05e6..810653c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -767,20 +767,23 @@
}
if (prot == 0) {
host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
- if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) {
- mmap_reserve(old_addr + old_size, old_size - new_size);
+
+ if (host_addr != MAP_FAILED) {
+ /* Check if address fits target address space */
+ if (!guest_range_valid(h2g(host_addr), new_size)) {
+ /* Revert mremap() changes */
+ host_addr = mremap(g2h(old_addr), new_size, old_size,
+ flags);
+ errno = ENOMEM;
+ host_addr = MAP_FAILED;
+ } else if (reserved_va && old_size > new_size) {
+ mmap_reserve(old_addr + old_size, old_size - new_size);
+ }
}
} else {
errno = ENOMEM;
host_addr = MAP_FAILED;
}
- /* Check if address fits target address space */
- if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {
- /* Revert mremap() changes */
- host_addr = mremap(g2h(old_addr), new_size, old_size, flags);
- errno = ENOMEM;
- host_addr = MAP_FAILED;
- }
}
if (host_addr == MAP_FAILED) {
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index d12adc8..d27b7a3 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -402,8 +402,10 @@
abi_ulong ucp_addr;
struct target_ucontext *ucp;
target_mc_gregset_t *grp;
+ target_mc_fpu_t *fpup;
abi_ulong pc, npc, tstate;
unsigned int i;
+ unsigned char fenab;
ucp_addr = env->regwptr[WREG_O0];
if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
@@ -436,16 +438,16 @@
env->npc = npc;
__get_user(env->y, &((*grp)[SPARC_MC_Y]));
__get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
+ /* Honour TSTATE_ASI, TSTATE_ICC and TSTATE_XCC only */
env->asi = (tstate >> 24) & 0xff;
- cpu_put_ccr(env, tstate >> 32);
- cpu_put_cwp64(env, tstate & 0x1f);
+ cpu_put_ccr(env, (tstate >> 32) & 0xff);
__get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
__get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
__get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
__get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
__get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
__get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
- __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
+ /* Skip g7 as that's the thread register in userspace */
/*
* Note that unlike the kernel, we didn't need to mess with the
@@ -467,26 +469,42 @@
__get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp));
__get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7));
- /* FIXME this does not match how the kernel handles the FPU in
- * its sparc64_set_context implementation. In particular the FPU
- * is only restored if fenab is non-zero in:
- * __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
- */
- __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
- {
- uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
- for (i = 0; i < 64; i++, src++) {
- if (i & 1) {
- __get_user(env->fpr[i/2].l.lower, src);
- } else {
- __get_user(env->fpr[i/2].l.upper, src);
+ fpup = &ucp->tuc_mcontext.mc_fpregs;
+
+ __get_user(fenab, &(fpup->mcfpu_enab));
+ if (fenab) {
+ abi_ulong fprs;
+
+ /*
+ * We use the FPRS from the guest only in deciding whether
+ * to restore the upper, lower, or both banks of the FPU regs.
+ * The kernel here writes the FPU register data into the
+ * process's current_thread_info state and unconditionally
+ * clears FPRS and TSTATE_PEF: this disables the FPU so that the
+ * next FPU-disabled trap will copy the data out of
+ * current_thread_info and into the real FPU registers.
+ * QEMU doesn't need to handle lazy-FPU-state-restoring like that,
+ * so we always load the data directly into the FPU registers
+ * and leave FPRS and TSTATE_PEF alone (so the FPU stays enabled).
+ * Note that because we (and the kernel) always write zeroes for
+ * the fenab and fprs in sparc64_get_context() none of this code
+ * will execute unless the guest manually constructed or changed
+ * the context structure.
+ */
+ __get_user(fprs, &(fpup->mcfpu_fprs));
+ if (fprs & FPRS_DL) {
+ for (i = 0; i < 16; i++) {
+ __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
}
}
+ if (fprs & FPRS_DU) {
+ for (i = 16; i < 32; i++) {
+ __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
+ }
+ }
+ __get_user(env->fsr, &(fpup->mcfpu_fsr));
+ __get_user(env->gsr, &(fpup->mcfpu_gsr));
}
- __get_user(env->fsr,
- &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
- __get_user(env->gsr,
- &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
unlock_user_struct(ucp, ucp_addr, 0);
return;
do_sigsegv:
@@ -509,7 +527,9 @@
if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
goto do_sigsegv;
}
-
+
+ memset(ucp, 0, sizeof(*ucp));
+
mcp = &ucp->tuc_mcontext;
grp = &mcp->mc_gregs;
@@ -535,12 +555,9 @@
for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
__put_user(*src, dst);
}
- if (err)
- goto do_sigsegv;
}
- /* XXX: tstate must be saved properly */
- // __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
+ __put_user(sparc64_tstate(env), &((*grp)[SPARC_MC_TSTATE]));
__put_user(env->pc, &((*grp)[SPARC_MC_PC]));
__put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
__put_user(env->y, &((*grp)[SPARC_MC_Y]));
@@ -572,22 +589,12 @@
__put_user(env->regwptr[WREG_FP], &(mcp->mc_fp));
__put_user(env->regwptr[WREG_I7], &(mcp->mc_i7));
- {
- uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
- for (i = 0; i < 64; i++, dst++) {
- if (i & 1) {
- __put_user(env->fpr[i/2].l.lower, dst);
- } else {
- __put_user(env->fpr[i/2].l.upper, dst);
- }
- }
- }
- __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
- __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
- __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+ /*
+ * We don't write out the FPU state. This matches the kernel's
+ * implementation (which has the code for doing this but
+ * hidden behind an "if (fenab)" where fenab is always 0).
+ */
- if (err)
- goto do_sigsegv;
unlock_user_struct(ucp, ucp_addr, 1);
return;
do_sigsegv:
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7bf99be..d182890 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -56,6 +56,7 @@
#include <linux/wireless.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h>
+#include <linux/if_tun.h>
#include <linux/errqueue.h>
#include <linux/random.h>
#ifdef CONFIG_TIMERFD
@@ -813,6 +814,12 @@
safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
size_t, len, unsigned *, prio, const struct timespec *, timeout)
#endif
+#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
+safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
+ int, outfd, loff_t *, poutoff, size_t, length,
+ unsigned int, flags)
+#endif
+
/* We do ioctl like this rather than via safe_syscall3 to preserve the
* "third argument might be integer or pointer or not present" behaviour of
* the libc function.
@@ -5703,6 +5710,42 @@
#endif
+static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+ struct tun_filter *filter = (struct tun_filter *)buf_temp;
+ struct tun_filter *target_filter;
+ char *target_addr;
+
+ assert(ie->access == IOC_W);
+
+ target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
+ if (!target_filter) {
+ return -TARGET_EFAULT;
+ }
+ filter->flags = tswap16(target_filter->flags);
+ filter->count = tswap16(target_filter->count);
+ unlock_user(target_filter, arg, 0);
+
+ if (filter->count) {
+ if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
+ MAX_STRUCT_SIZE) {
+ return -TARGET_EFAULT;
+ }
+
+ target_addr = lock_user(VERIFY_READ,
+ arg + offsetof(struct tun_filter, addr),
+ filter->count * ETH_ALEN, 1);
+ if (!target_addr) {
+ return -TARGET_EFAULT;
+ }
+ memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
+ unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
+ }
+
+ return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
+}
+
IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
@@ -13065,6 +13108,42 @@
return get_errno(membarrier(arg1, arg2));
#endif
+#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
+ case TARGET_NR_copy_file_range:
+ {
+ loff_t inoff, outoff;
+ loff_t *pinoff = NULL, *poutoff = NULL;
+
+ if (arg2) {
+ if (get_user_u64(inoff, arg2)) {
+ return -TARGET_EFAULT;
+ }
+ pinoff = &inoff;
+ }
+ if (arg4) {
+ if (get_user_u64(outoff, arg4)) {
+ return -TARGET_EFAULT;
+ }
+ poutoff = &outoff;
+ }
+ ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
+ arg5, arg6));
+ if (!is_error(ret) && ret > 0) {
+ if (arg2) {
+ if (put_user_u64(inoff, arg2)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ if (arg4) {
+ if (put_user_u64(outoff, arg4)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ }
+ }
+ return ret;
+#endif
+
default:
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
return -TARGET_ENOSYS;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index b934d0b..a00bfc2 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -929,6 +929,38 @@
#define TARGET_SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* From <linux/if_tun.h> */
+
+#define TARGET_TUNSETDEBUG TARGET_IOW('T', 201, int)
+#define TARGET_TUNSETIFF TARGET_IOW('T', 202, int)
+#define TARGET_TUNSETPERSIST TARGET_IOW('T', 203, int)
+#define TARGET_TUNSETOWNER TARGET_IOW('T', 204, int)
+#define TARGET_TUNSETLINK TARGET_IOW('T', 205, int)
+#define TARGET_TUNSETGROUP TARGET_IOW('T', 206, int)
+#define TARGET_TUNGETFEATURES TARGET_IOR('T', 207, unsigned int)
+#define TARGET_TUNSETOFFLOAD TARGET_IOW('T', 208, unsigned int)
+#define TARGET_TUNSETTXFILTER TARGET_IOW('T', 209, unsigned int)
+#define TARGET_TUNGETIFF TARGET_IOR('T', 210, unsigned int)
+#define TARGET_TUNGETSNDBUF TARGET_IOR('T', 211, int)
+#define TARGET_TUNSETSNDBUF TARGET_IOW('T', 212, int)
+/*
+ * TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
+ * user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
+ */
+#define TARGET_TUNGETVNETHDRSZ TARGET_IOR('T', 215, int)
+#define TARGET_TUNSETVNETHDRSZ TARGET_IOW('T', 216, int)
+#define TARGET_TUNSETQUEUE TARGET_IOW('T', 217, int)
+#define TARGET_TUNSETIFINDEX TARGET_IOW('T', 218, unsigned int)
+/* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
+#define TARGET_TUNSETVNETLE TARGET_IOW('T', 220, int)
+#define TARGET_TUNGETVNETLE TARGET_IOR('T', 221, int)
+#define TARGET_TUNSETVNETBE TARGET_IOW('T', 222, int)
+#define TARGET_TUNGETVNETBE TARGET_IOR('T', 223, int)
+#define TARGET_TUNSETSTEERINGEBPF TARGET_IOR('T', 224, int)
+#define TARGET_TUNSETFILTEREBPF TARGET_IOR('T', 225, int)
+#define TARGET_TUNSETCARRIER TARGET_IOW('T', 226, int)
+#define TARGET_TUNGETDEVNETNS TARGET_IO('T', 227)
+
/* From <linux/random.h> */
#define TARGET_RNDGETENTCNT TARGET_IOR('R', 0x00, int)
diff --git a/migration/migration.c b/migration/migration.c
index e0dbde4..f5d4a52 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2102,6 +2102,12 @@
return false;
}
+ if (runstate_check(RUN_STATE_POSTMIGRATE)) {
+ error_setg(errp, "Can't migrate the vm that was paused due to "
+ "previous migration");
+ return false;
+ }
+
if (migration_is_blocked(errp)) {
return false;
}
diff --git a/migration/savevm.c b/migration/savevm.c
index 5f937a2..4a18c9d 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2728,7 +2728,7 @@
int save_snapshot(const char *name, Error **errp)
{
BlockDriverState *bs, *bs1;
- QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
+ QEMUSnapshotInfo sn1, *sn = &sn1;
int ret = -1, ret2;
QEMUFile *f;
int saved_vm_running;
@@ -2797,13 +2797,7 @@
}
if (name) {
- ret = bdrv_snapshot_find(bs, old_sn, name);
- if (ret >= 0) {
- pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
- pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
- } else {
- pstrcpy(sn->name, sizeof(sn->name), name);
- }
+ pstrcpy(sn->name, sizeof(sn->name), name);
} else {
/* cast below needed for OpenBSD where tv_sec is still 'long' */
localtime_r((const time_t *)&tv.tv_sec, &tm);
@@ -2839,6 +2833,7 @@
if (ret < 0) {
error_setg(errp, "Error while creating snapshot on '%s'",
bdrv_get_device_or_node_name(bs));
+ bdrv_all_delete_snapshot(sn->name, &bs, NULL);
goto the_end;
}
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 65d8ff4..79c8432 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1549,8 +1549,7 @@
hmp_handle_error(mon, err);
}
-typedef struct HMPMigrationStatus
-{
+typedef struct HMPMigrationStatus {
QEMUTimer *timer;
Monitor *mon;
bool is_block_migration;
diff --git a/monitor/misc.c b/monitor/misc.c
index fde6e36..6f5ae09 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -492,8 +492,10 @@
static void hmp_gdbserver(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_try_str(qdict, "device");
- if (!device)
+ if (!device) {
device = "tcp::" DEFAULT_GDBSTUB_PORT;
+ }
+
if (gdbserver_start(device) < 0) {
monitor_printf(mon, "Could not open gdbserver on device '%s'\n",
device);
@@ -559,10 +561,11 @@
}
len = wsize * count;
- if (wsize == 1)
+ if (wsize == 1) {
line_size = 8;
- else
+ } else {
line_size = 16;
+ }
max_digits = 0;
switch(format) {
@@ -583,10 +586,11 @@
}
while (len > 0) {
- if (is_physical)
+ if (is_physical) {
monitor_printf(mon, TARGET_FMT_plx ":", addr);
- else
+ } else {
monitor_printf(mon, TARGET_FMT_lx ":", (target_ulong)addr);
+ }
l = len;
if (l > line_size)
l = line_size;
@@ -915,7 +919,7 @@
suffix = 'l';
break;
}
- monitor_printf(mon, "port%c[0x%04x] = %#0*x\n",
+ monitor_printf(mon, "port%c[0x%04x] = 0x%0*x\n",
suffix, addr, size * 2, val);
}
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 750f75c..11db2f3 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1778,9 +1778,12 @@
} else {
tcg_gen_deposit_tl(s->T1, s->T0, s->T1, 16, 16);
}
- /* FALLTHRU */
-#ifdef TARGET_X86_64
+ /*
+ * If TARGET_X86_64 defined then fall through into MO_32 case,
+ * otherwise fall through default case.
+ */
case MO_32:
+#ifdef TARGET_X86_64
/* Concatenate the two 32-bit values and use a 64-bit shift. */
tcg_gen_subi_tl(s->tmp0, count, 1);
if (is_right) {
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3ac21d0..4cbc31c 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -844,6 +844,7 @@
#define CP0C0_MT 7 /* 9..7 */
#define CP0C0_VI 3
#define CP0C0_K0 0 /* 2..0 */
+#define CP0C0_AR_LENGTH 3
int32_t CP0_Config1;
#define CP0C1_M 31
#define CP0C1_MMU 25 /* 30..25 */
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6a0264f..254cd83 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -108,6 +108,15 @@
}
}
+bool riscv_cpu_is_32bit(CPURISCVState *env)
+{
+ if (env->misa & RV64) {
+ return false;
+ }
+
+ return true;
+}
+
static void set_misa(CPURISCVState *env, target_ulong misa)
{
env->misa_mask = env->misa = misa;
@@ -142,29 +151,50 @@
set_priv_version(env, PRIV_VERSION_1_11_0);
}
-static void riscv_base_cpu_init(Object *obj)
+#if defined(TARGET_RISCV64)
+static void rv64_base_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, 0);
+ set_misa(env, RV64);
}
-static void rvxx_sifive_u_cpu_init(Object *obj)
+static void rv64_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
}
-static void rvxx_sifive_e_cpu_init(Object *obj)
+static void rv64_sifive_e_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, RVXLEN | RVI | RVM | RVA | RVC | RVU);
+ set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
+#else
+static void rv32_base_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ /* We set this in the realise function */
+ set_misa(env, RV32);
+}
-#if defined(TARGET_RISCV32)
+static void rv32_sifive_u_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ set_priv_version(env, PRIV_VERSION_1_10_0);
+}
+
+static void rv32_sifive_e_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
+ set_priv_version(env, PRIV_VERSION_1_10_0);
+ qdev_prop_set_bit(DEVICE(obj), "mmu", false);
+}
static void rv32_ibex_cpu_init(Object *obj)
{
@@ -182,7 +212,6 @@
set_resetvec(env, DEFAULT_RSTVEC);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
-
#endif
static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
@@ -218,10 +247,10 @@
#ifndef CONFIG_USER_ONLY
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", (target_ulong)env->mstatus);
-#ifdef TARGET_RISCV32
- qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
- (target_ulong)(env->mstatus >> 32));
-#endif
+ if (riscv_cpu_is_32bit(env)) {
+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
+ (target_ulong)(env->mstatus >> 32));
+ }
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 ",
@@ -334,11 +363,12 @@
static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
{
-#if defined(TARGET_RISCV32)
- info->print_insn = print_insn_riscv32;
-#elif defined(TARGET_RISCV64)
- info->print_insn = print_insn_riscv64;
-#endif
+ RISCVCPU *cpu = RISCV_CPU(s);
+ if (riscv_cpu_is_32bit(&cpu->env)) {
+ info->print_insn = print_insn_riscv32;
+ } else {
+ info->print_insn = print_insn_riscv64;
+ }
}
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
@@ -349,7 +379,7 @@
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
int priv_version = PRIV_VERSION_1_11_0;
int vext_version = VEXT_VERSION_0_07_1;
- target_ulong target_misa = 0;
+ target_ulong target_misa = env->misa;
Error *local_err = NULL;
cpu_exec_realizefn(cs, &local_err);
@@ -384,8 +414,8 @@
set_resetvec(env, cpu->cfg.resetvec);
- /* If misa isn't set (rv32 and rv64 machines) set it here */
- if (!env->misa) {
+ /* If only XLEN is set for misa, then set misa from properties */
+ if (env->misa == RV32 || env->misa == RV64) {
/* Do some ISA extension error checking */
if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
error_setg(errp,
@@ -481,7 +511,7 @@
set_vext_version(env, vext_version);
}
- set_misa(env, RVXLEN | target_misa);
+ set_misa(env, target_misa);
}
riscv_cpu_register_gdb_regs_for_features(cs);
@@ -632,15 +662,15 @@
},
DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
#if defined(TARGET_RISCV32)
- DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_BASE32, rv32_base_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rvxx_sifive_e_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32_sifive_e_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rvxx_sifive_u_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32_sifive_u_cpu_init),
#elif defined(TARGET_RISCV64)
- DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rvxx_sifive_e_cpu_init),
- DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rvxx_sifive_u_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_BASE64, rv64_base_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init),
#endif
};
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c0a326c..6339e84 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -44,6 +44,12 @@
#define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34")
#define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54")
+#if defined(TARGET_RISCV32)
+# define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE32
+#elif defined(TARGET_RISCV64)
+# define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE64
+#endif
+
#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
@@ -378,6 +384,8 @@
/* Is a Hypervisor instruction load/store allowed? */
FIELD(TB_FLAGS, HLSX, 9, 1)
+bool riscv_cpu_is_32bit(CPURISCVState *env);
+
/*
* A simplification for VLMAX
* = (1 << LMUL) * VLEN / (8 * (1 << SEW))
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 24b24c6..b41e883 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -379,8 +379,8 @@
#define MSTATUS_MXR 0x00080000
#define MSTATUS_VM 0x1F000000 /* until: priv-1.9.1 */
#define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */
-#define MSTATUS_TW 0x20000000 /* since: priv-1.10 */
-#define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */
+#define MSTATUS_TW 0x00200000 /* since: priv-1.10 */
+#define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */
#define MSTATUS_GVA 0x4000000000ULL
#define MSTATUS_MPV 0x8000000000ULL
@@ -437,9 +437,7 @@
#define HSTATUS_VGEIN 0x0003F000
#define HSTATUS_VTVM 0x00100000
#define HSTATUS_VTSR 0x00400000
-#if defined(TARGET_RISCV64)
-#define HSTATUS_VSXL 0x300000000
-#endif
+#define HSTATUS_VSXL 0x300000000
#define HSTATUS32_WPRI 0xFF8FF87E
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index a2787b1..a2afb95 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -367,7 +367,8 @@
vm = get_field(env->hgatp, HGATP_MODE);
widened = 2;
}
- sum = get_field(env->mstatus, MSTATUS_SUM);
+ /* status.SUM will be ignored if execute on background */
+ sum = get_field(env->mstatus, MSTATUS_SUM) || use_background;
switch (vm) {
case VM_1_10_SV32:
levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -446,11 +447,13 @@
return TRANSLATE_PMP_FAIL;
}
-#if defined(TARGET_RISCV32)
- target_ulong pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
-#elif defined(TARGET_RISCV64)
- target_ulong pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
-#endif
+ target_ulong pte;
+ if (riscv_cpu_is_32bit(env)) {
+ pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
+ } else {
+ pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
+ }
+
if (res != MEMTX_OK) {
return TRANSLATE_FAIL;
}
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 93263f8..10ab82e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -102,44 +102,65 @@
return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
break;
-#if defined(TARGET_RISCV32)
- case CSR_CYCLEH:
- if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
- get_field(env->mcounteren, HCOUNTEREN_CY)) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ if (riscv_cpu_is_32bit(env)) {
+ switch (csrno) {
+ case CSR_CYCLEH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
+ get_field(env->mcounteren, HCOUNTEREN_CY)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_TIMEH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
+ get_field(env->mcounteren, HCOUNTEREN_TM)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_INSTRETH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
+ get_field(env->mcounteren, HCOUNTEREN_IR)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
+ if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
+ get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
}
- break;
- case CSR_TIMEH:
- if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
- get_field(env->mcounteren, HCOUNTEREN_TM)) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- case CSR_INSTRETH:
- if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
- get_field(env->mcounteren, HCOUNTEREN_IR)) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
- if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
- get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
- return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
-#endif
}
}
#endif
return 0;
}
+static int ctr32(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_is_32bit(env)) {
+ return -RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return ctr(env, csrno);
+}
+
#if !defined(CONFIG_USER_ONLY)
static int any(CPURISCVState *env, int csrno)
{
return 0;
}
+static int any32(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_is_32bit(env)) {
+ return -RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return any(env, csrno);
+
+}
+
static int smode(CPURISCVState *env, int csrno)
{
return -!riscv_has_ext(env, RVS);
@@ -161,6 +182,16 @@
return -RISCV_EXCP_ILLEGAL_INST;
}
+static int hmode32(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_is_32bit(env)) {
+ return 0;
+ }
+
+ return hmode(env, csrno);
+
+}
+
static int pmp(CPURISCVState *env, int csrno)
{
return -!riscv_feature(env, RISCV_FEATURE_PMP);
@@ -310,7 +341,6 @@
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val)
{
#if !defined(CONFIG_USER_ONLY)
@@ -324,7 +354,6 @@
#endif
return 0;
}
-#endif /* TARGET_RISCV32 */
#if defined(CONFIG_USER_ONLY)
static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
@@ -333,13 +362,11 @@
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = cpu_get_host_ticks() >> 32;
return 0;
}
-#endif
#else /* CONFIG_USER_ONLY */
@@ -355,7 +382,6 @@
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
{
uint64_t delta = riscv_cpu_virt_enabled(env) ? env->htimedelta : 0;
@@ -367,7 +393,6 @@
*val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32;
return 0;
}
-#endif
/* Machine constants */
@@ -406,19 +431,17 @@
static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP;
static const target_ulong vsip_writable_mask = MIP_VSSIP;
-#if defined(TARGET_RISCV32)
-static const char valid_vm_1_10[16] = {
+static const char valid_vm_1_10_32[16] = {
[VM_1_10_MBARE] = 1,
[VM_1_10_SV32] = 1
};
-#elif defined(TARGET_RISCV64)
-static const char valid_vm_1_10[16] = {
+
+static const char valid_vm_1_10_64[16] = {
[VM_1_10_MBARE] = 1,
[VM_1_10_SV39] = 1,
[VM_1_10_SV48] = 1,
[VM_1_10_SV57] = 1
};
-#endif /* CONFIG_USER_ONLY */
/* Machine Information Registers */
static int read_zero(CPURISCVState *env, int csrno, target_ulong *val)
@@ -441,7 +464,11 @@
static int validate_vm(CPURISCVState *env, target_ulong vm)
{
- return valid_vm_1_10[vm & 0xf];
+ if (riscv_cpu_is_32bit(env)) {
+ return valid_vm_1_10_32[vm & 0xf];
+ } else {
+ return valid_vm_1_10_64[vm & 0xf];
+ }
}
static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
@@ -459,13 +486,14 @@
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
MSTATUS_TW;
-#if defined(TARGET_RISCV64)
- /*
- * RV32: MPV and GVA are not in mstatus. The current plan is to
- * add them to mstatush. For now, we just don't support it.
- */
- mask |= MSTATUS_MPV | MSTATUS_GVA;
-#endif
+
+ if (!riscv_cpu_is_32bit(env)) {
+ /*
+ * RV32: MPV and GVA are not in mstatus. The current plan is to
+ * add them to mstatush. For now, we just don't support it.
+ */
+ mask |= MSTATUS_MPV | MSTATUS_GVA;
+ }
mstatus = (mstatus & ~mask) | (val & mask);
@@ -477,7 +505,6 @@
return 0;
}
-#ifdef TARGET_RISCV32
static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->mstatus >> 32;
@@ -497,7 +524,6 @@
return 0;
}
-#endif
static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
{
@@ -895,10 +921,10 @@
static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->hstatus;
-#ifdef TARGET_RISCV64
- /* We only support 64-bit VSXL */
- *val = set_field(*val, HSTATUS_VSXL, 2);
-#endif
+ if (!riscv_cpu_is_32bit(env)) {
+ /* We only support 64-bit VSXL */
+ *val = set_field(*val, HSTATUS_VSXL, 2);
+ }
/* We only support little endian */
*val = set_field(*val, HSTATUS_VSBE, 0);
return 0;
@@ -907,11 +933,9 @@
static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val)
{
env->hstatus = val;
-#ifdef TARGET_RISCV64
- if (get_field(val, HSTATUS_VSXL) != 2) {
+ if (!riscv_cpu_is_32bit(env) && get_field(val, HSTATUS_VSXL) != 2) {
qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options.");
}
-#endif
if (get_field(val, HSTATUS_VSBE) != 0) {
qemu_log_mask(LOG_UNIMP, "QEMU does not support big endian guests.");
}
@@ -1053,11 +1077,7 @@
return -RISCV_EXCP_ILLEGAL_INST;
}
-#if defined(TARGET_RISCV32)
- *val = env->htimedelta & 0xffffffff;
-#else
*val = env->htimedelta;
-#endif
return 0;
}
@@ -1067,15 +1087,14 @@
return -RISCV_EXCP_ILLEGAL_INST;
}
-#if defined(TARGET_RISCV32)
- env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
-#else
- env->htimedelta = val;
-#endif
+ if (riscv_cpu_is_32bit(env)) {
+ env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
+ } else {
+ env->htimedelta = val;
+ }
return 0;
}
-#if defined(TARGET_RISCV32)
static int read_htimedeltah(CPURISCVState *env, int csrno, target_ulong *val)
{
if (!env->rdtime_fn) {
@@ -1095,7 +1114,6 @@
env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
return 0;
}
-#endif
/* Virtual CSR Registers */
static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val)
@@ -1374,26 +1392,20 @@
/* User Timers and Counters */
[CSR_CYCLE] = { ctr, read_instret },
[CSR_INSTRET] = { ctr, read_instret },
-#if defined(TARGET_RISCV32)
- [CSR_CYCLEH] = { ctr, read_instreth },
- [CSR_INSTRETH] = { ctr, read_instreth },
-#endif
+ [CSR_CYCLEH] = { ctr32, read_instreth },
+ [CSR_INSTRETH] = { ctr32, read_instreth },
/* In privileged mode, the monitor will have to emulate TIME CSRs only if
* rdtime callback is not provided by machine/platform emulation */
[CSR_TIME] = { ctr, read_time },
-#if defined(TARGET_RISCV32)
- [CSR_TIMEH] = { ctr, read_timeh },
-#endif
+ [CSR_TIMEH] = { ctr32, read_timeh },
#if !defined(CONFIG_USER_ONLY)
/* Machine Timers and Counters */
[CSR_MCYCLE] = { any, read_instret },
[CSR_MINSTRET] = { any, read_instret },
-#if defined(TARGET_RISCV32)
- [CSR_MCYCLEH] = { any, read_instreth },
- [CSR_MINSTRETH] = { any, read_instreth },
-#endif
+ [CSR_MCYCLEH] = { any32, read_instreth },
+ [CSR_MINSTRETH] = { any32, read_instreth },
/* Machine Information Registers */
[CSR_MVENDORID] = { any, read_zero },
@@ -1410,9 +1422,7 @@
[CSR_MTVEC] = { any, read_mtvec, write_mtvec },
[CSR_MCOUNTEREN] = { any, read_mcounteren, write_mcounteren },
-#if defined(TARGET_RISCV32)
- [CSR_MSTATUSH] = { any, read_mstatush, write_mstatush },
-#endif
+ [CSR_MSTATUSH] = { any32, read_mstatush, write_mstatush },
[CSR_MSCOUNTEREN] = { any, read_mscounteren, write_mscounteren },
@@ -1452,9 +1462,7 @@
[CSR_HGEIP] = { hmode, read_hgeip, write_hgeip },
[CSR_HGATP] = { hmode, read_hgatp, write_hgatp },
[CSR_HTIMEDELTA] = { hmode, read_htimedelta, write_htimedelta },
-#if defined(TARGET_RISCV32)
- [CSR_HTIMEDELTAH] = { hmode, read_htimedeltah, write_htimedeltah},
-#endif
+ [CSR_HTIMEDELTAH] = { hmode32, read_htimedeltah, write_htimedeltah},
[CSR_VSSTATUS] = { hmode, read_vsstatus, write_vsstatus },
[CSR_VSIP] = { hmode, NULL, NULL, rmw_vsip },
@@ -1477,9 +1485,7 @@
[CSR_HPMCOUNTER3 ... CSR_HPMCOUNTER31] = { ctr, read_zero },
[CSR_MHPMCOUNTER3 ... CSR_MHPMCOUNTER31] = { any, read_zero },
[CSR_MHPMEVENT3 ... CSR_MHPMEVENT31] = { any, read_zero },
-#if defined(TARGET_RISCV32)
- [CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H] = { ctr, read_zero },
- [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] = { any, read_zero },
-#endif
+ [CSR_HPMCOUNTER3H ... CSR_HPMCOUNTER31H] = { ctr32, read_zero },
+ [CSR_MHPMCOUNTER3H ... CSR_MHPMCOUNTER31H] = { any32, read_zero },
#endif /* !CONFIG_USER_ONLY */
};
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index bb346a8..7c4ab92 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -223,7 +223,6 @@
return (int32_t)float32_to_uint32(frs1, &env->fp_status);
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
@@ -235,7 +234,6 @@
float32 frs1 = check_nanbox_s(rs1);
return float32_to_uint64(frs1, &env->fp_status);
}
-#endif
uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
{
@@ -247,7 +245,6 @@
return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status));
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1)
{
return nanbox_s(int64_to_float32(rs1, &env->fp_status));
@@ -257,7 +254,6 @@
{
return nanbox_s(uint64_to_float32(rs1, &env->fp_status));
}
-#endif
target_ulong helper_fclass_s(uint64_t rs1)
{
@@ -336,7 +332,6 @@
return (int32_t)float64_to_uint32(frs1, &env->fp_status);
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
{
return float64_to_int64(frs1, &env->fp_status);
@@ -346,7 +341,6 @@
{
return float64_to_uint64(frs1, &env->fp_status);
}
-#endif
uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
{
@@ -358,7 +352,6 @@
return uint32_to_float64((uint32_t)rs1, &env->fp_status);
}
-#if defined(TARGET_RISCV64)
uint64_t helper_fcvt_d_l(CPURISCVState *env, uint64_t rs1)
{
return int64_to_float64(rs1, &env->fp_status);
@@ -368,7 +361,6 @@
{
return uint64_to_float64(rs1, &env->fp_status);
}
-#endif
target_ulong helper_fclass_d(uint64_t frs1)
{
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 939731c..e3f3f41 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -27,16 +27,12 @@
DEF_HELPER_FLAGS_3(feq_s, TCG_CALL_NO_RWG, tl, env, i64, i64)
DEF_HELPER_FLAGS_2(fcvt_w_s, TCG_CALL_NO_RWG, tl, env, i64)
DEF_HELPER_FLAGS_2(fcvt_wu_s, TCG_CALL_NO_RWG, tl, env, i64)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_l_s, TCG_CALL_NO_RWG, tl, env, i64)
-DEF_HELPER_FLAGS_2(fcvt_lu_s, TCG_CALL_NO_RWG, tl, env, i64)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_l_s, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_lu_s, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(fcvt_s_w, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_s_wu, TCG_CALL_NO_RWG, i64, env, tl)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_s_l, TCG_CALL_NO_RWG, i64, env, tl)
-DEF_HELPER_FLAGS_2(fcvt_s_lu, TCG_CALL_NO_RWG, i64, env, tl)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_s_l, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_s_lu, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_1(fclass_s, TCG_CALL_NO_RWG_SE, tl, i64)
/* Floating Point - Double Precision */
@@ -54,16 +50,12 @@
DEF_HELPER_FLAGS_3(feq_d, TCG_CALL_NO_RWG, tl, env, i64, i64)
DEF_HELPER_FLAGS_2(fcvt_w_d, TCG_CALL_NO_RWG, tl, env, i64)
DEF_HELPER_FLAGS_2(fcvt_wu_d, TCG_CALL_NO_RWG, tl, env, i64)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_l_d, TCG_CALL_NO_RWG, tl, env, i64)
-DEF_HELPER_FLAGS_2(fcvt_lu_d, TCG_CALL_NO_RWG, tl, env, i64)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_l_d, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_lu_d, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(fcvt_d_w, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_d_wu, TCG_CALL_NO_RWG, i64, env, tl)
-#if defined(TARGET_RISCV64)
-DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, tl)
-DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, tl)
-#endif
+DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, i64)
+DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
/* Special functions */
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index b936939..4b22906 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -156,7 +156,9 @@
#define PS_IE (1<<1)
#define PS_AG (1<<0) /* v9, zero on UA2007 */
-#define FPRS_FEF (1<<2)
+#define FPRS_DL (1 << 0)
+#define FPRS_DU (1 << 1)
+#define FPRS_FEF (1 << 2)
#define HS_PRIV (1<<2)
#endif
@@ -606,10 +608,6 @@
void cpu_put_psr(CPUSPARCState *env1, target_ulong val);
void cpu_put_psr_raw(CPUSPARCState *env1, target_ulong val);
#ifdef TARGET_SPARC64
-target_ulong cpu_get_ccr(CPUSPARCState *env1);
-void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
-target_ulong cpu_get_cwp64(CPUSPARCState *env1);
-void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate);
void cpu_gl_switch_gregs(CPUSPARCState *env, uint32_t new_gl);
#endif
@@ -827,4 +825,24 @@
#endif
}
+#ifdef TARGET_SPARC64
+/* win_helper.c */
+target_ulong cpu_get_ccr(CPUSPARCState *env1);
+void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
+target_ulong cpu_get_cwp64(CPUSPARCState *env1);
+void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
+
+static inline uint64_t sparc64_tstate(CPUSPARCState *env)
+{
+ uint64_t tstate = (cpu_get_ccr(env) << 32) |
+ ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
+ cpu_get_cwp64(env);
+
+ if (env->def.features & CPU_FEATURE_GL) {
+ tstate |= (env->gl & 7ULL) << 40;
+ }
+ return tstate;
+}
+#endif
+
#endif
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index ba95bf2..7fb8ab2 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -131,9 +131,7 @@
}
tsptr = cpu_tsptr(env);
- tsptr->tstate = (cpu_get_ccr(env) << 32) |
- ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
- cpu_get_cwp64(env);
+ tsptr->tstate = sparc64_tstate(env);
tsptr->tpc = env->pc;
tsptr->tnpc = env->npc;
tsptr->tt = intno;
@@ -148,7 +146,6 @@
}
if (env->def.features & CPU_FEATURE_GL) {
- tsptr->tstate |= (env->gl & 7ULL) << 40;
cpu_gl_switch_gregs(env, env->gl + 1);
env->gl++;
}
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 30c73f8..4bfa317 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -2324,8 +2324,8 @@
}
/* in OpenSPARC T1+ CPUs TWINX ASIs in store instructions
* are ST_BLKINIT_ ASIs */
- /* fall through */
#endif
+ /* fall through */
case GET_ASI_DIRECT:
gen_address_mask(dc, addr);
tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop);
diff --git a/target/sparc/win_helper.c b/target/sparc/win_helper.c
index 5b57892..3a7c0ff 100644
--- a/target/sparc/win_helper.c
+++ b/target/sparc/win_helper.c
@@ -302,7 +302,7 @@
switch (pstate) {
default:
trace_win_helper_gregset_error(pstate);
- /* pass through to normal set of global registers */
+ /* fall through to normal set of global registers */
case 0:
return env->bgregs;
case PS_AG:
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index d4b06df..962f987 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -1801,6 +1801,7 @@
do_misc(env, s, insn);
break;
}
+ /* fallthrough */
case 0x1:
if (((UCOP_OPCODES >> 2) == 2) && !UCOP_SET_S) {
do_misc(env, s, insn);
@@ -1817,6 +1818,7 @@
if (UCOP_SET(8) || UCOP_SET(5)) {
ILLEGAL;
}
+ /* fallthrough */
case 0x3:
do_ldst_ir(env, s, insn);
break;
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 220f460..7ca71de 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -855,6 +855,7 @@
if ((arg_info(op->args[1])->mask & 0x80) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
CASE_OP_32_64(ext8u):
mask = 0xff;
goto and_const;
@@ -862,6 +863,7 @@
if ((arg_info(op->args[1])->mask & 0x8000) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
CASE_OP_32_64(ext16u):
mask = 0xffff;
goto and_const;
@@ -869,6 +871,7 @@
if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
case INDEX_op_ext32u_i64:
mask = 0xffffffffU;
goto and_const;
@@ -886,6 +889,7 @@
if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
break;
}
+ QEMU_FALLTHROUGH;
case INDEX_op_extu_i32_i64:
/* We do not compute affected as it is a size changing op. */
mask = (uint32_t)arg_info(op->args[1])->mask;
diff --git a/tests/fp/meson.build b/tests/fp/meson.build
index 3d4fb00..8d739c4 100644
--- a/tests/fp/meson.build
+++ b/tests/fp/meson.build
@@ -27,6 +27,7 @@
sfinc = include_directories(sfdir / 'include', sfspedir)
tfcflags = [
+ '-Wno-implicit-fallthrough',
'-Wno-strict-prototypes',
'-Wno-unknown-pragmas',
'-Wno-uninitialized',
@@ -209,6 +210,7 @@
)
sfcflags = [
+ '-Wno-implicit-fallthrough',
'-Wno-missing-prototypes',
'-Wno-redundant-decls',
'-Wno-return-type',
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index d4119e9..e94b711 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -2143,104 +2143,6 @@
send_reply_ok(req, NULL, 0);
}
-static int send_notify_iov(struct fuse_session *se, int notify_code,
- struct iovec *iov, int count)
-{
- struct fuse_out_header out = {
- .error = notify_code,
- };
-
- if (!se->got_init) {
- return -ENOTCONN;
- }
-
- iov[0].iov_base = &out;
- iov[0].iov_len = sizeof(struct fuse_out_header);
-
- return fuse_send_msg(se, NULL, iov, count);
-}
-
-int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
-{
- if (ph != NULL) {
- struct fuse_notify_poll_wakeup_out outarg = {
- .kh = ph->kh,
- };
- struct iovec iov[2];
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
-
- return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2);
- } else {
- return 0;
- }
-}
-
-int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino,
- off_t off, off_t len)
-{
- struct fuse_notify_inval_inode_out outarg = {
- .ino = ino,
- .off = off,
- .len = len,
- };
- struct iovec iov[2];
-
- if (!se) {
- return -EINVAL;
- }
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
-
- return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2);
-}
-
-int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent,
- const char *name, size_t namelen)
-{
- struct fuse_notify_inval_entry_out outarg = {
- .parent = parent,
- .namelen = namelen,
- };
- struct iovec iov[3];
-
- if (!se) {
- return -EINVAL;
- }
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
- iov[2].iov_base = (void *)name;
- iov[2].iov_len = namelen + 1;
-
- return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
-}
-
-int fuse_lowlevel_notify_delete(struct fuse_session *se, fuse_ino_t parent,
- fuse_ino_t child, const char *name,
- size_t namelen)
-{
- struct fuse_notify_delete_out outarg = {
- .parent = parent,
- .child = child,
- .namelen = namelen,
- };
- struct iovec iov[3];
-
- if (!se) {
- return -EINVAL;
- }
-
- iov[1].iov_base = &outarg;
- iov[1].iov_len = sizeof(outarg);
- iov[2].iov_base = (void *)name;
- iov[2].iov_len = namelen + 1;
-
- return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3);
-}
-
int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
off_t offset, struct fuse_bufvec *bufv)
{
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
index b264dcb..ddcefee 100644
--- a/tools/virtiofsd/fuse_virtio.c
+++ b/tools/virtiofsd/fuse_virtio.c
@@ -578,13 +578,18 @@
struct VuDev *dev = &qi->virtio_dev->dev;
struct VuVirtq *q = vu_get_queue(dev, qi->qidx);
struct fuse_session *se = qi->virtio_dev->se;
- GThreadPool *pool;
+ GThreadPool *pool = NULL;
+ GList *req_list = NULL;
- pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size, FALSE,
- NULL);
- if (!pool) {
- fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__);
- return NULL;
+ if (se->thread_pool_size) {
+ fuse_log(FUSE_LOG_DEBUG, "%s: Creating thread pool for Queue %d\n",
+ __func__, qi->qidx);
+ pool = g_thread_pool_new(fv_queue_worker, qi, se->thread_pool_size,
+ FALSE, NULL);
+ if (!pool) {
+ fuse_log(FUSE_LOG_ERR, "%s: g_thread_pool_new failed\n", __func__);
+ return NULL;
+ }
}
fuse_log(FUSE_LOG_INFO, "%s: Start for queue %d kick_fd %d\n", __func__,
@@ -659,14 +664,27 @@
req->reply_sent = false;
- g_thread_pool_push(pool, req, NULL);
+ if (!se->thread_pool_size) {
+ req_list = g_list_prepend(req_list, req);
+ } else {
+ g_thread_pool_push(pool, req, NULL);
+ }
}
pthread_mutex_unlock(&qi->vq_lock);
pthread_rwlock_unlock(&qi->virtio_dev->vu_dispatch_rwlock);
+
+ /* Process all the requests. */
+ if (!se->thread_pool_size && req_list != NULL) {
+ g_list_foreach(req_list, fv_queue_worker, qi);
+ g_list_free(req_list);
+ req_list = NULL;
+ }
}
- g_thread_pool_free(pool, FALSE, TRUE);
+ if (pool) {
+ g_thread_pool_free(pool, FALSE, TRUE);
+ }
return NULL;
}
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 12de321..5fb36d9 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -101,7 +101,7 @@
* This counter keeps the inode alive during the FUSE session.
* Incremented when the FUSE inode number is sent in a reply
* (FUSE_LOOKUP, FUSE_READDIRPLUS, etc). Decremented when an inode is
- * released by requests like FUSE_FORGET, FUSE_RMDIR, FUSE_RENAME, etc.
+ * released by a FUSE_FORGET request.
*
* Note that this value is untrusted because the client can manipulate
* it arbitrarily using FUSE_FORGET requests.
@@ -902,10 +902,11 @@
inode->key.ino = e->attr.st_ino;
inode->key.dev = e->attr.st_dev;
inode->key.mnt_id = mnt_id;
- pthread_mutex_init(&inode->plock_mutex, NULL);
- inode->posix_locks = g_hash_table_new_full(
- g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
-
+ if (lo->posix_lock) {
+ pthread_mutex_init(&inode->plock_mutex, NULL);
+ inode->posix_locks = g_hash_table_new_full(
+ g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
+ }
pthread_mutex_lock(&lo->mutex);
inode->fuse_ino = lo_add_inode_mapping(req, inode);
g_hash_table_insert(lo->inodes, &inode->key, inode);
@@ -1291,12 +1292,13 @@
if (!inode->nlookup) {
lo_map_remove(&lo->ino_map, inode->fuse_ino);
g_hash_table_remove(lo->inodes, &inode->key);
- if (g_hash_table_size(inode->posix_locks)) {
- fuse_log(FUSE_LOG_WARNING, "Hash table is not empty\n");
+ if (lo->posix_lock) {
+ if (g_hash_table_size(inode->posix_locks)) {
+ fuse_log(FUSE_LOG_WARNING, "Hash table is not empty\n");
+ }
+ g_hash_table_destroy(inode->posix_locks);
+ pthread_mutex_destroy(&inode->plock_mutex);
}
- g_hash_table_destroy(inode->posix_locks);
- pthread_mutex_destroy(&inode->plock_mutex);
-
/* Drop our refcount from lo_do_lookup() */
lo_inode_put(lo, &inode);
}
@@ -1772,6 +1774,11 @@
ino, fi->flags, fi->lock_owner, lock->l_type, lock->l_start,
lock->l_len);
+ if (!lo->posix_lock) {
+ fuse_reply_err(req, ENOSYS);
+ return;
+ }
+
inode = lo_inode(req, ino);
if (!inode) {
fuse_reply_err(req, EBADF);
@@ -1817,6 +1824,11 @@
ino, fi->flags, lock->l_type, lock->l_pid, fi->lock_owner, sleep,
lock->l_whence, lock->l_start, lock->l_len);
+ if (!lo->posix_lock) {
+ fuse_reply_err(req, ENOSYS);
+ return;
+ }
+
if (sleep) {
fuse_reply_err(req, EOPNOTSUPP);
return;
@@ -1941,6 +1953,7 @@
int res;
(void)ino;
struct lo_inode *inode;
+ struct lo_data *lo = lo_data(req);
inode = lo_inode(req, ino);
if (!inode) {
@@ -1948,13 +1961,21 @@
return;
}
- /* An fd is going away. Cleanup associated posix locks */
- pthread_mutex_lock(&inode->plock_mutex);
- g_hash_table_remove(inode->posix_locks, GUINT_TO_POINTER(fi->lock_owner));
- pthread_mutex_unlock(&inode->plock_mutex);
+ if (!S_ISREG(inode->filetype)) {
+ lo_inode_put(lo, &inode);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
+ /* An fd is going away. Cleanup associated posix locks */
+ if (lo->posix_lock) {
+ pthread_mutex_lock(&inode->plock_mutex);
+ g_hash_table_remove(inode->posix_locks,
+ GUINT_TO_POINTER(fi->lock_owner));
+ pthread_mutex_unlock(&inode->plock_mutex);
+ }
res = close(dup(lo_fi_fd(req, fi)));
- lo_inode_put(lo_data(req), &inode);
+ lo_inode_put(lo, &inode);
fuse_reply_err(req, res == -1 ? errno : 0);
}
@@ -3284,18 +3305,38 @@
static void log_func(enum fuse_log_level level, const char *fmt, va_list ap)
{
g_autofree char *localfmt = NULL;
+ struct timespec ts;
+ struct tm tm;
+ char sec_fmt[sizeof "2020-12-07 18:17:54"];
+ char zone_fmt[sizeof "+0100"];
if (current_log_level < level) {
return;
}
if (current_log_level == FUSE_LOG_DEBUG) {
- if (!use_syslog) {
- localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s",
- get_clock(), syscall(__NR_gettid), fmt);
- } else {
+ if (use_syslog) {
+ /* no timestamp needed */
localfmt = g_strdup_printf("[ID: %08ld] %s", syscall(__NR_gettid),
fmt);
+ } else {
+ /* try formatting a broken-down timestamp */
+ if (clock_gettime(CLOCK_REALTIME, &ts) != -1 &&
+ localtime_r(&ts.tv_sec, &tm) != NULL &&
+ strftime(sec_fmt, sizeof sec_fmt, "%Y-%m-%d %H:%M:%S",
+ &tm) != 0 &&
+ strftime(zone_fmt, sizeof zone_fmt, "%z", &tm) != 0) {
+ localfmt = g_strdup_printf("[%s.%02ld%s] [ID: %08ld] %s",
+ sec_fmt,
+ ts.tv_nsec / (10L * 1000 * 1000),
+ zone_fmt, syscall(__NR_gettid),
+ fmt);
+ } else {
+ /* fall back to a flat timestamp */
+ localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s",
+ get_clock(), syscall(__NR_gettid),
+ fmt);
+ }
}
fmt = localfmt;
}
@@ -3360,6 +3401,11 @@
root->key.mnt_id = mnt_id;
root->nlookup = 2;
g_atomic_int_set(&root->refcount, 2);
+ if (lo->posix_lock) {
+ pthread_mutex_init(&root->plock_mutex, NULL);
+ root->posix_locks = g_hash_table_new_full(
+ g_direct_hash, g_direct_equal, NULL, posix_locks_value_destroy);
+ }
}
static guint lo_key_hash(gconstpointer key)
@@ -3382,6 +3428,10 @@
if (lo->inodes) {
g_hash_table_destroy(lo->inodes);
}
+
+ if (lo->root.posix_locks) {
+ g_hash_table_destroy(lo->root.posix_locks);
+ }
lo_map_destroy(&lo->fd_map);
lo_map_destroy(&lo->dirp_map);
lo_map_destroy(&lo->ino_map);
@@ -3416,6 +3466,9 @@
struct lo_map_elem *reserve_elem;
int ret = -1;
+ /* Initialize time conversion information for localtime_r(). */
+ tzset();
+
/* Don't mask creation mode, kernel already did that */
umask(0);