From 709616c713f9471a993ad7d16bce23e8b88ce958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:44 +0200 Subject: [PATCH 01/44] util/cutils: Introduce freq_to_str() to display Hertz units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce freq_to_str() to convert frequency values in human friendly units using the SI units for Hertz. Suggested-by: Luc Michel Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Reviewed-by: Luc Michel Message-Id: <20201012095804.3335117-2-f4bug@amsat.org> --- include/qemu/cutils.h | 12 ++++++++++++ util/cutils.c | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index 3a86ec0321..4bbf4834ea 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -158,6 +158,18 @@ int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result); char *size_to_str(uint64_t val); +/** + * freq_to_str: + * @freq_hz: frequency to stringify + * + * Return human readable string for frequency @freq_hz. + * Use SI units like KHz, MHz, and so forth. + * + * The caller is responsible for releasing the value returned + * with g_free() after use. + */ +char *freq_to_str(uint64_t freq_hz); + /* used to print char* safely */ #define STR_OR_NULL(str) ((str) ? (str) : "null") diff --git a/util/cutils.c b/util/cutils.c index 8da34e04b0..be4e43a9ef 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -885,6 +885,20 @@ char *size_to_str(uint64_t val) return g_strdup_printf("%0.3g %sB", (double)val / div, suffixes[i]); } +char *freq_to_str(uint64_t freq_hz) +{ + static const char *const suffixes[] = { "", "K", "M", "G", "T", "P", "E" }; + double freq = freq_hz; + size_t idx = 0; + + while (freq >= 1000.0 && idx < ARRAY_SIZE(suffixes)) { + freq /= 1000.0; + idx++; + } + + return g_strdup_printf("%0.3g %sHz", freq, suffixes[idx]); +} + int qemu_pstrcmp0(const char **str1, const char **str2) { return g_strcmp0(*str1, *str2); From 01d858629eae532f50f3dac6df9e6ab912626e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:46 +0200 Subject: [PATCH 02/44] hw/qdev-clock: Display error hint when clock is missing from device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of directly aborting, display a hint to help the developer figure out the problem (likely trying to connect a clock to a device pre-dating the Clock API, thus not expecting clocks). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Luc Michel Reviewed-by: Damien Hedde Reviewed-by: Edgar E. Iglesias Message-Id: <20201012095804.3335117-4-f4bug@amsat.org> --- hw/core/qdev-clock.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c index 47ecb5b4fa..6a9a340d0f 100644 --- a/hw/core/qdev-clock.c +++ b/hw/core/qdev-clock.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "hw/qdev-clock.h" #include "hw/qdev-core.h" #include "qapi/error.h" @@ -153,6 +154,11 @@ Clock *qdev_get_clock_in(DeviceState *dev, const char *name) assert(name); ncl = qdev_get_clocklist(dev, name); + if (!ncl) { + error_report("Can not find clock-in '%s' for device type '%s'", + name, object_get_typename(OBJECT(dev))); + abort(); + } assert(!ncl->output); return ncl->clock; @@ -165,6 +171,11 @@ Clock *qdev_get_clock_out(DeviceState *dev, const char *name) assert(name); ncl = qdev_get_clocklist(dev, name); + if (!ncl) { + error_report("Can not find clock-out '%s' for device type '%s'", + name, object_get_typename(OBJECT(dev))); + abort(); + } assert(ncl->output); return ncl->clock; From 5ebc664800b66f886f58cd4d5bcc7785644c9980 Mon Sep 17 00:00:00 2001 From: Luc Michel Date: Mon, 12 Oct 2020 11:57:47 +0200 Subject: [PATCH 03/44] hw/core/clock: Add the clock_new helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function creates a clock and parents it to another object with a given name. It calls clock_setup_canonical_path before returning the new clock. This function is useful to create clocks in devices when one doesn't want to expose it at the qdev level (as an input or an output). Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Luc Michel Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201010135759.437903-4-luc@lmichel.fr> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/clock.c | 15 +++++++++++++++ include/hw/clock.h | 13 +++++++++++++ 2 files changed, 28 insertions(+) diff --git a/hw/core/clock.c b/hw/core/clock.c index 7066282f7b..f866717a83 100644 --- a/hw/core/clock.c +++ b/hw/core/clock.c @@ -23,6 +23,21 @@ void clock_setup_canonical_path(Clock *clk) clk->canonical_path = object_get_canonical_path(OBJECT(clk)); } +Clock *clock_new(Object *parent, const char *name) +{ + Object *obj; + Clock *clk; + + obj = object_new(TYPE_CLOCK); + object_property_add_child(parent, name, obj); + object_unref(obj); + + clk = CLOCK(obj); + clock_setup_canonical_path(clk); + + return clk; +} + void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque) { clk->callback = cb; diff --git a/include/hw/clock.h b/include/hw/clock.h index d357594df9..cbc5e6ced1 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -90,6 +90,19 @@ extern const VMStateDescription vmstate_clock; */ void clock_setup_canonical_path(Clock *clk); +/** + * clock_new: + * @parent: the clock parent + * @name: the clock object name + * + * Helper function to create a new clock and parent it to @parent. There is no + * need to call clock_setup_canonical_path on the returned clock as it is done + * by this function. + * + * @return the newly created clock + */ +Clock *clock_new(Object *parent, const char *name); + /** * clock_set_callback: * @clk: the clock to register the callback into From 8cdf88690dc79511cfa1b2557434c09e3685f090 Mon Sep 17 00:00:00 2001 From: zhaolichang Date: Fri, 9 Oct 2020 14:44:41 +0800 Subject: [PATCH 04/44] target/mips: Fix some comment spelling errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many spelling errors in the comments in target/mips/. Use spellcheck to check the spelling errors. Signed-off-by: zhaolichang Reviewed-by: David Edmondson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201009064449.2336-7-zhaolichang@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/internal.h | 2 +- target/mips/translate.c | 10 +++++----- target/mips/translate_init.c.inc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/mips/internal.h b/target/mips/internal.h index 7f159a9230..b811f547f3 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -188,7 +188,7 @@ static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) /* * A MIPS configured with a vectorizing external interrupt controller * will feed a vector into the Cause pending lines. The core treats - * the status lines as a vector level, not as indiviual masks. + * the status lines as a vector level, not as individual masks. */ r = pending > status; } else { diff --git a/target/mips/translate.c b/target/mips/translate.c index 398edf7289..b4d009078e 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -3718,7 +3718,7 @@ static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset, t0 = tcg_temp_new(); addr = tcg_temp_new(); - /* compare the address against that of the preceeding LL */ + /* compare the address against that of the preceding LL */ gen_base_offset_addr(ctx, addr, base, offset); tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1); tcg_temp_free(addr); @@ -25597,7 +25597,7 @@ static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) } /* return resulting half-words to its original position */ tcg_gen_shri_i32(t0, t0, 16); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); tcg_temp_free(t1); @@ -25633,7 +25633,7 @@ static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx) } /* return resulting half-words to its original position */ tcg_gen_shri_i32(t0, t0, 16); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); tcg_temp_free(t1); @@ -25702,7 +25702,7 @@ static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) } /* return resulting byte to its original position */ tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); } @@ -25742,7 +25742,7 @@ static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx) } /* return resulting byte to its original position */ tcg_gen_shri_i32(t0, t0, 8 * (3 - i)); - /* finaly update the destination */ + /* finally update the destination */ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0); } diff --git a/target/mips/translate_init.c.inc b/target/mips/translate_init.c.inc index 637caccd89..c735b2bf66 100644 --- a/target/mips/translate_init.c.inc +++ b/target/mips/translate_init.c.inc @@ -995,7 +995,7 @@ static void mvp_init (CPUMIPSState *env, const mips_def_t *def) /* MVPConf1 implemented, TLB sharable, no gating storage support, programmable cache partitioning implemented, number of allocatable - and sharable TLB entries, MVP has allocatable TCs, 2 VPEs + and shareable TLB entries, MVP has allocatable TCs, 2 VPEs implemented, 5 TCs implemented. */ env->mvp->CP0_MVPConf0 = (1U << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) | (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) | From 8a6c9e0fdd10dce2240b2058fdedc5557e36adbd Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic Date: Wed, 7 Oct 2020 22:37:17 +0200 Subject: [PATCH 05/44] target/mips: Demacro helpers for . MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove function definitions via macros to achieve better code clarity. Signed-off-by: Aleksandar Markovic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <1602103041-32017-2-git-send-email-aleksandar.qemu.devel@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/fpu_helper.c | 59 ++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index 56beda49d8..f851723f22 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -983,27 +983,46 @@ uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0) } /* unary operations, not modifying fp status */ -#define FLOAT_UNOP(name) \ -uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \ -{ \ - return float64_ ## name(fdt0); \ -} \ -uint32_t helper_float_ ## name ## _s(uint32_t fst0) \ -{ \ - return float32_ ## name(fst0); \ -} \ -uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \ -{ \ - uint32_t wt0; \ - uint32_t wth0; \ - \ - wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \ - wth0 = float32_ ## name(fdt0 >> 32); \ - return ((uint64_t)wth0 << 32) | wt0; \ + +uint64_t helper_float_abs_d(uint64_t fdt0) +{ + return float64_abs(fdt0); +} + +uint32_t helper_float_abs_s(uint32_t fst0) +{ + return float32_abs(fst0); +} + +uint64_t helper_float_abs_ps(uint64_t fdt0) +{ + uint32_t wt0; + uint32_t wth0; + + wt0 = float32_abs(fdt0 & 0XFFFFFFFF); + wth0 = float32_abs(fdt0 >> 32); + return ((uint64_t)wth0 << 32) | wt0; +} + +uint64_t helper_float_chs_d(uint64_t fdt0) +{ + return float64_chs(fdt0); +} + +uint32_t helper_float_chs_s(uint32_t fst0) +{ + return float32_chs(fst0); +} + +uint64_t helper_float_chs_ps(uint64_t fdt0) +{ + uint32_t wt0; + uint32_t wth0; + + wt0 = float32_chs(fdt0 & 0XFFFFFFFF); + wth0 = float32_chs(fdt0 >> 32); + return ((uint64_t)wth0 << 32) | wt0; } -FLOAT_UNOP(abs) -FLOAT_UNOP(chs) -#undef FLOAT_UNOP /* MIPS specific unary operations */ uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) From be0cb99426badb2fa0b02404144b2b80ac82f4c9 Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic Date: Wed, 7 Oct 2020 22:37:18 +0200 Subject: [PATCH 06/44] target/mips: Demacro helpers for MF. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove function definitions via macros to achieve better code clarity. Signed-off-by: Aleksandar Markovic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <1602103041-32017-3-git-send-email-aleksandar.qemu.devel@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/fpu_helper.c | 63 +++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index f851723f22..b3c715494a 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -1666,25 +1666,54 @@ uint64_t helper_float_nmsub_ps(CPUMIPSState *env, uint64_t fdt0, } -#define FLOAT_FMADDSUB(name, bits, muladd_arg) \ -uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ - uint ## bits ## _t fs, \ - uint ## bits ## _t ft, \ - uint ## bits ## _t fd) \ -{ \ - uint ## bits ## _t fdret; \ - \ - fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ - &env->active_fpu.fp_status); \ - update_fcr31(env, GETPC()); \ - return fdret; \ +uint32_t helper_float_maddf_s(CPUMIPSState *env, uint32_t fs, + uint32_t ft, uint32_t fd) +{ + uint32_t fdret; + + fdret = float32_muladd(fs, ft, fd, 0, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_maddf_d(CPUMIPSState *env, uint64_t fs, + uint64_t ft, uint64_t fd) +{ + uint64_t fdret; + + fdret = float64_muladd(fs, ft, fd, 0, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_msubf_s(CPUMIPSState *env, uint32_t fs, + uint32_t ft, uint32_t fd) +{ + uint32_t fdret; + + fdret = float32_muladd(fs, ft, fd, float_muladd_negate_product, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_msubf_d(CPUMIPSState *env, uint64_t fs, + uint64_t ft, uint64_t fd) +{ + uint64_t fdret; + + fdret = float64_muladd(fs, ft, fd, float_muladd_negate_product, + &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; } -FLOAT_FMADDSUB(maddf_s, 32, 0) -FLOAT_FMADDSUB(maddf_d, 64, 0) -FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product) -FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product) -#undef FLOAT_FMADDSUB /* compare operations */ #define FOP_COND_D(op, cond) \ From 32eb97b5eb24c1fc1a1c366f25e1ffe31f0e096a Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic Date: Wed, 7 Oct 2020 22:37:19 +0200 Subject: [PATCH 07/44] target/mips: Demacro helpers for . MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove function definitions via macros to achieve better code clarity. Signed-off-by: Aleksandar Markovic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <1602103041-32017-4-git-send-email-aleksandar.qemu.devel@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/fpu_helper.c | 98 ++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 20 deletions(-) diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index b3c715494a..6cc956c023 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -1475,29 +1475,87 @@ uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) return ((uint64_t)fsth2 << 32) | fstl2; } -#define FLOAT_MINMAX(name, bits, minmaxfunc) \ -uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ - uint ## bits ## _t fs, \ - uint ## bits ## _t ft) \ -{ \ - uint ## bits ## _t fdret; \ - \ - fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ - &env->active_fpu.fp_status); \ - update_fcr31(env, GETPC()); \ - return fdret; \ + +uint32_t helper_float_max_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_maxnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; } -FLOAT_MINMAX(max_s, 32, maxnum) -FLOAT_MINMAX(max_d, 64, maxnum) -FLOAT_MINMAX(maxa_s, 32, maxnummag) -FLOAT_MINMAX(maxa_d, 64, maxnummag) +uint64_t helper_float_max_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_maxnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_maxa_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_maxnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_maxa_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_maxnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_min_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_minnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_min_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_minnum(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint32_t helper_float_mina_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) +{ + uint32_t fdret; + + fdret = float32_minnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} + +uint64_t helper_float_mina_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) +{ + uint64_t fdret; + + fdret = float64_minnummag(fs, ft, &env->active_fpu.fp_status); + + update_fcr31(env, GETPC()); + return fdret; +} -FLOAT_MINMAX(min_s, 32, minnum) -FLOAT_MINMAX(min_d, 64, minnum) -FLOAT_MINMAX(mina_s, 32, minnummag) -FLOAT_MINMAX(mina_d, 64, minnummag) -#undef FLOAT_MINMAX /* ternary operations */ From e10a0ca17dfeac25afb58f163b99d784b88d4e23 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Fri, 16 Oct 2020 14:51:54 +0800 Subject: [PATCH 08/44] target/mips: Add loongson-ext lswc2 group of instructions (Part 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LWC2 & SWC2 have been rewritten by Loongson EXT vendor ASE as "load/store quad word" and "shifted load/store" groups of instructions. This patch add implementation of these instructions: gslq: load 16 bytes to GPR gssq: store 16 bytes from GPR gslqc1: load 16 bytes to FPR gssqc1: store 16 bytes from FPR Details of Loongson-EXT is here: https://github.com/FlyGoat/loongson-insn/blob/master/loongson-ext.md Signed-off-by: Jiaxun Yang Signed-off-by: Huacai Chen Message-Id: <1602831120-3377-3-git-send-email-chenhc@lemote.com> [PMD: Restrict t1 variable to TARGET_MIPS64, remove unused t2/fp0] Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 86 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/target/mips/translate.c b/target/mips/translate.c index b4d009078e..e83954d782 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -460,6 +460,17 @@ enum { R6_OPC_SCD = 0x27 | OPC_SPECIAL3, }; +/* Loongson EXT load/store quad word opcodes */ +#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020)) +enum { + OPC_GSLQ = 0x0020 | OPC_LWC2, + OPC_GSLQC1 = 0x8020 | OPC_LWC2, + OPC_GSSHFL = OPC_LWC2, + OPC_GSSQ = 0x0020 | OPC_SWC2, + OPC_GSSQC1 = 0x8020 | OPC_SWC2, + OPC_GSSHFS = OPC_SWC2, +}; + /* BSHFL opcodes */ #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -5910,6 +5921,79 @@ no_rd: tcg_temp_free_i64(t1); } +static void gen_loongson_lswc2(DisasContext *ctx, int rt, + int rs, int rd) +{ + TCGv t0; +#if defined(TARGET_MIPS64) + TCGv t1; + int lsq_rt1 = ctx->opcode & 0x1f; + int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4; +#endif + + t0 = tcg_temp_new(); + + switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) { +#if defined(TARGET_MIPS64) + case OPC_GSLQ: + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t1, rt); + gen_store_gpr(t0, lsq_rt1); + tcg_temp_free(t1); + break; + case OPC_GSLQC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, t1, rt); + gen_store_fpr64(ctx, t0, lsq_rt1); + tcg_temp_free(t1); + break; + case OPC_GSSQ: + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + gen_load_gpr(t1, lsq_rt1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; + case OPC_GSSQC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, lsq_offset); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); + gen_load_fpr64(ctx, t1, lsq_rt1); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + default: + MIPS_INVAL("loongson_gslsq"); + generate_exception_end(ctx, EXCP_RI); + break; + } + tcg_temp_free(t0); +} + /* Traps */ static void gen_trap(DisasContext *ctx, uint32_t opc, int rs, int rt, int16_t imm) @@ -30774,6 +30858,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) /* OPC_BC, OPC_BALC */ gen_compute_compact_branch(ctx, op, 0, 0, sextract32(ctx->opcode << 2, 0, 28)); + } else if (ctx->insn_flags & ASE_LEXT) { + gen_loongson_lswc2(ctx, rt, rs, rd); } else { /* OPC_LWC2, OPC_SWC2 */ /* COP2: Not implemented. */ From fd723105c15e09b8a9eaad29fa59347e63cfdb20 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Fri, 16 Oct 2020 14:51:55 +0800 Subject: [PATCH 09/44] target/mips: Add loongson-ext lswc2 group of instructions (Part 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LWC2 & SWC2 have been rewritten by Loongson EXT vendor ASE as "load/store quad word" and "shifted load/store" groups of instructions. This patch add implementation of these instructions: gslwlc1: similar to lwl but RT is FPR instead of GPR gslwrc1: similar to lwr but RT is FPR instead of GPR gsldlc1: similar to ldl but RT is FPR instead of GPR gsldrc1: similar to ldr but RT is FPR instead of GPR gsswlc1: similar to swl but RT is FPR instead of GPR gsswrc1: similar to swr but RT is FPR instead of GPR gssdlc1: similar to sdl but RT is FPR instead of GPR gssdrc1: similar to sdr but RT is FPR instead of GPR Details of Loongson-EXT is here: https://github.com/FlyGoat/loongson-insn/blob/master/loongson-ext.md Signed-off-by: Jiaxun Yang Signed-off-by: Huacai Chen Message-Id: <1602831120-3377-4-git-send-email-chenhc@lemote.com> [PMD: Reuse t1 on MIPS32, reintroduce t2/fp0] Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 182 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 2 deletions(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index e83954d782..b335645e03 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -471,6 +471,19 @@ enum { OPC_GSSHFS = OPC_SWC2, }; +/* Loongson EXT shifted load/store opcodes */ +#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f)) +enum { + OPC_GSLWLC1 = 0x4 | OPC_GSSHFL, + OPC_GSLWRC1 = 0x5 | OPC_GSSHFL, + OPC_GSLDLC1 = 0x6 | OPC_GSSHFL, + OPC_GSLDRC1 = 0x7 | OPC_GSSHFL, + OPC_GSSWLC1 = 0x4 | OPC_GSSHFS, + OPC_GSSWRC1 = 0x5 | OPC_GSSHFS, + OPC_GSSDLC1 = 0x6 | OPC_GSSHFS, + OPC_GSSDRC1 = 0x7 | OPC_GSSHFS, +}; + /* BSHFL opcodes */ #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -5924,12 +5937,13 @@ no_rd: static void gen_loongson_lswc2(DisasContext *ctx, int rt, int rs, int rd) { - TCGv t0; + TCGv t0, t1, t2; + TCGv_i32 fp0; #if defined(TARGET_MIPS64) - TCGv t1; int lsq_rt1 = ctx->opcode & 0x1f; int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4; #endif + int shf_offset = sextract32(ctx->opcode, 6, 8); t0 = tcg_temp_new(); @@ -5986,6 +6000,170 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, tcg_temp_free(t1); break; #endif + case OPC_GSSHFL: + switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { + case OPC_GSLWLC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 3); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_shl_tl(t0, t0, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + tcg_gen_andc_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); +#if defined(TARGET_MIPS64) + tcg_gen_extrl_i64_i32(fp0, t0); +#else + tcg_gen_ext32s_tl(fp0, t0); +#endif + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; + case OPC_GSLWRC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 3); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 3); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~3); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 31); + t2 = tcg_const_tl(0xfffffffeull); + tcg_gen_shl_tl(t2, t2, t1); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); +#if defined(TARGET_MIPS64) + tcg_gen_extrl_i64_i32(fp0, t0); +#else + tcg_gen_ext32s_tl(fp0, t0); +#endif + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDLC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 7); +#ifndef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_shl_tl(t0, t0, t1); + t2 = tcg_const_tl(-1); + tcg_gen_shl_tl(t2, t2, t1); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_andc_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); + gen_store_fpr64(ctx, t0, rt); + break; + case OPC_GSLDRC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + t1 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB); + tcg_gen_andi_tl(t1, t0, 7); +#ifdef TARGET_WORDS_BIGENDIAN + tcg_gen_xori_tl(t1, t1, 7); +#endif + tcg_gen_shli_tl(t1, t1, 3); + tcg_gen_andi_tl(t0, t0, ~7); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_shr_tl(t0, t0, t1); + tcg_gen_xori_tl(t1, t1, 63); + t2 = tcg_const_tl(0xfffffffffffffffeull); + tcg_gen_shl_tl(t2, t2, t1); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_and_tl(t1, t1, t2); + tcg_temp_free(t2); + tcg_gen_or_tl(t0, t0, t1); + tcg_temp_free(t1); + gen_store_fpr64(ctx, t0, rt); + break; +#endif + default: + MIPS_INVAL("loongson_gsshfl"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; + case OPC_GSSHFS: + switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { + case OPC_GSSWLC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + gen_helper_0e2i(swl, t1, t0, ctx->mem_idx); + tcg_temp_free_i32(fp0); + tcg_temp_free(t1); + break; + case OPC_GSSWRC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_ext_i32_tl(t1, fp0); + gen_helper_0e2i(swr, t1, t0, ctx->mem_idx); + tcg_temp_free_i32(fp0); + tcg_temp_free(t1); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDLC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + gen_load_fpr64(ctx, t1, rt); + gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx); + tcg_temp_free(t1); + break; + case OPC_GSSDRC1: + check_cp1_enabled(ctx); + t1 = tcg_temp_new(); + gen_base_offset_addr(ctx, t0, rs, shf_offset); + gen_load_fpr64(ctx, t1, rt); + gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx); + tcg_temp_free(t1); + break; +#endif + default: + MIPS_INVAL("loongson_gsshfs"); + generate_exception_end(ctx, EXCP_RI); + break; + } + break; default: MIPS_INVAL("loongson_gslsq"); generate_exception_end(ctx, EXCP_RI); From 90e22a57af975dea08b3015dfac072709f131616 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Fri, 16 Oct 2020 14:51:56 +0800 Subject: [PATCH 10/44] target/mips: Add loongson-ext lsdc2 group of instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LDC2/SDC2 opcodes have been rewritten as "load & store with offset" group of instructions by loongson-ext ASE. This patch add implementation of these instructions: gslbx: load 1 bytes to GPR gslhx: load 2 bytes to GPR gslwx: load 4 bytes to GPR gsldx: load 8 bytes to GPR gslwxc1: load 4 bytes to FPR gsldxc1: load 8 bytes to FPR gssbx: store 1 bytes from GPR gsshx: store 2 bytes from GPR gsswx: store 4 bytes from GPR gssdx: store 8 bytes from GPR gsswxc1: store 4 bytes from FPR gssdxc1: store 8 bytes from FPR Details of Loongson-EXT is here: https://github.com/FlyGoat/loongson-insn/blob/master/loongson-ext.md Signed-off-by: Jiaxun Yang Signed-off-by: Huacai Chen Reviewed-by: Philippe Mathieu-Daudé Message-Id: <1602831120-3377-5-git-send-email-chenhc@lemote.com> --- target/mips/translate.c | 179 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/target/mips/translate.c b/target/mips/translate.c index b335645e03..f449758606 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -484,6 +484,24 @@ enum { OPC_GSSDRC1 = 0x7 | OPC_GSSHFS, }; +/* Loongson EXT LDC2/SDC2 opcodes */ +#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7)) + +enum { + OPC_GSLBX = 0x0 | OPC_LDC2, + OPC_GSLHX = 0x1 | OPC_LDC2, + OPC_GSLWX = 0x2 | OPC_LDC2, + OPC_GSLDX = 0x3 | OPC_LDC2, + OPC_GSLWXC1 = 0x6 | OPC_LDC2, + OPC_GSLDXC1 = 0x7 | OPC_LDC2, + OPC_GSSBX = 0x0 | OPC_SDC2, + OPC_GSSHX = 0x1 | OPC_SDC2, + OPC_GSSWX = 0x2 | OPC_SDC2, + OPC_GSSDX = 0x3 | OPC_SDC2, + OPC_GSSWXC1 = 0x6 | OPC_SDC2, + OPC_GSSDXC1 = 0x7 | OPC_SDC2, +}; + /* BSHFL opcodes */ #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -6172,6 +6190,165 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, tcg_temp_free(t0); } +/* Loongson EXT LDC2/SDC2 */ +static void gen_loongson_lsdc2(DisasContext *ctx, int rt, + int rs, int rd) +{ + int offset = sextract32(ctx->opcode, 3, 8); + uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode); + TCGv t0, t1; + TCGv_i32 fp0; + + /* Pre-conditions */ + switch (opc) { + case OPC_GSLBX: + case OPC_GSLHX: + case OPC_GSLWX: + case OPC_GSLDX: + /* prefetch, implement as NOP */ + if (rt == 0) { + return; + } + break; + case OPC_GSSBX: + case OPC_GSSHX: + case OPC_GSSWX: + case OPC_GSSDX: + break; + case OPC_GSLWXC1: +#if defined(TARGET_MIPS64) + case OPC_GSLDXC1: +#endif + check_cp1_enabled(ctx); + /* prefetch, implement as NOP */ + if (rt == 0) { + return; + } + break; + case OPC_GSSWXC1: +#if defined(TARGET_MIPS64) + case OPC_GSSDXC1: +#endif + check_cp1_enabled(ctx); + break; + default: + MIPS_INVAL("loongson_lsdc2"); + generate_exception_end(ctx, EXCP_RI); + return; + break; + } + + t0 = tcg_temp_new(); + + gen_base_offset_addr(ctx, t0, rs, offset); + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + + switch (opc) { + case OPC_GSLBX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB); + gen_store_gpr(t0, rt); + break; + case OPC_GSLHX: + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; + case OPC_GSLWX: + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDX: + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_gpr(t0, rt); + break; +#endif + case OPC_GSLWXC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + fp0 = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL | + ctx->default_tcg_memop_mask); + gen_store_fpr32(ctx, fp0, rt); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSLDXC1: + check_cp1_enabled(ctx); + gen_base_offset_addr(ctx, t0, rs, offset); + if (rd) { + gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); + } + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + gen_store_fpr64(ctx, t0, rt); + break; +#endif + case OPC_GSSBX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB); + tcg_temp_free(t1); + break; + case OPC_GSSHX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; + case OPC_GSSWX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDX: + t1 = tcg_temp_new(); + gen_load_gpr(t1, rt); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + case OPC_GSSWXC1: + fp0 = tcg_temp_new_i32(); + gen_load_fpr32(ctx, fp0, rt); + tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL | + ctx->default_tcg_memop_mask); + tcg_temp_free_i32(fp0); + break; +#if defined(TARGET_MIPS64) + case OPC_GSSDXC1: + t1 = tcg_temp_new(); + gen_load_fpr64(ctx, t1, rt); + tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ | + ctx->default_tcg_memop_mask); + tcg_temp_free(t1); + break; +#endif + default: + break; + } + + tcg_temp_free(t0); +} + /* Traps */ static void gen_trap(DisasContext *ctx, uint32_t opc, int rs, int rt, int16_t imm) @@ -31055,6 +31232,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) /* OPC_JIC, OPC_JIALC */ gen_compute_compact_branch(ctx, op, 0, rt, imm); } + } else if (ctx->insn_flags & ASE_LEXT) { + gen_loongson_lsdc2(ctx, rt, rs, rd); } else { /* OPC_LWC2, OPC_SWC2 */ /* COP2: Not implemented. */ From 4a367cfb00d3779f0113f871e4b7cb550d068098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 13 Aug 2020 19:48:49 +0200 Subject: [PATCH 11/44] target/mips/op_helper: Convert multiple if() to switch case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cache operation is encoded in bits [20:18] of the instruction. The 'op' argument of helper_cache() contains the bits [20:16]. Extract the 3 bits and parse them using a switch case. This allow us to handle multiple cache types (the cache type is encoded in bits [17:16]). Previously the if() block was only checking the D-Cache (Primary Data or Unified Primary). Now we also handle the I-Cache (Primary Instruction), S-Cache (Secondary) and T-Cache (Terciary). Reported-by: Jiaxun Yang Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20200813181527.22551-2-f4bug@amsat.org> --- target/mips/op_helper.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 9552b280e0..c15f5c0776 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -1574,15 +1574,20 @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) { #ifndef CONFIG_USER_ONLY + uint32_t cache_operation = extract32(op, 2, 3); target_ulong index = addr & 0x1fffffff; - if (op == 9) { - /* Index Store Tag */ + + switch (cache_operation) { + case 0b010: /* Index Store Tag */ memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo, MO_64, MEMTXATTRS_UNSPECIFIED); - } else if (op == 5) { - /* Index Load Tag */ + break; + case 0b001: /* Index Load Tag */ memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo, MO_64, MEMTXATTRS_UNSPECIFIED); + break; + default: + break; } #endif } From 45964263e42b9728dd206936c157bfd1bdb6918a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 13 Aug 2020 19:49:22 +0200 Subject: [PATCH 12/44] target/mips/op_helper: Document Invalidate/Writeback opcodes as no-op MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU does not model caches, so there is not much to do with the Invalidate/Writeback opcodes. Make it explicit adding a comment. Suggested-by: Jiaxun Yang Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20200813181527.22551-3-f4bug@amsat.org> --- target/mips/op_helper.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index c15f5c0776..2496d1dd71 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -1586,6 +1586,11 @@ void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo, MO_64, MEMTXATTRS_UNSPECIFIED); break; + case 0b000: /* Index Invalidate */ + case 0b100: /* Hit Invalidate */ + case 0b110: /* Hit Writeback */ + /* no-op */ + break; default: break; } From 88a844545e0fb1fa95a55888fb31024fcfc9720b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 13 Aug 2020 19:48:32 +0200 Subject: [PATCH 13/44] target/mips/op_helper: Log unimplemented cache opcode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case the guest uses a cache opcode we are not expecting, log it to give us a chance to notice it, in case we should actually do something. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Jiaxun Yang Message-Id: <20200813181527.22551-4-f4bug@amsat.org> --- target/mips/op_helper.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index 2496d1dd71..0050d0616b 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -1574,6 +1574,13 @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) { #ifndef CONFIG_USER_ONLY + static const char *const type_name[] = { + "Primary Instruction", + "Primary Data or Unified Primary", + "Tertiary", + "Secondary" + }; + uint32_t cache_type = extract32(op, 0, 2); uint32_t cache_operation = extract32(op, 2, 3); target_ulong index = addr & 0x1fffffff; @@ -1592,6 +1599,8 @@ void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) /* no-op */ break; default: + qemu_log_mask(LOG_UNIMP, "cache operation:%u (type: %s cache)\n", + cache_operation, type_name[cache_type]); break; } #endif From 2dc29222a6f7c87300c1a7e1982e11422d34595e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:48 +0200 Subject: [PATCH 14/44] target/mips: Move cpu_mips_get_random() with CP0 helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The get_random() helper uses the CP0_Wired register, which is unrelated to the CP0_Count register used as timer. Commit e16fe40c872 ("Move the MIPS CPU timer in a separate file") incorrectly moved this get_random() helper with timer specific code. Move it back to generic CP0 helpers. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Aleksandar Markovic Reviewed-by: Luc Michel Message-Id: <20201012095804.3335117-6-f4bug@amsat.org> --- target/mips/cp0_helper.c | 25 +++++++++++++++++++++++++ target/mips/cp0_timer.c | 25 ------------------------- target/mips/internal.h | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c index de64add038..12143ac55b 100644 --- a/target/mips/cp0_helper.c +++ b/target/mips/cp0_helper.c @@ -203,6 +203,31 @@ static void sync_c0_entryhi(CPUMIPSState *cpu, int tc) *tcst |= asid; } +/* XXX: do not use a global */ +uint32_t cpu_mips_get_random(CPUMIPSState *env) +{ + static uint32_t seed = 1; + static uint32_t prev_idx; + uint32_t idx; + uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired; + + if (nb_rand_tlb == 1) { + return env->tlb->nb_tlb - 1; + } + + /* Don't return same value twice, so get another value */ + do { + /* + * Use a simple algorithm of Linear Congruential Generator + * from ISO/IEC 9899 standard. + */ + seed = 1103515245 * seed + 12345; + idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired; + } while (idx == prev_idx); + prev_idx = idx; + return idx; +} + /* CP0 helpers */ target_ulong helper_mfc0_mvpcontrol(CPUMIPSState *env) { diff --git a/target/mips/cp0_timer.c b/target/mips/cp0_timer.c index bd7efb152d..9c38e9da1c 100644 --- a/target/mips/cp0_timer.c +++ b/target/mips/cp0_timer.c @@ -29,31 +29,6 @@ #define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ -/* XXX: do not use a global */ -uint32_t cpu_mips_get_random(CPUMIPSState *env) -{ - static uint32_t seed = 1; - static uint32_t prev_idx = 0; - uint32_t idx; - uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired; - - if (nb_rand_tlb == 1) { - return env->tlb->nb_tlb - 1; - } - - /* Don't return same value twice, so get another value */ - do { - /* - * Use a simple algorithm of Linear Congruential Generator - * from ISO/IEC 9899 standard. - */ - seed = 1103515245 * seed + 12345; - idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired; - } while (idx == prev_idx); - prev_idx = idx; - return idx; -} - /* MIPS R4K timer */ static void cpu_mips_timer_update(CPUMIPSState *env) { diff --git a/target/mips/internal.h b/target/mips/internal.h index b811f547f3..dd8a7809b6 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -144,6 +144,7 @@ void r4k_helper_tlbr(CPUMIPSState *env); void r4k_helper_tlbinv(CPUMIPSState *env); void r4k_helper_tlbinvf(CPUMIPSState *env); void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra); +uint32_t cpu_mips_get_random(CPUMIPSState *env); void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, unsigned size, @@ -209,7 +210,6 @@ void cpu_state_reset(CPUMIPSState *s); void cpu_mips_realize_env(CPUMIPSState *env); /* cp0_timer.c */ -uint32_t cpu_mips_get_random(CPUMIPSState *env); uint32_t cpu_mips_get_count(CPUMIPSState *env); void cpu_mips_store_count(CPUMIPSState *env, uint32_t value); void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value); From 62f8f2603da7fbcc481489d2903558001a896cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:49 +0200 Subject: [PATCH 15/44] target/mips/cp0_timer: Explicit unit in variable name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Name variables holding nanoseconds with the '_ns' suffix. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Aleksandar Markovic Message-Id: <20201012095804.3335117-7-f4bug@amsat.org> --- target/mips/cp0_timer.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/target/mips/cp0_timer.c b/target/mips/cp0_timer.c index 9c38e9da1c..5194c967ae 100644 --- a/target/mips/cp0_timer.c +++ b/target/mips/cp0_timer.c @@ -32,13 +32,14 @@ /* MIPS R4K timer */ static void cpu_mips_timer_update(CPUMIPSState *env) { - uint64_t now, next; + uint64_t now_ns, next_ns; uint32_t wait; - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - wait = env->CP0_Compare - env->CP0_Count - (uint32_t)(now / TIMER_PERIOD); - next = now + (uint64_t)wait * TIMER_PERIOD; - timer_mod(env->timer, next); + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + wait = env->CP0_Compare - env->CP0_Count - + (uint32_t)(now_ns / TIMER_PERIOD); + next_ns = now_ns + (uint64_t)wait * TIMER_PERIOD; + timer_mod(env->timer, next_ns); } /* Expire the timer. */ @@ -56,16 +57,16 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env) if (env->CP0_Cause & (1 << CP0Ca_DC)) { return env->CP0_Count; } else { - uint64_t now; + uint64_t now_ns; - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if (timer_pending(env->timer) - && timer_expired(env->timer, now)) { + && timer_expired(env->timer, now_ns)) { /* The timer has already expired. */ cpu_mips_timer_expire(env); } - return env->CP0_Count + (uint32_t)(now / TIMER_PERIOD); + return env->CP0_Count + (uint32_t)(now_ns / TIMER_PERIOD); } } From 8dadffc01700f79fd66db972fff3a93a594715ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:50 +0200 Subject: [PATCH 16/44] target/mips/cp0_timer: Document TIMER_PERIOD origin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TIMER_PERIOD value of '10 ns' can be explained looking at commit 6af0bf9c7c3doc, where the CPU frequency is 200 MHz and CP0 default count rate is half the frequency of the CPU. Document that. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-8-f4bug@amsat.org> --- target/mips/cp0_timer.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/target/mips/cp0_timer.c b/target/mips/cp0_timer.c index 5194c967ae..6fec5fe0ff 100644 --- a/target/mips/cp0_timer.c +++ b/target/mips/cp0_timer.c @@ -27,7 +27,17 @@ #include "sysemu/kvm.h" #include "internal.h" -#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */ +/* + * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz + * and a CP0 timer running at half the clock of the CPU (cp0_count_rate = 2). + * + * TIMER_FREQ_HZ = CPU_FREQ_HZ / CP0_COUNT_RATE = 200 MHz / 2 = 100 MHz + * + * TIMER_PERIOD_NS = 1 / TIMER_FREQ_HZ = 10 ns + */ +#define CPU_FREQ_HZ_DEFAULT 200000000 +#define CP0_COUNT_RATE_DEFAULT 2 +#define TIMER_PERIOD 10 /* 1 / (CPU_FREQ_HZ / CP0_COUNT_RATE) */ /* MIPS R4K timer */ static void cpu_mips_timer_update(CPUMIPSState *env) From d225b5122029c3d6293aab6e2d0a05597fc92ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:51 +0200 Subject: [PATCH 17/44] target/mips: Move cp0_count_ns to CPUMIPSState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the CP0 timer period is fixed at 10 ns, corresponding to a fixed CPU frequency of 200 MHz (using half the speed of the CPU). In few commits we will be able to use a different CPU frequency. In preparation, move the cp0_count_ns variable to CPUMIPSState so we can modify it. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang Message-Id: <20201012095804.3335117-9-f4bug@amsat.org> --- target/mips/cp0_timer.c | 23 ++++++----------------- target/mips/cpu.c | 21 +++++++++++++++++++++ target/mips/cpu.h | 1 + 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/target/mips/cp0_timer.c b/target/mips/cp0_timer.c index 6fec5fe0ff..5ec0d6249e 100644 --- a/target/mips/cp0_timer.c +++ b/target/mips/cp0_timer.c @@ -27,18 +27,6 @@ #include "sysemu/kvm.h" #include "internal.h" -/* - * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz - * and a CP0 timer running at half the clock of the CPU (cp0_count_rate = 2). - * - * TIMER_FREQ_HZ = CPU_FREQ_HZ / CP0_COUNT_RATE = 200 MHz / 2 = 100 MHz - * - * TIMER_PERIOD_NS = 1 / TIMER_FREQ_HZ = 10 ns - */ -#define CPU_FREQ_HZ_DEFAULT 200000000 -#define CP0_COUNT_RATE_DEFAULT 2 -#define TIMER_PERIOD 10 /* 1 / (CPU_FREQ_HZ / CP0_COUNT_RATE) */ - /* MIPS R4K timer */ static void cpu_mips_timer_update(CPUMIPSState *env) { @@ -47,8 +35,8 @@ static void cpu_mips_timer_update(CPUMIPSState *env) now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); wait = env->CP0_Compare - env->CP0_Count - - (uint32_t)(now_ns / TIMER_PERIOD); - next_ns = now_ns + (uint64_t)wait * TIMER_PERIOD; + (uint32_t)(now_ns / env->cp0_count_ns); + next_ns = now_ns + (uint64_t)wait * env->cp0_count_ns; timer_mod(env->timer, next_ns); } @@ -76,7 +64,7 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env) cpu_mips_timer_expire(env); } - return env->CP0_Count + (uint32_t)(now_ns / TIMER_PERIOD); + return env->CP0_Count + (uint32_t)(now_ns / env->cp0_count_ns); } } @@ -92,7 +80,8 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count) } else { /* Store new count register */ env->CP0_Count = count - - (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD); + (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / + env->cp0_count_ns); /* Update timer timer */ cpu_mips_timer_update(env); } @@ -119,7 +108,7 @@ void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / - TIMER_PERIOD); + env->cp0_count_ns); } static void mips_timer_cb(void *opaque) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index e86cd06548..84b727fefa 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -134,6 +134,25 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) } } +/* + * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz + * and a CP0 timer running at half the clock of the CPU (cp0_count_rate = 2). + * + * TIMER_FREQ_HZ = CPU_FREQ_HZ / CP0_COUNT_RATE = 200 MHz / 2 = 100 MHz + * + * TIMER_PERIOD_NS = 1 / TIMER_FREQ_HZ = 10 ns + */ +#define CPU_FREQ_HZ_DEFAULT 200000000 +#define CP0_COUNT_RATE_DEFAULT 2 +#define TIMER_PERIOD_DEFAULT 10 /* 1 / (CPU_FREQ_HZ / CP0_COUNT_RATE) */ + +static void mips_cp0_period_set(MIPSCPU *cpu) +{ + CPUMIPSState *env = &cpu->env; + + env->cp0_count_ns = TIMER_PERIOD_DEFAULT; +} + static void mips_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -141,6 +160,8 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); Error *local_err = NULL; + mips_cp0_period_set(cpu); + cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 7cf7f5239f..085a88e955 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1145,6 +1145,7 @@ struct CPUMIPSState { struct MIPSITUState *itu; MemoryRegion *itc_tag; /* ITC Configuration Tags */ target_ulong exception_base; /* ExceptionBase input to the core */ + uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */ }; /** From 68b981aa76079216f5765a6aecaf8728f27d3696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:52 +0200 Subject: [PATCH 18/44] target/mips/cpu: Calculate the CP0 timer period using the CPU frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CP0 timer period is a function of the CPU frequency. Start using the default values, which will be replaced by properties in the next commits. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang Message-Id: <20201012095804.3335117-10-f4bug@amsat.org> --- target/mips/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 84b727fefa..46188139b7 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -144,13 +144,13 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) */ #define CPU_FREQ_HZ_DEFAULT 200000000 #define CP0_COUNT_RATE_DEFAULT 2 -#define TIMER_PERIOD_DEFAULT 10 /* 1 / (CPU_FREQ_HZ / CP0_COUNT_RATE) */ static void mips_cp0_period_set(MIPSCPU *cpu) { CPUMIPSState *env = &cpu->env; - env->cp0_count_ns = TIMER_PERIOD_DEFAULT; + env->cp0_count_ns = muldiv64(NANOSECONDS_PER_SECOND, CP0_COUNT_RATE_DEFAULT, + CPU_FREQ_HZ_DEFAULT); } static void mips_cpu_realizefn(DeviceState *dev, Error **errp) From d0bec217ee0f6c948ba4579ca0f43a1a3f346cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:53 +0200 Subject: [PATCH 19/44] target/mips/cpu: Make cp0_count_rate a property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since not all CPU implementations use a cores use a CP0 timer at half the frequency of the CPU, make this variable a property. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-11-f4bug@amsat.org> --- target/mips/cpu.c | 19 +++++++++++-------- target/mips/cpu.h | 9 +++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 46188139b7..461edfe22b 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -26,7 +26,7 @@ #include "qemu/module.h" #include "sysemu/kvm.h" #include "exec/exec-all.h" - +#include "hw/qdev-properties.h" static void mips_cpu_set_pc(CPUState *cs, vaddr value) { @@ -135,12 +135,7 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info) } /* - * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz - * and a CP0 timer running at half the clock of the CPU (cp0_count_rate = 2). - * - * TIMER_FREQ_HZ = CPU_FREQ_HZ / CP0_COUNT_RATE = 200 MHz / 2 = 100 MHz - * - * TIMER_PERIOD_NS = 1 / TIMER_FREQ_HZ = 10 ns + * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz. */ #define CPU_FREQ_HZ_DEFAULT 200000000 #define CP0_COUNT_RATE_DEFAULT 2 @@ -149,7 +144,7 @@ static void mips_cp0_period_set(MIPSCPU *cpu) { CPUMIPSState *env = &cpu->env; - env->cp0_count_ns = muldiv64(NANOSECONDS_PER_SECOND, CP0_COUNT_RATE_DEFAULT, + env->cp0_count_ns = muldiv64(NANOSECONDS_PER_SECOND, cpu->cp0_count_rate, CPU_FREQ_HZ_DEFAULT); } @@ -202,6 +197,13 @@ static ObjectClass *mips_cpu_class_by_name(const char *cpu_model) return oc; } +static Property mips_cpu_properties[] = { + /* CP0 timer running at half the clock of the CPU */ + DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate, + CP0_COUNT_RATE_DEFAULT), + DEFINE_PROP_END_OF_LIST() +}; + static void mips_cpu_class_init(ObjectClass *c, void *data) { MIPSCPUClass *mcc = MIPS_CPU_CLASS(c); @@ -211,6 +213,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) device_class_set_parent_realize(dc, mips_cpu_realizefn, &mcc->parent_realize); device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset); + device_class_set_props(dc, mips_cpu_properties); cc->class_by_name = mips_cpu_class_by_name; cc->has_work = mips_cpu_has_work; diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 085a88e955..baeceb892e 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1151,6 +1151,7 @@ struct CPUMIPSState { /** * MIPSCPU: * @env: #CPUMIPSState + * @cp0_count_rate: rate at which the coprocessor 0 counter increments * * A MIPS CPU. */ @@ -1161,6 +1162,14 @@ struct MIPSCPU { CPUNegativeOffsetState neg; CPUMIPSState env; + /* + * The Count register acts as a timer, incrementing at a constant rate, + * whether or not an instruction is executed, retired, or any forward + * progress is made through the pipeline. The rate at which the counter + * increments is implementation dependent, and is a function of the + * pipeline clock of the processor, not the issue width of the processor. + */ + unsigned cp0_count_rate; }; From a0713e85bfaec4d787b978640096322716938a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:54 +0200 Subject: [PATCH 20/44] target/mips/cpu: Allow the CPU to use dynamic frequencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the Clock API and let the CPU object have an input clock. If no clock is connected, keep using the default frequency of 200 MHz used since the introduction of the 'r4k' machine in commit 6af0bf9c7c3. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-12-f4bug@amsat.org> --- target/mips/cpu.c | 11 +++++++++-- target/mips/cpu.h | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 461edfe22b..2a6f4840e2 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -27,6 +27,7 @@ #include "sysemu/kvm.h" #include "exec/exec-all.h" #include "hw/qdev-properties.h" +#include "hw/qdev-clock.h" static void mips_cpu_set_pc(CPUState *cs, vaddr value) { @@ -144,8 +145,9 @@ static void mips_cp0_period_set(MIPSCPU *cpu) { CPUMIPSState *env = &cpu->env; - env->cp0_count_ns = muldiv64(NANOSECONDS_PER_SECOND, cpu->cp0_count_rate, - CPU_FREQ_HZ_DEFAULT); + env->cp0_count_ns = cpu->cp0_count_rate + * clock_get_ns(MIPS_CPU(cpu)->clock); + assert(env->cp0_count_ns); } static void mips_cpu_realizefn(DeviceState *dev, Error **errp) @@ -155,6 +157,10 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); Error *local_err = NULL; + if (!clock_get(cpu->clock)) { + /* Initialize the frequency in case the clock remains unconnected. */ + clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT); + } mips_cp0_period_set(cpu); cpu_exec_realizefn(cs, &local_err); @@ -178,6 +184,7 @@ static void mips_cpu_initfn(Object *obj) MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj); cpu_set_cpustate_pointers(cpu); + cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu); env->cpu_model = mcc->cpu_def; } diff --git a/target/mips/cpu.h b/target/mips/cpu.h index baeceb892e..062a4ba622 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -4,6 +4,7 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" +#include "hw/clock.h" #include "mips-defs.h" #define TCG_GUEST_DEFAULT_MO (0) @@ -1151,6 +1152,8 @@ struct CPUMIPSState { /** * MIPSCPU: * @env: #CPUMIPSState + * @clock: this CPU input clock (may be connected + * to an output clock from another device). * @cp0_count_rate: rate at which the coprocessor 0 counter increments * * A MIPS CPU. @@ -1160,6 +1163,7 @@ struct MIPSCPU { CPUState parent_obj; /*< public >*/ + Clock *clock; CPUNegativeOffsetState neg; CPUMIPSState env; /* From 7aaab96a9b1c37f473f73363ff815eb059a2f823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:55 +0200 Subject: [PATCH 21/44] target/mips/cpu: Introduce mips_cpu_create_with_clock() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce an helper to create a MIPS CPU and connect it to a reference clock. This helper is not MIPS specific, but so far only MIPS CPUs need it. Suggested-by: Huacai Chen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-13-f4bug@amsat.org> --- target/mips/cpu.c | 12 ++++++++++++ target/mips/cpu.h | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 2a6f4840e2..33a9ed5c24 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -288,3 +288,15 @@ static void mips_cpu_register_types(void) } type_init(mips_cpu_register_types) + +/* Could be used by generic CPU object */ +MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) +{ + DeviceState *cpu; + + cpu = DEVICE(object_new(cpu_type)); + qdev_connect_clock_in(cpu, "clk-in", cpu_refclk); + qdev_realize(cpu, NULL, &error_abort); + + return MIPS_CPU(cpu); +} diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 062a4ba622..d41579d44a 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1307,4 +1307,16 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, MIPS_HFLAG_HWRENA_ULR); } +/** + * mips_cpu_create_with_clock: + * @typename: a MIPS CPU type. + * @cpu_refclk: this cpu input clock (an output clock of another device) + * + * Instantiates a MIPS CPU, set the input clock of the CPU to @cpu_refclk, + * then realizes the CPU. + * + * Returns: A #CPUState or %NULL if an error occurred. + */ +MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk); + #endif /* MIPS_CPU_H */ From dccf092d67e05c76fe47ed92cab0aa59e77c6e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:56 +0200 Subject: [PATCH 22/44] hw/mips/r4k: Explicit CPU frequency is 200 MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since its introduction in commit 6af0bf9c7c3, the 'r4k' machine runs at 200 MHz. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-14-f4bug@amsat.org> --- hw/mips/r4k.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/mips/r4k.c b/hw/mips/r4k.c index 3487013a4a..39bc626e7c 100644 --- a/hw/mips/r4k.c +++ b/hw/mips/r4k.c @@ -13,6 +13,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/intc/i8259.h" @@ -182,6 +183,7 @@ void mips_r4k_init(MachineState *machine) MemoryRegion *isa_io = g_new(MemoryRegion, 1); MemoryRegion *isa_mem = g_new(MemoryRegion, 1); int bios_size; + Clock *cpuclk; MIPSCPU *cpu; CPUMIPSState *env; ResetData *reset_info; @@ -192,8 +194,11 @@ void mips_r4k_init(MachineState *machine) DriveInfo *dinfo; int be; + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + clock_set_hz(cpuclk, 200000000); /* 200 MHz */ + /* init CPUs */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; reset_info = g_malloc0(sizeof(ResetData)); From 3ca7639ff0077ef1869c88523360c017defecaad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:57 +0200 Subject: [PATCH 23/44] hw/mips/fuloong2e: Set CPU frequency to 533 MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CPU frequency is normally provided by the firmware in the "cpuclock" environment variable. The 2E board can handles up to 660MHz, but be conservative and take the same value used by the Linux kernel: 533 MHz. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang Message-Id: <20201012095804.3335117-15-f4bug@amsat.org> --- hw/mips/fuloong2e.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index b000ed1d7f..b8234f6108 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -23,6 +23,7 @@ #include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/isa/superio.h" @@ -298,12 +299,16 @@ static void mips_fuloong2e_init(MachineState *machine) PCIBus *pci_bus; ISABus *isa_bus; I2CBus *smbus; + Clock *cpuclk; MIPSCPU *cpu; CPUMIPSState *env; DeviceState *dev; + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + clock_set_hz(cpuclk, 533080000); /* ~533 MHz */ + /* init CPUs */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); From 8543a806912da7cdbc45303226762372f92f689b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:58 +0200 Subject: [PATCH 24/44] hw/mips/mipssim: Correct CPU frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MIPSsim machine CPU frequency is too fast running at 200 MHz, while it should be 12 MHz for the 24K and 6 MHz for the 5K core. Ref: Linux commit c78cbf49c4ed ("Support for MIPSsim, the cycle accurate MIPS simulator.") Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-16-f4bug@amsat.org> --- hw/mips/mipssim.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index 5d4ad74828..f0042f7f43 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -29,6 +29,7 @@ #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/char/serial.h" @@ -150,13 +151,21 @@ mips_mipssim_init(MachineState *machine) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); + Clock *cpuclk; MIPSCPU *cpu; CPUMIPSState *env; ResetData *reset_info; int bios_size; + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); +#ifdef TARGET_MIPS64 + clock_set_hz(cpuclk, 6000000); /* 6 MHz */ +#else + clock_set_hz(cpuclk, 12000000); /* 12 MHz */ +#endif + /* Init CPUs. */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; reset_info = g_malloc0(sizeof(ResetData)); From 79b99fe3f09979b6ba0a8d9f4603dc43e7e066c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:57:59 +0200 Subject: [PATCH 25/44] hw/mips/jazz: Correct CPU frequencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Magnum 4000PC CPU runs at 100 MHz, and the Acer PICA-61 CPU at ~134 MHz. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-17-f4bug@amsat.org> --- hw/mips/jazz.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 47723093b6..8f1ad55ba3 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "hw/clock.h" #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/intc/i8259.h" @@ -142,6 +143,7 @@ static void mips_jazz_init(MachineState *machine, MemoryRegion *address_space = get_system_memory(); char *filename; int bios_size, n; + Clock *cpuclk; MIPSCPU *cpu; CPUClass *cc; CPUMIPSState *env; @@ -163,14 +165,25 @@ static void mips_jazz_init(MachineState *machine, MemoryRegion *bios2 = g_new(MemoryRegion, 1); SysBusESPState *sysbus_esp; ESPState *esp; + static const struct { + unsigned freq_hz; + unsigned pll_mult; + } ext_clk[] = { + [JAZZ_MAGNUM] = {50000000, 2}, + [JAZZ_PICA61] = {33333333, 4}, + }; if (machine->ram_size > 256 * MiB) { error_report("RAM size more than 256Mb is not supported"); exit(EXIT_FAILURE); } + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + clock_set_hz(cpuclk, ext_clk[jazz_model].freq_hz + * ext_clk[jazz_model].pll_mult); + /* init CPUs */ - cpu = MIPS_CPU(cpu_create(machine->cpu_type)); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); From e8373c56531cec8eb48743f261e8b216bcda589a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:58:00 +0200 Subject: [PATCH 26/44] hw/mips/cps: Expose input clock and connect it to CPU cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose a qdev input clock named 'clk-in', and connect it to each core to forward-propagate the clock. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-18-f4bug@amsat.org> --- hw/mips/cps.c | 4 ++++ include/hw/mips/cps.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 23c0f87e41..af7b58c4bd 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -22,6 +22,7 @@ #include "qemu/module.h" #include "hw/mips/cps.h" #include "hw/mips/mips.h" +#include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "hw/mips/cpudevs.h" #include "sysemu/kvm.h" @@ -38,6 +39,7 @@ static void mips_cps_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); MIPSCPSState *s = MIPS_CPS(obj); + s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL); /* * Cover entire address space as there do not seem to be any * constraints for the base address of CPC and GIC. @@ -80,6 +82,8 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) errp)) { return; } + /* All cores use the same clock tree */ + qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock); if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) { return; diff --git a/include/hw/mips/cps.h b/include/hw/mips/cps.h index 9e35a88136..859a8d4a67 100644 --- a/include/hw/mips/cps.h +++ b/include/hw/mips/cps.h @@ -21,6 +21,7 @@ #define MIPS_CPS_H #include "hw/sysbus.h" +#include "hw/clock.h" #include "hw/misc/mips_cmgcr.h" #include "hw/intc/mips_gic.h" #include "hw/misc/mips_cpc.h" @@ -43,6 +44,7 @@ struct MIPSCPSState { MIPSGICState gic; MIPSCPCState cpc; MIPSITUState itu; + Clock *clock; }; qemu_irq get_cps_irq(MIPSCPSState *cps, int pin_number); From 6b290b41cb533b93548248846e0e320af0a419ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:58:01 +0200 Subject: [PATCH 27/44] hw/mips/boston: Set CPU frequency to 1 GHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The I6400 can run at 1 GHz or more. Create a 'cpuclk' output clock and connect it to the CPU input clock. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-19-f4bug@amsat.org> --- hw/mips/boston.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 1b3f69e949..cf2296f448 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -30,6 +30,7 @@ #include "hw/mips/cps.h" #include "hw/mips/cpudevs.h" #include "hw/pci-host/xilinx-pcie.h" +#include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -54,6 +55,7 @@ struct BostonState { MachineState *mach; MIPSCPSState cps; SerialMM *uart; + Clock *cpuclk; CharBackend lcd_display; char lcd_content[8]; @@ -251,10 +253,19 @@ static const MemoryRegionOps boston_platreg_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void mips_boston_instance_init(Object *obj) +{ + BostonState *s = BOSTON(obj); + + s->cpuclk = qdev_init_clock_out(DEVICE(obj), "cpu-refclk"); + clock_set_hz(s->cpuclk, 1000000000); /* 1 GHz */ +} + static const TypeInfo boston_device = { .name = TYPE_MIPS_BOSTON, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BostonState), + .instance_init = mips_boston_instance_init, }; static void boston_register_types(void) @@ -462,6 +473,8 @@ static void boston_mach_init(MachineState *machine) &error_fatal); object_property_set_int(OBJECT(&s->cps), "num-vp", machine->smp.cpus, &error_fatal); + qdev_connect_clock_in(DEVICE(&s->cps), "clk-in", + qdev_get_clock_out(dev, "cpu-refclk")); sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); From eea1f5bac6f7ea71ef357bb8166512ef759a7b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:58:02 +0200 Subject: [PATCH 28/44] hw/mips/malta: Set CPU frequency to 320 MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CoreLV card with ID 0x420's CPU clocked at 320 MHz. Create a 'cpuclk' output clock and connect it to the CPU input clock. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-20-f4bug@amsat.org> --- hw/mips/malta.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 4019c9dc1a..1e2b750719 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -26,6 +26,7 @@ #include "qemu/units.h" #include "qemu-common.h" #include "cpu.h" +#include "hw/clock.h" #include "hw/southbridge/piix.h" #include "hw/isa/superio.h" #include "hw/char/serial.h" @@ -57,6 +58,7 @@ #include "sysemu/kvm.h" #include "hw/semihosting/semihost.h" #include "hw/mips/cps.h" +#include "hw/qdev-clock.h" #define ENVP_ADDR 0x80002000l #define ENVP_NB_ENTRIES 16 @@ -94,6 +96,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(MaltaState, MIPS_MALTA) struct MaltaState { SysBusDevice parent_obj; + Clock *cpuclk; MIPSCPSState cps; qemu_irq i8259[ISA_NUM_IRQS]; }; @@ -1159,7 +1162,7 @@ static void main_cpu_reset(void *opaque) } } -static void create_cpu_without_cps(MachineState *ms, +static void create_cpu_without_cps(MachineState *ms, MaltaState *s, qemu_irq *cbus_irq, qemu_irq *i8259_irq) { CPUMIPSState *env; @@ -1167,7 +1170,7 @@ static void create_cpu_without_cps(MachineState *ms, int i; for (i = 0; i < ms->smp.cpus; i++) { - cpu = MIPS_CPU(cpu_create(ms->cpu_type)); + cpu = mips_cpu_create_with_clock(ms->cpu_type, s->cpuclk); /* Init internal devices */ cpu_mips_irq_init_cpu(cpu); @@ -1189,6 +1192,7 @@ static void create_cps(MachineState *ms, MaltaState *s, &error_fatal); object_property_set_int(OBJECT(&s->cps), "num-vp", ms->smp.cpus, &error_fatal); + qdev_connect_clock_in(DEVICE(&s->cps), "clk-in", s->cpuclk); sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal); sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); @@ -1203,7 +1207,7 @@ static void mips_create_cpu(MachineState *ms, MaltaState *s, if ((ms->smp.cpus > 1) && cpu_supports_cps_smp(ms->cpu_type)) { create_cps(ms, s, cbus_irq, i8259_irq); } else { - create_cpu_without_cps(ms, cbus_irq, i8259_irq); + create_cpu_without_cps(ms, s, cbus_irq, i8259_irq); } } @@ -1421,10 +1425,19 @@ void mips_malta_init(MachineState *machine) pci_vga_init(pci_bus); } +static void mips_malta_instance_init(Object *obj) +{ + MaltaState *s = MIPS_MALTA(obj); + + s->cpuclk = qdev_init_clock_out(DEVICE(obj), "cpu-refclk"); + clock_set_hz(s->cpuclk, 320000000); /* 320 MHz */ +} + static const TypeInfo mips_malta_device = { .name = TYPE_MIPS_MALTA, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MaltaState), + .instance_init = mips_malta_instance_init, }; static void mips_malta_machine_init(MachineClass *mc) From ba25670c1d3e122bfa5a43cd785f5eb4988861d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:58:03 +0200 Subject: [PATCH 29/44] hw/mips/cps: Do not allow use without input clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now than all QOM users provides the input clock, do not allow using a CPS without input clock connected. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-21-f4bug@amsat.org> --- hw/mips/cps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/mips/cps.c b/hw/mips/cps.c index af7b58c4bd..c624821315 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -74,6 +74,11 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) bool itu_present = false; bool saar_present = false; + if (!clock_get(s->clock)) { + error_setg(errp, "CPS input clock is not connected to an output clock"); + return; + } + for (i = 0; i < s->num_vp; i++) { cpu = MIPS_CPU(object_new(s->cpu_type)); From 8a6359f937632d4b47bfaf0640c5acbf73736521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 11:58:04 +0200 Subject: [PATCH 30/44] target/mips/cpu: Display warning when CPU is used without input clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All our QOM users provides an input clock. In order to avoid avoid future machines added without clock, display a warning. User-mode emulation use the CP0 timer with the RDHWR instruction (see commit cdfcad788394) so keep using the fixed 200 MHz clock without diplaying any warning. Only display it in system-mode emulation. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20201012095804.3335117-22-f4bug@amsat.org> --- target/mips/cpu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 33a9ed5c24..76d50b00b4 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -19,12 +19,14 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qapi/error.h" #include "cpu.h" #include "internal.h" #include "kvm_mips.h" #include "qemu/module.h" #include "sysemu/kvm.h" +#include "sysemu/qtest.h" #include "exec/exec-all.h" #include "hw/qdev-properties.h" #include "hw/qdev-clock.h" @@ -158,6 +160,14 @@ static void mips_cpu_realizefn(DeviceState *dev, Error **errp) Error *local_err = NULL; if (!clock_get(cpu->clock)) { +#ifndef CONFIG_USER_ONLY + if (!qtest_enabled()) { + g_autofree char *cpu_freq_str = freq_to_str(CPU_FREQ_HZ_DEFAULT); + + warn_report("CPU input clock is not connected to any output clock, " + "using default frequency of %s.", cpu_freq_str); + } +#endif /* Initialize the frequency in case the clock remains unconnected. */ clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT); } From 9a2133f45c287e99ef23896a7a33b3d2dbfe97fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 5 Sep 2020 22:01:24 +0200 Subject: [PATCH 31/44] hw/mips/malta: Fix FPGA I/O region size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FPGA present on the CoreCard has an I/O region 1MiB wide. Refs: - Atlas User’s Manual (Document Number: MD00005) - Malta User’s Manual (Document Number: MD00048) Fixes: ea85df72b60 ("mips_malta: convert to memory API") Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20200905213049.761949-1-f4bug@amsat.org> --- hw/mips/malta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 1e2b750719..a4a4c38626 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -578,7 +578,7 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, memory_region_init_alias(&s->iomem_lo, NULL, "malta-fpga", &s->iomem, 0, 0x900); memory_region_init_alias(&s->iomem_hi, NULL, "malta-fpga", - &s->iomem, 0xa00, 0x10000 - 0xa00); + &s->iomem, 0xa00, 0x100000 - 0xa00); memory_region_add_subregion(address_space, base, &s->iomem_lo); memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi); From c5cdf7561311a2dd37eb7af636247440182e6e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 17:35:50 +0200 Subject: [PATCH 32/44] hw/mips/malta: Move gt64120 related code together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'empty_slot' region created is related to the gt64120. Move its creation close to the gt64120 instance creation. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201012160503.3472140-2-f4bug@amsat.org> --- hw/mips/malta.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index a4a4c38626..944045d770 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1239,13 +1239,6 @@ void mips_malta_init(MachineState *machine) DeviceState *dev = qdev_new(TYPE_MIPS_MALTA); MaltaState *s = MIPS_MALTA(dev); - /* - * The whole address space decoded by the GT-64120A doesn't generate - * exception when accessing invalid memory. Create an empty slot to - * emulate this feature. - */ - empty_slot_init("GT64120", 0, 0x20000000); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); /* create CPU */ @@ -1399,6 +1392,12 @@ void mips_malta_init(MachineState *machine) /* Northbridge */ pci_bus = gt64120_register(s->i8259); + /* + * The whole address space decoded by the GT-64120A doesn't generate + * exception when accessing invalid memory. Create an empty slot to + * emulate this feature. + */ + empty_slot_init("GT64120", 0, 0x20000000); /* Southbridge */ dev = piix4_create(pci_bus, &isa_bus, &smbus); From 8df525a558e85aee7a2c757dd7654173ef369544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 17:56:40 +0200 Subject: [PATCH 33/44] hw/mips/malta: Use clearer qdev style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be consistent with the other code base uses, rewrite slightly how the MIPS_MALTA object is created. No logical change. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201012160503.3472140-3-f4bug@amsat.org> --- hw/mips/malta.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 944045d770..ff3225bb8e 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1235,11 +1235,11 @@ void mips_malta_init(MachineState *machine) DriveInfo *dinfo; int fl_idx = 0; int be; + MaltaState *s; + DeviceState *dev; - DeviceState *dev = qdev_new(TYPE_MIPS_MALTA); - MaltaState *s = MIPS_MALTA(dev); - - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + s = MIPS_MALTA(qdev_new(TYPE_MIPS_MALTA)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal); /* create CPU */ mips_create_cpu(machine, s, &cbus_irq, &i8259_irq); From 9d585eaa87bf1c5f66e12d6c4a8a38c80f69c5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 27 Sep 2020 14:21:11 +0200 Subject: [PATCH 34/44] hw/mips: Simplify loading 64-bit ELF kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 82790064116 ("Cast ELF datatypes properly to host 64bit types") we don't need to sign-extend the entry_point address. Remove this unnecessary code. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200927163943.614604-2-f4bug@amsat.org> --- hw/mips/mipssim.c | 6 +----- hw/mips/r4k.c | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index f0042f7f43..afef4f2e77 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -77,11 +77,7 @@ static int64_t load_kernel(void) (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, NULL, big_endian, EM_MIPS, 1, 0); - if (kernel_size >= 0) { - if ((entry & ~0x7fffffffULL) == 0x80000000) { - entry = (int32_t)entry; - } - } else { + if (kernel_size < 0) { error_report("could not load kernel '%s': %s", loaderparams.kernel_filename, load_elf_strerror(kernel_size)); diff --git a/hw/mips/r4k.c b/hw/mips/r4k.c index 39bc626e7c..7ee37c4968 100644 --- a/hw/mips/r4k.c +++ b/hw/mips/r4k.c @@ -102,11 +102,7 @@ static int64_t load_kernel(void) (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, NULL, big_endian, EM_MIPS, 1, 0); - if (kernel_size >= 0) { - if ((entry & ~0x7fffffffULL) == 0x80000000) { - entry = (int32_t)entry; - } - } else { + if (kernel_size < 0) { error_report("could not load kernel '%s': %s", loaderparams.kernel_filename, load_elf_strerror(kernel_size)); From acab36ca25101930b263dd9e8afd9b244354d338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 27 Sep 2020 13:18:17 +0200 Subject: [PATCH 35/44] hw/mips: Simplify code using ROUND_UP(INITRD_PAGE_SIZE) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using a INITRD_PAGE_MASK definition, use the simpler INITRD_PAGE_SIZE one which allows us to simplify the code by using directly the self-explicit ROUND_UP() macro. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200927163943.614604-3-f4bug@amsat.org> --- hw/mips/fuloong2e.c | 3 +-- hw/mips/malta.c | 6 +++--- hw/mips/mipssim.c | 3 +-- hw/mips/r4k.c | 3 +-- include/hw/mips/mips.h | 4 +++- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index b8234f6108..de66215f95 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -133,8 +133,7 @@ static int64_t load_kernel(CPUMIPSState *env) if (loaderparams.initrd_filename) { initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & - INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); if (initrd_offset + initrd_size > ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); diff --git a/hw/mips/malta.c b/hw/mips/malta.c index ff3225bb8e..beb0f43941 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1077,9 +1077,9 @@ static int64_t load_kernel(void) * the initrd. It takes at most 128kiB for 2GB RAM and 4kiB * pages. */ - initrd_offset = (loaderparams.ram_low_size - initrd_size - - (128 * KiB) - - ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(loaderparams.ram_low_size + - (initrd_size + 128 * KiB), + INITRD_PAGE_SIZE); if (kernel_high >= initrd_offset) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index afef4f2e77..97dcc23247 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -90,8 +90,7 @@ static int64_t load_kernel(void) if (loaderparams.initrd_filename) { initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & - INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); if (initrd_offset + initrd_size > loaderparams.ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); diff --git a/hw/mips/r4k.c b/hw/mips/r4k.c index 7ee37c4968..3830854342 100644 --- a/hw/mips/r4k.c +++ b/hw/mips/r4k.c @@ -115,8 +115,7 @@ static int64_t load_kernel(void) if (loaderparams.initrd_filename) { initrd_size = get_image_size(loaderparams.initrd_filename); if (initrd_size > 0) { - initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & - INITRD_PAGE_MASK; + initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); if (initrd_offset + initrd_size > ram_size) { error_report("memory too small for initial ram disk '%s'", loaderparams.initrd_filename); diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h index 0af4c3d5d7..6c9c8805f3 100644 --- a/include/hw/mips/mips.h +++ b/include/hw/mips/mips.h @@ -2,8 +2,10 @@ #define HW_MIPS_H /* Definitions for mips board emulation. */ +#include "qemu/units.h" + /* Kernels can be configured with 64KB pages */ -#define INITRD_PAGE_MASK (~((1 << 16) - 1)) +#define INITRD_PAGE_SIZE (64 * KiB) #include "exec/memory.h" From 27cf0896bfd84a9ccb2cfe315952338f00aa086e Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 2 Sep 2020 18:42:26 -0400 Subject: [PATCH 36/44] hw/mips: Rename TYPE_MIPS_BOSTON to TYPE_BOSTON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will make the type name constant consistent with the name of the type checking macro. Signed-off-by: Eduardo Habkost Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20200902224311.1321159-19-ehabkost@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/boston.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/mips/boston.c b/hw/mips/boston.c index cf2296f448..74c18edbb3 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -44,10 +44,10 @@ #include #include "qom/object.h" -#define TYPE_MIPS_BOSTON "mips-boston" +#define TYPE_BOSTON "mips-boston" typedef struct BostonState BostonState; DECLARE_INSTANCE_CHECKER(BostonState, BOSTON, - TYPE_MIPS_BOSTON) + TYPE_BOSTON) struct BostonState { SysBusDevice parent_obj; @@ -262,7 +262,7 @@ static void mips_boston_instance_init(Object *obj) } static const TypeInfo boston_device = { - .name = TYPE_MIPS_BOSTON, + .name = TYPE_BOSTON, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BostonState), .instance_init = mips_boston_instance_init, @@ -455,7 +455,7 @@ static void boston_mach_init(MachineState *machine) exit(1); } - dev = qdev_new(TYPE_MIPS_BOSTON); + dev = qdev_new(TYPE_BOSTON); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); s = BOSTON(dev); From a4374f86dc648b6cf10a7c8c40bde33722e5b25d Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Tue, 21 Jul 2020 09:15:05 +0300 Subject: [PATCH 37/44] hw/mips: Remove exit(1) in case of missing ROM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch updates MIPS-based machines to allow starting them without ROM. In this case CPU starts to execute instructions from the empty memory, but QEMU allows introspecting the machine configuration. Signed-off-by: Pavel Dovgalyuk Reviewed-by: Philippe Mathieu-Daudé Message-Id: <159531210571.24117.231100997794891819.stgit@pasha-ThinkPad-X280> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 8 +++----- hw/mips/jazz.c | 8 +++----- hw/mips/malta.c | 11 ++++------- hw/mips/mipssim.c | 10 +++------- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index de66215f95..a9e0c2f8d3 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -337,10 +337,8 @@ static void mips_fuloong2e_init(MachineState *machine) kernel_entry = load_kernel(env); write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); } else { - if (bios_name == NULL) { - bios_name = FULOONG_BIOSNAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + bios_name ?: FULOONG_BIOSNAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); @@ -350,7 +348,7 @@ static void mips_fuloong2e_init(MachineState *machine) } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - !kernel_filename && !qtest_enabled()) { + bios_name && !qtest_enabled()) { error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 8f1ad55ba3..71448f72ac 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -218,10 +218,7 @@ static void mips_jazz_init(MachineState *machine, memory_region_add_subregion(address_space, 0xfff00000LL, bios2); /* load the BIOS image. */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0xfff00000LL, MAGNUM_BIOS_SIZE); @@ -229,7 +226,8 @@ static void mips_jazz_init(MachineState *machine, } else { bios_size = -1; } - if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) { + if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) + && bios_name && !qtest_enabled()) { error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } diff --git a/hw/mips/malta.c b/hw/mips/malta.c index beb0f43941..9d1a3b50b7 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1332,10 +1332,8 @@ void mips_malta_init(MachineState *machine) /* Load firmware from flash. */ if (!dinfo) { /* Load a BIOS image. */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + bios_name ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, FLASH_ADDRESS, BIOS_SIZE); @@ -1344,9 +1342,8 @@ void mips_malta_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - !kernel_filename && !qtest_enabled()) { - error_report("Could not load MIPS bios '%s', and no " - "-kernel argument was specified", bios_name); + bios_name && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } } diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index 97dcc23247..aaa62a0f4b 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -177,10 +177,7 @@ mips_mipssim_init(MachineState *machine) /* Map the BIOS / boot exception handler. */ memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); /* Load a BIOS / boot exception handler image. */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name ?: BIOS_FILENAME); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); g_free(filename); @@ -188,10 +185,9 @@ mips_mipssim_init(MachineState *machine) bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && - !kernel_filename && !qtest_enabled()) { + bios_name && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ - error_report("Could not load MIPS bios '%s', and no " - "-kernel argument was specified", bios_name); + error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } else { /* We have a boot vector start address. */ From 1d2ff14b72ed11d577cbe42a3fef9fcce522418a Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Thu, 15 Oct 2020 14:25:02 +0300 Subject: [PATCH 38/44] tests/acceptance: Add MIPS record/replay tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds MIPS-targeted acceptance tests for record/replay functions. Signed-off-by: Pavel Dovgalyuk Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <160276110297.2705.10918105269658307206.stgit@pasha-ThinkPad-X280> [PMD: Moved 'override timeout' comment from instance to class, moved nanomips tests to ReplayKernelSlow class, tagged ReplayKernelSlow class with AVOCADO_TIMEOUT_EXPECTED] Signed-off-by: Philippe Mathieu-Daudé --- tests/acceptance/replay_kernel.py | 167 +++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/tests/acceptance/replay_kernel.py b/tests/acceptance/replay_kernel.py index 952f429cac..00c228382b 100644 --- a/tests/acceptance/replay_kernel.py +++ b/tests/acceptance/replay_kernel.py @@ -9,6 +9,8 @@ # later. See the COPYING file in the top-level directory. import os +import lzma +import shutil import logging import time @@ -19,7 +21,7 @@ from avocado.utils import archive from avocado.utils import process from boot_linux_console import LinuxKernelTest -class ReplayKernel(LinuxKernelTest): +class ReplayKernelBase(LinuxKernelTest): """ Boots a Linux kernel in record mode and checks that the console is operational and the kernel command line is properly passed @@ -74,6 +76,7 @@ class ReplayKernel(LinuxKernelTest): logger = logging.getLogger('replay') logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) +class ReplayKernelNormal(ReplayKernelBase): @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_x86_64_pc(self): """ @@ -91,6 +94,51 @@ class ReplayKernel(LinuxKernelTest): self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + def test_mips_malta(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb') + deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-4kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + def test_mips64el_malta(self): + """ + This test requires the ar tool to extract "data.tar.gz" from + the Debian package. + + The kernel can be rebuilt using this Debian kernel source [1] and + following the instructions on [2]. + + [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ + #linux-source-2.6.32_2.6.32-48 + [2] https://kernel-team.pages.debian.net/kernel-handbook/ + ch-common-tasks.html#s-common-official + + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb') + deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-2.6.32-5-5kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + def test_aarch64_virt(self): """ :avocado: tags=arch:aarch64 @@ -302,3 +350,120 @@ class ReplayKernel(LinuxKernelTest): file_path = self.fetch_asset(tar_url, asset_hash=tar_hash) self.do_test_advcal_2018(file_path, 'santas-sleigh-ride.elf', args=('-cpu', 'dc233c')) + +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout') +class ReplayKernelSlow(ReplayKernelBase): + # Override the timeout, because this kernel includes an inner + # loop which is executed with TB recompilings during replay, + # making it very slow. + timeout = 180 + + def test_mips_malta_cpio(self): + """ + :avocado: tags=arch:mips + :avocado: tags=machine:malta + :avocado: tags=endian:big + :avocado: tags=slowness:high + """ + deb_url = ('http://snapshot.debian.org/archive/debian/' + '20160601T041800Z/pool/main/l/linux/' + 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb') + deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-4.5.0-2-4kc-malta') + initrd_url = ('https://github.com/groeck/linux-build-test/raw/' + '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' + 'mips/rootfs.cpio.gz') + initrd_hash = 'bf806e17009360a866bf537f6de66590de349a99' + initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path)) + + @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code') + def test_mips64el_malta_5KEc_cpio(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:malta + :avocado: tags=endian:little + :avocado: tags=slowness:high + """ + kernel_url = ('https://github.com/philmd/qemu-testing-blob/' + 'raw/9ad2df38/mips/malta/mips64el/' + 'vmlinux-3.19.3.mtoman.20150408') + kernel_hash = '00d1d268fb9f7d8beda1de6bebcc46e884d71754' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + initrd_url = ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/' + 'mipsel64/rootfs.mipsel64r1.cpio.gz') + initrd_hash = '1dbb8a396e916847325284dbe2151167' + initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5', + asset_hash=initrd_hash) + initrd_path = self.workdir + "rootfs.cpio" + archive.gzip_uncompress(initrd_path_gz, initrd_path) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path, '-cpu', '5KEc')) + + def do_test_mips_malta32el_nanomips(self, kernel_path_xz): + kernel_path = self.workdir + "kernel" + with lzma.open(kernel_path_xz, 'rb') as f_in: + with open(kernel_path, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'mem=256m@@0x0 ' + 'console=ttyS0') + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-cpu', 'I7200')) + + def test_mips_malta32el_nanomips_4k(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page4k.xz') + kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) + + def test_mips_malta32el_nanomips_16k_up(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page16k_up.xz') + kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) + + def test_mips_malta32el_nanomips_64k_dbg(self): + """ + :avocado: tags=arch:mipsel + :avocado: tags=machine:malta + :avocado: tags=endian:little + """ + kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page64k_dbg.xz') + kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180' + kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.do_test_mips_malta32el_nanomips(kernel_path_xz) From b5330cf19ad29a71c3981d315a14f17db539ec80 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 7 Oct 2020 16:39:35 +0800 Subject: [PATCH 39/44] docs/system: Update MIPS CPU documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Loongson-3A CPU models description. Signed-off-by: Huacai Chen Message-Id: <1602059975-10115-10-git-send-email-chenhc@lemote.com> [PMD: Split patch in 2: CPU / machine] Signed-off-by: Philippe Mathieu-Daudé --- docs/system/cpu-models-mips.rst.inc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/system/cpu-models-mips.rst.inc b/docs/system/cpu-models-mips.rst.inc index 499b5b6fed..02cc4bb884 100644 --- a/docs/system/cpu-models-mips.rst.inc +++ b/docs/system/cpu-models-mips.rst.inc @@ -48,11 +48,17 @@ across all desired hosts. ``I6400`` MIPS64 Processor (Release 6, 2014) +``Loongson-2E`` + MIPS64 Processor (Loongson 2, 2006) + ``Loongson-2F`` MIPS64 Processor (Loongson 2, 2008) -``Loongson-2E`` - MIPS64 Processor (Loongson 2, 2006) +``Loongson-3A1000`` + MIPS64 Processor (Loongson 3, 2010) + +``Loongson-3A4000`` + MIPS64 Processor (Loongson 3, 2018) ``mips64dspr2`` MIPS64 Processor (Release 2, 2006) From ca263c0fb9f33cc746e6e3d968b7db80072ecf86 Mon Sep 17 00:00:00 2001 From: Aleksandar Markovic Date: Wed, 7 Oct 2020 22:37:21 +0200 Subject: [PATCH 40/44] MAINTAINERS: Remove myself MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have been working on project other than QEMU for some time, and would like to devote myself to that project. It is impossible for me to find enough time to perform maintainer's duties with needed meticulousness and patience. I wish prosperous future to QEMU and all colleagues in QEMU community. Signed-off-by: Aleksandar Markovic Message-Id: <1602103041-32017-6-git-send-email-aleksandar.qemu.devel@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 99ab02bbab..b91bd754d1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -220,11 +220,10 @@ F: hw/microblaze/ F: disas/microblaze.c MIPS TCG CPUs -M: Aleksandar Markovic R: Aurelien Jarno R: Jiaxun Yang R: Aleksandar Rikalo -S: Maintained +S: Orphaned F: target/mips/ F: default-configs/*mips* F: disas/*mips* @@ -386,7 +385,6 @@ F: target/arm/kvm.c MIPS KVM CPUs M: Huacai Chen -M: Aleksandar Markovic S: Odd Fixes F: target/mips/kvm.c @@ -1123,10 +1121,9 @@ F: hw/display/jazz_led.c F: hw/dma/rc4030.c Malta -M: Aleksandar Markovic M: Philippe Mathieu-Daudé R: Aurelien Jarno -S: Maintained +S: Odd Fixes F: hw/isa/piix4.c F: hw/acpi/piix4.c F: hw/mips/malta.c @@ -1136,14 +1133,12 @@ F: tests/acceptance/linux_ssh_mips_malta.py F: tests/acceptance/machine_mips_malta.py Mipssim -M: Aleksandar Markovic R: Aleksandar Rikalo -S: Odd Fixes +S: Orphaned F: hw/mips/mipssim.c F: hw/net/mipsnet.c R4000 -M: Aleksandar Markovic R: Aurelien Jarno R: Aleksandar Rikalo S: Obsolete @@ -1152,7 +1147,6 @@ F: hw/mips/r4k.c Fuloong 2E M: Huacai Chen M: Philippe Mathieu-Daudé -M: Aleksandar Markovic R: Jiaxun Yang S: Odd Fixes F: hw/mips/fuloong2e.c @@ -2823,12 +2817,11 @@ F: tcg/i386/ F: disas/i386.c MIPS TCG target -M: Aleksandar Markovic R: Aurelien Jarno R: Huacai Chen R: Jiaxun Yang R: Aleksandar Rikalo -S: Maintained +S: Orphaned F: tcg/mips/ PPC TCG target @@ -3169,7 +3162,7 @@ S: Odd Fixes F: scripts/git-submodule.sh UI translations -M: Aleksandar Markovic +S: Orphaned F: po/*.po Sphinx documentation configuration and build machinery From cf960317cb644c772610c1a275a88635af4a40d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 9 Oct 2020 17:05:13 +0200 Subject: [PATCH 41/44] MAINTAINERS: Put myself forward for MIPS target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid the MIPS target being orphan, volunteer to keep an eye on it and put together pull requests. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Jiaxun Yang Reviewed-by: Thomas Huth Message-Id: <20201013101659.3557154-2-f4bug@amsat.org> --- MAINTAINERS | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index b91bd754d1..50fb9fda34 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -220,10 +220,11 @@ F: hw/microblaze/ F: disas/microblaze.c MIPS TCG CPUs +M: Philippe Mathieu-Daudé R: Aurelien Jarno R: Jiaxun Yang R: Aleksandar Rikalo -S: Orphaned +S: Odd Fixes F: target/mips/ F: default-configs/*mips* F: disas/*mips* @@ -2817,11 +2818,12 @@ F: tcg/i386/ F: disas/i386.c MIPS TCG target +M: Philippe Mathieu-Daudé R: Aurelien Jarno R: Huacai Chen R: Jiaxun Yang R: Aleksandar Rikalo -S: Orphaned +S: Odd Fixes F: tcg/mips/ PPC TCG target From 4ba98e96e0d1cf8c6188a3169fbb2e1f08838a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 9 Oct 2020 18:15:59 +0200 Subject: [PATCH 42/44] MAINTAINERS: Downgrade MIPS Boston to 'Odd Fixes', fix Paul Burton mail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Paul's Wavecomp email has been bouncing for months. He told us he "no longer has access to modern MIPS CPUs or Boston hardware, and wouldn't currently have time to spend on them if he did." [1] but "perhaps that might change in the future." [2]. Be fair and downgrade the status of the Boston board to "Odd Fixes" (has a maintainer but they don't have time to do much other). Similarly to commit 2b107c2c1c (".mailmap: Update Paul Burton email address"), update his email address here too. [1] https://www.mail-archive.com/qemu-devel@nongnu.org/msg718739.html [2] https://www.mail-archive.com/qemu-devel@nongnu.org/msg728605.html Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-Id: <20201013101659.3557154-4-f4bug@amsat.org> --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 50fb9fda34..8770cd6d05 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1162,9 +1162,9 @@ S: Maintained F: hw/intc/loongson_liointc.c Boston -M: Paul Burton +M: Paul Burton R: Aleksandar Rikalo -S: Maintained +S: Odd Fixes F: hw/core/loader-fit.c F: hw/mips/boston.c F: hw/pci-host/xilinx-pcie.c From 5ca2b252692761e9c7bea60634d3ecca96be0599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 9 Oct 2020 17:11:00 +0200 Subject: [PATCH 43/44] MAINTAINERS: Remove duplicated Malta test entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Malta tests are already covered in the Malta section. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-Id: <20201013101659.3557154-3-f4bug@amsat.org> --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8770cd6d05..a7f0acf866 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -237,8 +237,6 @@ F: include/hw/intc/mips_gic.h F: include/hw/mips/ F: include/hw/misc/mips_* F: include/hw/timer/mips_gictimer.h -F: tests/acceptance/linux_ssh_mips_malta.py -F: tests/acceptance/machine_mips_malta.py F: tests/tcg/mips/ K: ^Subject:.*(?i)mips From 68fa519a6cb455005317bd61f95214b58b2f1e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 16 Oct 2020 15:20:37 +0200 Subject: [PATCH 44/44] target/mips: Increase number of TLB entries on the 34Kf core (16 -> 64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per "MIPS32 34K Processor Core Family Software User's Manual, Revision 01.13" page 8 in "Joint TLB (JTLB)" section: "The JTLB is a fully associative TLB cache containing 16, 32, or 64-dual-entries mapping up to 128 virtual pages to their corresponding physical addresses." There is no particular reason to restrict the 34Kf core model to 16 TLB entries, so raise its config to 64. This is helpful for other projects, in particular the Yocto Project: Yocto Project uses qemu-system-mips 34Kf cpu model, to run 32bit MIPS CI loop. It was observed that in this case CI test execution time was almost twice longer than 64bit MIPS variant that runs under MIPS64R2-generic model. It was investigated and concluded that the difference in number of TLBs 16 in 34Kf case vs 64 in MIPS64R2-generic is responsible for most of CI real time execution difference. Because with 16 TLBs linux user-land trashes TLB more and it needs to execute more instructions in TLB refill handler calls, as result it runs much longer. (https://lists.gnu.org/archive/html/qemu-devel/2020-10/msg03428.html) Buglink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=13992 Reported-by: Victor Kamensky Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20201016133317.553068-1-f4bug@amsat.org> --- target/mips/translate_init.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/translate_init.c.inc b/target/mips/translate_init.c.inc index c735b2bf66..fb5a9b38e5 100644 --- a/target/mips/translate_init.c.inc +++ b/target/mips/translate_init.c.inc @@ -254,7 +254,7 @@ const mips_def_t mips_defs[] = .CP0_PRid = 0x00019500, .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (MMU_TYPE_R4000 << CP0C0_MT), - .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) | + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA),