Merge tag 'misc-fixes-20230725' of https://github.com/philmd/qemu into staging
Misc patches queue
hw/sd/sdhci: Default I/O ops to little endian
hw/mips/loongson3-virt: Only use default USB if available
hw/char/escc: Implement loopback mode to allow self-testing
target/mips: Avoid overruns and shifts by negative number
target/sparc: Handle FPRS correctly on big-endian hosts
target/tricore: Rename tricore_feature to avoid clash with libcapstone
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmS/4ksACgkQ4+MsLN6t
# wN6OSg//cZY9C6fRXNNaIqkmnhjbaV6KLtjE7mOKp0RUyh3aN0dtTwWIjdJc0O5C
# iipHESYhcbHTiN/TxK0zXg4KgtKmtwqGsa3QTXGdTlSkTY/dMNioSpb7p82becu0
# fhCvGRLJ97j7/mhebiBNT/urrcG5h3n7CjA5IoFMMA4f+cajsGZHwmq5TTzc2ehy
# 4FuchjFUw+cgqU1peNYoqt2dfnxFg0EgKBSRikl8MyPf9lFzTlXOKbgd+qppG6hI
# 2fAUHyMqBkU22sAoK0eB0077LjgjPPQfmn8UPGkpGD5QZQcvBRNArg4fyHxCKTS7
# zOsO1Qc+4D2l2RJlIHgct2pmcHdT29TlTn2T4Lg900Hm09KelZh1XF+1BemCC13z
# cGWjPcYozvGFFiHlhazINtbGpB6XaP/Z3OwroRHRn+Mn3ss+FaU+j/p+4YlEVyFi
# 4yoEyjhNma6/hssmstifSQsaOf6XthzpS+XdKNB6G1b2WuRSc1Z59b2gcPBTwbXY
# B52lfI61nzSrP9pLuS8c/6hQXQvADIEndeWEcWZ50h3WW2Cemj9jTDVgfjWC4Vg9
# wV2U6NeTr+g54cSU5vcKiZrqsQHUoLiKbZFRJkXF7EEMbOErIQnyIS5l8xf71Pay
# YPxuPf1VprRiR07d+ZaA+wmEaBxLCUPEl1CEuu5NPVA9S4yIIWE=
# =F+Wb
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 25 Jul 2023 15:55:07 BST
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE
* tag 'misc-fixes-20230725' of https://github.com/philmd/qemu:
target/tricore: Rename tricore_feature
target/sparc: Handle FPRS correctly on big-endian hosts
target/mips: Avoid shift by negative number in page_table_walk_refill()
target/mips: Pass directory/leaf shift values to walk_directory()
target/mips/mxu: Avoid overrun in gen_mxu_q8adde()
target/mips/mxu: Avoid overrun in gen_mxu_S32SLT()
target/mips/mxu: Replace magic array size by its definition
hw/char/escc: Implement loopback mode
hw/mips: Improve the default USB settings in the loongson3-virt machine
hw/sd/sdhci: Do not force sdhci_mmio_*_ops onto all SD controllers
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 4f3872b..4be6605 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -653,7 +653,9 @@
escc_update_irq(s);
s->tx = val;
if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { /* tx enabled */
- if (qemu_chr_fe_backend_connected(&s->chr)) {
+ if (s->wregs[W_MISC2] & MISC2_LCL_LOOP) {
+ serial_receive_byte(s, s->tx);
+ } else if (qemu_chr_fe_backend_connected(&s->chr)) {
/*
* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 4018b8c..3ad0a22 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -447,7 +447,7 @@
pci_vga_init(pci_bus);
- if (defaults_enabled()) {
+ if (defaults_enabled() && object_class_by_name("pci-ohci")) {
pci_create_simple(pci_bus, -1, "pci-ohci");
usb_create_simple(usb_bus_find(-1), "usb-kbd");
usb_create_simple(usb_bus_find(-1), "usb-tablet");
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 6811f0f..362c2c8 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1382,6 +1382,8 @@
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
+
+ s->io_ops = &sdhci_mmio_le_ops;
}
void sdhci_uninitfn(SDHCIState *s)
@@ -1399,9 +1401,13 @@
switch (s->endianness) {
case DEVICE_LITTLE_ENDIAN:
- s->io_ops = &sdhci_mmio_le_ops;
+ /* s->io_ops is little endian by default */
break;
case DEVICE_BIG_ENDIAN:
+ if (s->io_ops != &sdhci_mmio_le_ops) {
+ error_setg(errp, "SD controller doesn't support big endianness");
+ return;
+ }
s->io_ops = &sdhci_mmio_be_ops;
break;
default:
diff --git a/target/mips/tcg/mxu_translate.c b/target/mips/tcg/mxu_translate.c
index deb8060..e662acd 100644
--- a/target/mips/tcg/mxu_translate.c
+++ b/target/mips/tcg/mxu_translate.c
@@ -609,7 +609,7 @@
static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
static TCGv mxu_CR;
-static const char mxuregnames[][4] = {
+static const char mxuregnames[NUMBER_OF_MXU_REGISTERS][4] = {
"XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
"XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "XCR",
};
@@ -644,6 +644,16 @@
}
}
+static inline void gen_extract_mxu_gpr(TCGv t, unsigned int reg,
+ unsigned int ofs, unsigned int len)
+{
+ if (reg == 0) {
+ tcg_gen_movi_tl(t, 0);
+ } else if (reg <= 15) {
+ tcg_gen_extract_tl(t, mxu_gpr[reg - 1], ofs, len);
+ }
+}
+
/* MXU control register moves. */
static inline void gen_load_mxu_cr(TCGv t)
{
@@ -2434,8 +2444,12 @@
tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
} else {
/* the most general case */
- tcg_gen_setcond_tl(TCG_COND_LT, mxu_gpr[XRa - 1],
- mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+
+ gen_load_mxu_gpr(t0, XRb);
+ gen_load_mxu_gpr(t1, XRc);
+ tcg_gen_setcond_tl(TCG_COND_LT, mxu_gpr[XRa - 1], t0, t1);
}
}
@@ -3000,10 +3014,10 @@
TCGv t5 = tcg_temp_new();
if (XRa != 0) {
- tcg_gen_extract_tl(t0, mxu_gpr[XRb - 1], 16, 8);
- tcg_gen_extract_tl(t1, mxu_gpr[XRc - 1], 16, 8);
- tcg_gen_extract_tl(t2, mxu_gpr[XRb - 1], 24, 8);
- tcg_gen_extract_tl(t3, mxu_gpr[XRc - 1], 24, 8);
+ gen_extract_mxu_gpr(t0, XRb, 16, 8);
+ gen_extract_mxu_gpr(t1, XRc, 16, 8);
+ gen_extract_mxu_gpr(t2, XRb, 24, 8);
+ gen_extract_mxu_gpr(t3, XRc, 24, 8);
if (aptn2 & 2) {
tcg_gen_sub_tl(t0, t0, t1);
tcg_gen_sub_tl(t2, t2, t3);
@@ -3023,10 +3037,10 @@
tcg_gen_or_tl(t4, t2, t0);
}
if (XRd != 0) {
- tcg_gen_extract_tl(t0, mxu_gpr[XRb - 1], 0, 8);
- tcg_gen_extract_tl(t1, mxu_gpr[XRc - 1], 0, 8);
- tcg_gen_extract_tl(t2, mxu_gpr[XRb - 1], 8, 8);
- tcg_gen_extract_tl(t3, mxu_gpr[XRc - 1], 8, 8);
+ gen_extract_mxu_gpr(t0, XRb, 0, 8);
+ gen_extract_mxu_gpr(t1, XRc, 0, 8);
+ gen_extract_mxu_gpr(t2, XRb, 8, 8);
+ gen_extract_mxu_gpr(t3, XRc, 8, 8);
if (aptn2 & 1) {
tcg_gen_sub_tl(t0, t0, t1);
tcg_gen_sub_tl(t2, t2, t3);
diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c
index e5e1e9d..7dbc2e2 100644
--- a/target/mips/tcg/sysemu/tlb_helper.c
+++ b/target/mips/tcg/sysemu/tlb_helper.c
@@ -623,18 +623,13 @@
static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
int directory_index, bool *huge_page, bool *hgpg_directory_hit,
- uint64_t *pw_entrylo0, uint64_t *pw_entrylo1)
+ uint64_t *pw_entrylo0, uint64_t *pw_entrylo1,
+ unsigned directory_shift, unsigned leaf_shift)
{
int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1;
int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F;
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;
int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
- int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F;
- int native_shift = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? 2 : 3;
- int directory_shift = (ptew > 1) ? -1 :
- (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
- int leaf_shift = (ptew > 1) ? -1 :
- (ptew == 1) ? native_shift + 1 : native_shift;
uint32_t direntry_size = 1 << (directory_shift + 3);
uint32_t leafentry_size = 1 << (leaf_shift + 3);
uint64_t entry;
@@ -735,21 +730,11 @@
/* Other HTW configs */
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;
-
- /* HTW Shift values (depend on entry size) */
- int directory_shift = (ptew > 1) ? -1 :
- (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
- int leaf_shift = (ptew > 1) ? -1 :
- (ptew == 1) ? native_shift + 1 : native_shift;
+ unsigned directory_shift, leaf_shift;
/* Offsets into tables */
- int goffset = gindex << directory_shift;
- int uoffset = uindex << directory_shift;
- int moffset = mindex << directory_shift;
- int ptoffset0 = (ptindex >> 1) << (leaf_shift + 1);
- int ptoffset1 = ptoffset0 | (1 << (leaf_shift));
-
- uint32_t leafentry_size = 1 << (leaf_shift + 3);
+ unsigned goffset, uoffset, moffset, ptoffset0, ptoffset1;
+ uint32_t leafentry_size;
/* Starting address - Page Table Base */
uint64_t vaddr = env->CP0_PWBase;
@@ -771,15 +756,28 @@
/* no structure to walk */
return false;
}
- if ((directory_shift == -1) || (leaf_shift == -1)) {
+ if (ptew > 1) {
return false;
}
+ /* HTW Shift values (depend on entry size) */
+ directory_shift = (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
+ leaf_shift = (ptew == 1) ? native_shift + 1 : native_shift;
+
+ goffset = gindex << directory_shift;
+ uoffset = uindex << directory_shift;
+ moffset = mindex << directory_shift;
+ ptoffset0 = (ptindex >> 1) << (leaf_shift + 1);
+ ptoffset1 = ptoffset0 | (1 << (leaf_shift));
+
+ leafentry_size = 1 << (leaf_shift + 3);
+
/* Global Directory */
if (gdw > 0) {
vaddr |= goffset;
switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit,
- &pw_entrylo0, &pw_entrylo1))
+ &pw_entrylo0, &pw_entrylo1,
+ directory_shift, leaf_shift))
{
case 0:
return false;
@@ -795,7 +793,8 @@
if (udw > 0) {
vaddr |= uoffset;
switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit,
- &pw_entrylo0, &pw_entrylo1))
+ &pw_entrylo0, &pw_entrylo1,
+ directory_shift, leaf_shift))
{
case 0:
return false;
@@ -811,7 +810,8 @@
if (mdw > 0) {
vaddr |= moffset;
switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit,
- &pw_entrylo0, &pw_entrylo1))
+ &pw_entrylo0, &pw_entrylo1,
+ directory_shift, leaf_shift))
{
case 0:
return false;
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index e329a7a..130ab8f 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -673,8 +673,8 @@
"cleanwin: %d cwp: %d\n",
env->cansave, env->canrestore, env->otherwin, env->wstate,
env->cleanwin, env->nwindows - 1 - env->cwp);
- qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
- TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
+ qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: %016x\n",
+ env->fsr, env->y, env->fprs);
#else
qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 95d2d0d..9804457 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -521,7 +521,7 @@
uint64_t igregs[8]; /* interrupt general registers */
uint64_t mgregs[8]; /* mmu general registers */
uint64_t glregs[8 * MAXTL_MAX];
- uint64_t fprs;
+ uint32_t fprs;
uint64_t tick_cmpr, stick_cmpr;
CPUTimer *tick, *stick;
#define TICK_NPT_MASK 0x8000000000000000ULL
diff --git a/target/sparc/machine.c b/target/sparc/machine.c
index 44b9e7d..274e121 100644
--- a/target/sparc/machine.c
+++ b/target/sparc/machine.c
@@ -168,7 +168,8 @@
VMSTATE_UINT64_ARRAY(env.bgregs, SPARCCPU, 8),
VMSTATE_UINT64_ARRAY(env.igregs, SPARCCPU, 8),
VMSTATE_UINT64_ARRAY(env.mgregs, SPARCCPU, 8),
- VMSTATE_UINT64(env.fprs, SPARCCPU),
+ VMSTATE_UNUSED(4), /* was unused high half of uint64_t fprs */
+ VMSTATE_UINT32(env.fprs, SPARCCPU),
VMSTATE_UINT64(env.tick_cmpr, SPARCCPU),
VMSTATE_UINT64(env.stick_cmpr, SPARCCPU),
VMSTATE_CPU_TIMER(env.tick, SPARCCPU),
diff --git a/target/sparc/monitor.c b/target/sparc/monitor.c
index 3184136..73f15aa 100644
--- a/target/sparc/monitor.c
+++ b/target/sparc/monitor.c
@@ -154,7 +154,7 @@
{ "otherwin", offsetof(CPUSPARCState, otherwin) },
{ "wstate", offsetof(CPUSPARCState, wstate) },
{ "cleanwin", offsetof(CPUSPARCState, cleanwin) },
- { "fprs", offsetof(CPUSPARCState, fprs) },
+ { "fprs", offsetof(CPUSPARCState, fprs), NULL, MD_I32 },
#endif
{ NULL },
};
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index f15169b..133a9ac 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -104,18 +104,18 @@
}
/* Some features automatically imply others */
- if (tricore_feature(env, TRICORE_FEATURE_162)) {
+ if (tricore_has_feature(env, TRICORE_FEATURE_162)) {
set_feature(env, TRICORE_FEATURE_161);
}
- if (tricore_feature(env, TRICORE_FEATURE_161)) {
+ if (tricore_has_feature(env, TRICORE_FEATURE_161)) {
set_feature(env, TRICORE_FEATURE_16);
}
- if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ if (tricore_has_feature(env, TRICORE_FEATURE_16)) {
set_feature(env, TRICORE_FEATURE_131);
}
- if (tricore_feature(env, TRICORE_FEATURE_131)) {
+ if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
set_feature(env, TRICORE_FEATURE_13);
}
cpu_reset(cs);
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index a50b91c..3708405 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -277,7 +277,7 @@
TRICORE_FEATURE_162,
};
-static inline int tricore_feature(CPUTriCoreState *env, int feature)
+static inline int tricore_has_feature(CPUTriCoreState *env, int feature)
{
return (env->features & (1ULL << feature)) != 0;
}
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
index 951024d..731a6e9 100644
--- a/target/tricore/helper.c
+++ b/target/tricore/helper.c
@@ -155,7 +155,7 @@
#define FIELD_GETTER_WITH_FEATURE(NAME, REG, FIELD, FEATURE) \
uint32_t NAME(CPUTriCoreState *env) \
{ \
- if (tricore_feature(env, TRICORE_FEATURE_##FEATURE)) { \
+ if (tricore_has_feature(env, TRICORE_FEATURE_##FEATURE)) { \
return FIELD_EX32(env->REG, REG, FIELD ## _ ## FEATURE); \
} \
return FIELD_EX32(env->REG, REG, FIELD ## _13); \
@@ -170,7 +170,7 @@
#define FIELD_SETTER_WITH_FEATURE(NAME, REG, FIELD, FEATURE) \
void NAME(CPUTriCoreState *env, uint32_t val) \
{ \
- if (tricore_feature(env, TRICORE_FEATURE_##FEATURE)) { \
+ if (tricore_has_feature(env, TRICORE_FEATURE_##FEATURE)) { \
env->REG = FIELD_DP32(env->REG, REG, FIELD ## _ ## FEATURE, val); \
} \
env->REG = FIELD_DP32(env->REG, REG, FIELD ## _13, val); \
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index 821a4b6..89be1ed 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -2584,7 +2584,7 @@
/* PCXI = new_PCXI; */
env->PCXI = new_PCXI;
- if (tricore_feature(env, TRICORE_FEATURE_131)) {
+ if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
/* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */
psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000)));
} else { /* TRICORE_FEATURE_13 only */
@@ -2695,7 +2695,7 @@
env->gpr_a[10] = cpu_ldl_data(env, env->DCX+8);
env->gpr_a[11] = cpu_ldl_data(env, env->DCX+12);
- if (tricore_feature(env, TRICORE_FEATURE_131)) {
+ if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
env->DBGTCR = 0;
}
}