All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses
@ 2015-04-28 12:41 Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 1/7] target-mips: extend selected CP0 registers to 64-bits in MIPS32 Leon Alrae
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Hi,

This patchset adds large physical address support in MIPS, specifically:
* eXtended Physical Addressing (XPA)
* Large Physical Addressing (LPA)

XPA and LPA are enabled in MIPS32R5-generic and MIPS64R6-generic cores
respectively.

The series applies on top of the Config5.FRE patches.

Regards,
Leon

Leon Alrae (7):
  target-mips: extend selected CP0 registers to 64-bits in MIPS32
  target-mips: support Page Frame Number Extension field
  target-mips: add CP0.PageGrain.ELPA support
  target-mips: add MTHC0 and MFHC0 instructions
  target-mips: correct MFC0 for CP0.EntryLo in MIPS64
  target-mips: remove invalid comments in translate_init.c
  target-mips: enable XPA and LPA features

 disas/mips.c                 |   2 +
 target-mips/cpu.h            |  42 ++++++--
 target-mips/machine.c        |  21 ++--
 target-mips/mips-defs.h      |   4 +-
 target-mips/op_helper.c      |  60 ++++++++---
 target-mips/translate.c      | 234 +++++++++++++++++++++++++++++++++++++++++--
 target-mips/translate_init.c |  24 ++---
 7 files changed, 328 insertions(+), 59 deletions(-)

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 1/7] target-mips: extend selected CP0 registers to 64-bits in MIPS32
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field Leon Alrae
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Extend EntryLo0, EntryLo1, LLAddr and TagLo from 32 to 64 bits in MIPS32.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       | 14 +++++++-------
 target-mips/machine.c   | 20 ++++++++++----------
 target-mips/op_helper.c |  8 ++++----
 target-mips/translate.c |  5 +++--
 4 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 03eb888..2dfa139 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -34,7 +34,7 @@ struct r4k_tlb_t {
     uint_fast16_t RI0:1;
     uint_fast16_t RI1:1;
     uint_fast16_t EHINV:1;
-    target_ulong PFN[2];
+    uint64_t PFN[2];
 };
 
 #if !defined(CONFIG_USER_ONLY)
@@ -225,7 +225,7 @@ struct CPUMIPSState {
     uint32_t SEGBITS;
     uint32_t PABITS;
     target_ulong SEGMask;
-    target_ulong PAMask;
+    uint64_t PAMask;
 
     int32_t msair;
 #define MSAIR_ProcID    8
@@ -273,8 +273,8 @@ struct CPUMIPSState {
 #define CP0VPEOpt_DWX2	2
 #define CP0VPEOpt_DWX1	1
 #define CP0VPEOpt_DWX0	0
-    target_ulong CP0_EntryLo0;
-    target_ulong CP0_EntryLo1;
+    uint64_t CP0_EntryLo0;
+    uint64_t CP0_EntryLo1;
 #if defined(TARGET_MIPS64)
 # define CP0EnLo_RI 63
 # define CP0EnLo_XI 62
@@ -471,11 +471,11 @@ struct CPUMIPSState {
     int32_t CP0_Config6;
     int32_t CP0_Config7;
     /* XXX: Maybe make LLAddr per-TC? */
-    target_ulong lladdr;
+    uint64_t lladdr;
     target_ulong llval;
     target_ulong llnewval;
     target_ulong llreg;
-    target_ulong CP0_LLAddr_rw_bitmask;
+    uint64_t CP0_LLAddr_rw_bitmask;
     int CP0_LLAddr_shift;
     target_ulong CP0_WatchLo[8];
     int32_t CP0_WatchHi[8];
@@ -502,7 +502,7 @@ struct CPUMIPSState {
 #define CP0DB_DSS  0
     target_ulong CP0_DEPC;
     int32_t CP0_Performance0;
-    int32_t CP0_TagLo;
+    uint64_t CP0_TagLo;
     int32_t CP0_DataLo;
     int32_t CP0_TagHi;
     int32_t CP0_DataHi;
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 7d1fa32..559402c 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -142,8 +142,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
     v->RI0 = (flags >> 13) & 1;
     v->XI1 = (flags >> 12) & 1;
     v->XI0 = (flags >> 11) & 1;
-    qemu_get_betls(f, &v->PFN[0]);
-    qemu_get_betls(f, &v->PFN[1]);
+    qemu_get_be64s(f, &v->PFN[0]);
+    qemu_get_be64s(f, &v->PFN[1]);
 
     return 0;
 }
@@ -169,8 +169,8 @@ static void put_tlb(QEMUFile *f, void *pv, size_t size)
     qemu_put_be32s(f, &v->PageMask);
     qemu_put_8s(f, &v->ASID);
     qemu_put_be16s(f, &flags);
-    qemu_put_betls(f, &v->PFN[0]);
-    qemu_put_betls(f, &v->PFN[1]);
+    qemu_put_be64s(f, &v->PFN[0]);
+    qemu_put_be64s(f, &v->PFN[1]);
 }
 
 const VMStateInfo vmstate_info_tlb = {
@@ -201,8 +201,8 @@ const VMStateDescription vmstate_tlb = {
 
 const VMStateDescription vmstate_mips_cpu = {
     .name = "cpu",
-    .version_id = 6,
-    .minimum_version_id = 6,
+    .version_id = 7,
+    .minimum_version_id = 7,
     .post_load = cpu_post_load,
     .fields = (VMStateField[]) {
         /* Active TC */
@@ -237,8 +237,8 @@ const VMStateDescription vmstate_mips_cpu = {
         VMSTATE_UINTTL(env.CP0_VPESchedule, MIPSCPU),
         VMSTATE_UINTTL(env.CP0_VPEScheFBack, MIPSCPU),
         VMSTATE_INT32(env.CP0_VPEOpt, MIPSCPU),
-        VMSTATE_UINTTL(env.CP0_EntryLo0, MIPSCPU),
-        VMSTATE_UINTTL(env.CP0_EntryLo1, MIPSCPU),
+        VMSTATE_UINT64(env.CP0_EntryLo0, MIPSCPU),
+        VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU),
         VMSTATE_UINTTL(env.CP0_Context, MIPSCPU),
         VMSTATE_INT32(env.CP0_PageMask, MIPSCPU),
         VMSTATE_INT32(env.CP0_PageGrain, MIPSCPU),
@@ -269,7 +269,7 @@ const VMStateDescription vmstate_mips_cpu = {
         VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
         VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
         VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
-        VMSTATE_UINTTL(env.lladdr, MIPSCPU),
+        VMSTATE_UINT64(env.lladdr, MIPSCPU),
         VMSTATE_UINTTL_ARRAY(env.CP0_WatchLo, MIPSCPU, 8),
         VMSTATE_INT32_ARRAY(env.CP0_WatchHi, MIPSCPU, 8),
         VMSTATE_UINTTL(env.CP0_XContext, MIPSCPU),
@@ -277,7 +277,7 @@ const VMStateDescription vmstate_mips_cpu = {
         VMSTATE_INT32(env.CP0_Debug, MIPSCPU),
         VMSTATE_UINTTL(env.CP0_DEPC, MIPSCPU),
         VMSTATE_INT32(env.CP0_Performance0, MIPSCPU),
-        VMSTATE_INT32(env.CP0_TagLo, MIPSCPU),
+        VMSTATE_UINT64(env.CP0_TagLo, MIPSCPU),
         VMSTATE_INT32(env.CP0_DataLo, MIPSCPU),
         VMSTATE_INT32(env.CP0_TagHi, MIPSCPU),
         VMSTATE_INT32(env.CP0_DataHi, MIPSCPU),
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index dd89068..c9a60bd 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1996,12 +1996,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
         env->CP0_EntryHi = tlb->VPN | tlb->ASID;
         env->CP0_PageMask = tlb->PageMask;
         env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
-                        ((target_ulong)tlb->RI0 << CP0EnLo_RI) |
-                        ((target_ulong)tlb->XI0 << CP0EnLo_XI) |
+                        ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
+                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) |
                         (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
         env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
-                        ((target_ulong)tlb->RI1 << CP0EnLo_RI) |
-                        ((target_ulong)tlb->XI1 << CP0EnLo_XI) |
+                        ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
+                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) |
                         (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
     }
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8bf08c8..0f875be 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -19391,7 +19391,8 @@ void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
 
     cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
                 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
-    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
+    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
+                PRIx64 "\n",
                 env->CP0_Config0, env->CP0_Config1, env->lladdr);
     cpu_fprintf(f, "    Config2 0x%08x Config3 0x%08x\n",
                 env->CP0_Config2, env->CP0_Config3);
@@ -19525,7 +19526,7 @@ void cpu_state_reset(CPUMIPSState *env)
     }
 #endif
     env->PABITS = env->cpu_model->PABITS;
-    env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
+    env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
     env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
     env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
     env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 1/7] target-mips: extend selected CP0 registers to 64-bits in MIPS32 Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  2015-04-28 13:35   ` James Hogan
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support Leon Alrae
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Update tlb->PFN to contain PFN concatenated with PFNX. PFNX is 0 if large
physical address is not supported.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/op_helper.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index c9a60bd..6bff927 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1825,6 +1825,16 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
     }
 }
 
+static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
+{
+#if defined(TARGET_MIPS64)
+    return extract64(entrylo, 6, 54);
+#else
+    return extract64(entrylo, 6, 24) | /* PFN */
+           (extract64(entrylo, 32, 32) << 24); /* PFNX */
+#endif
+}
+
 static void r4k_fill_tlb(CPUMIPSState *env, int idx)
 {
     r4k_tlb_t *tlb;
@@ -1848,13 +1858,13 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
     tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
     tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
     tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
-    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
+    tlb->PFN[0] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) << 12;
     tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
     tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
     tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
     tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
     tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
-    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
+    tlb->PFN[1] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) << 12;
 }
 
 void r4k_helper_tlbinv(CPUMIPSState *env)
@@ -1971,6 +1981,16 @@ void r4k_helper_tlbp(CPUMIPSState *env)
     }
 }
 
+static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
+{
+#if defined(TARGET_MIPS64)
+    return tlb_pfn << 6;
+#else
+    return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
+           (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
+#endif
+}
+
 void r4k_helper_tlbr(CPUMIPSState *env)
 {
     r4k_tlb_t *tlb;
@@ -1997,12 +2017,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
         env->CP0_PageMask = tlb->PageMask;
         env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
                         ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
-                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) |
-                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
+                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
+                        get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
         env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
                         ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
-                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) |
-                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
+                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
+                        get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
     }
 }
 

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 1/7] target-mips: extend selected CP0 registers to 64-bits in MIPS32 Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  2015-04-28 15:08   ` James Hogan
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions Leon Alrae
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

CP0.PageGrain.ELPA enables support for large physical addresses. This field
is encoded as follows:
0: Large physical address support is disabled.
1: Large physical address support is enabled.

If this bit is a 1, the following changes occur to coprocessor 0 registers:
- The PFNX field of the EntryLo0 and EntryLo1 registers is writable and
  concatenated with the PFN field to form the full page frame number.
- Access to optional COP0 registers with PA extension, LLAddr, TagLo is
  defined.

P5600 can operate in 32-bit or 40-bit Physical Address Mode. Therefore if
XPA is disabled (CP0.PageGrain.ELPA = 0) then assuming 32-bit Address Mode.
For MIPS64 default PABITS are 36.

env->PABITS value is constant and indicates maximum PABITS available on
a core, whereas env->PAMask is calculated from env->PABITS and is also
affected by CP0.PageGrain.ELPA.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       | 27 +++++++++++++++++++++++++--
 target-mips/machine.c   |  1 +
 target-mips/mips-defs.h |  4 ++--
 target-mips/op_helper.c | 24 +++++++++++++++++-------
 target-mips/translate.c |  3 ++-
 5 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 2dfa139..bcd1e2b 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -224,8 +224,14 @@ struct CPUMIPSState {
 
     uint32_t SEGBITS;
     uint32_t PABITS;
+#if defined(TARGET_MIPS64)
+# define DEFAULT_PABITS 36
+#else
+# define DEFAULT_PABITS 32
+#endif
     target_ulong SEGMask;
     uint64_t PAMask;
+#define DEFAULT_PAMASK ((1ULL << DEFAULT_PABITS) - 1)
 
     int32_t msair;
 #define MSAIR_ProcID    8
@@ -289,6 +295,7 @@ struct CPUMIPSState {
     int32_t CP0_PageGrain;
 #define CP0PG_RIE 31
 #define CP0PG_XIE 30
+#define CP0PG_ELPA 29
 #define CP0PG_IEC 27
     int32_t CP0_Wired;
     int32_t CP0_SRSConf0_rw_bitmask;
@@ -517,7 +524,7 @@ struct CPUMIPSState {
 #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK  0x35807FF
+#define MIPS_HFLAG_TMASK  0x75807FF
 #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
     /* The KSU flags must be the lowest bits in hflags. The flag order
        must be the same as defined for CP0 Status. This allows to use
@@ -565,6 +572,7 @@ struct CPUMIPSState {
 #define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot                   */
 #define MIPS_HFLAG_MSA   0x1000000
 #define MIPS_HFLAG_FRE   0x2000000 /* FRE enabled */
+#define MIPS_HFLAG_ELPA  0x4000000
     target_ulong btarget;        /* Jump / branch target               */
     target_ulong bcond;          /* Branch condition (if needed)       */
 
@@ -800,6 +808,15 @@ static inline void restore_msa_fp_status(CPUMIPSState *env)
     set_flush_inputs_to_zero(flush_to_zero, status);
 }
 
+static inline void restore_pamask(CPUMIPSState *env)
+{
+    if (env->hflags & MIPS_HFLAG_ELPA) {
+        env->PAMask = (1ULL << env->PABITS) - 1;
+    } else {
+        env->PAMask = DEFAULT_PAMASK;
+    }
+}
+
 static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
@@ -847,7 +864,8 @@ static inline void compute_hflags(CPUMIPSState *env)
     env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
                      MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
                      MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
-                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
+                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
+                     MIPS_HFLAG_ELPA);
     if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
         !(env->CP0_Status & (1 << CP0St_ERL)) &&
         !(env->hflags & MIPS_HFLAG_DM)) {
@@ -933,6 +951,11 @@ static inline void compute_hflags(CPUMIPSState *env)
             env->hflags |= MIPS_HFLAG_FRE;
         }
     }
+    if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
+        if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
+            env->hflags |= MIPS_HFLAG_ELPA;
+        }
+    }
 }
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 559402c..8fa755c 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -10,6 +10,7 @@ static int cpu_post_load(void *opaque, int version_id)
     restore_fp_status(env);
     restore_msa_fp_status(env);
     compute_hflags(env);
+    restore_pamask(env);
 
     return 0;
 }
diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index 1784227..20aa87c 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -10,11 +10,11 @@
 
 #if defined(TARGET_MIPS64)
 #define TARGET_LONG_BITS 64
-#define TARGET_PHYS_ADDR_SPACE_BITS 36
+#define TARGET_PHYS_ADDR_SPACE_BITS 48
 #define TARGET_VIRT_ADDR_SPACE_BITS 42
 #else
 #define TARGET_LONG_BITS 32
-#define TARGET_PHYS_ADDR_SPACE_BITS 36
+#define TARGET_PHYS_ADDR_SPACE_BITS 40
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 #endif
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 6bff927..4b1b0ec 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1067,19 +1067,28 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
     env->CP0_VPEOpt = arg1 & 0x0000ffff;
 }
 
+static inline target_ulong get_mtc0_entrylo_mask(const CPUMIPSState *env)
+{
+#if defined(TARGET_MIPS64)
+    return env->PAMask >> 6;
+#else
+    return (env->PAMask >> 6) & 0x3FFFFFFF;
+#endif
+}
+
 void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
 {
-    /* Large physaddr (PABITS) not implemented */
     /* 1k pages not implemented */
     target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
-    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
+    env->CP0_EntryLo0 = (arg1 & get_mtc0_entrylo_mask(env))
+                        | (rxi << (CP0EnLo_XI - 30));
 }
 
 #if defined(TARGET_MIPS64)
 void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
 {
     uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
-    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
+    env->CP0_EntryLo0 = (arg1 & get_mtc0_entrylo_mask(env)) | rxi;
 }
 #endif
 
@@ -1245,17 +1254,17 @@ void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
 
 void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
 {
-    /* Large physaddr (PABITS) not implemented */
     /* 1k pages not implemented */
     target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
-    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
+    env->CP0_EntryLo1 = (arg1 & get_mtc0_entrylo_mask(env))
+                        | (rxi << (CP0EnLo_XI - 30));
 }
 
 #if defined(TARGET_MIPS64)
 void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
 {
     uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
-    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
+    env->CP0_EntryLo1 = (arg1 & get_mtc0_entrylo_mask(env)) | rxi;
 }
 #endif
 
@@ -1278,10 +1287,11 @@ void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
 void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
 {
     /* SmartMIPS not implemented */
-    /* Large physaddr (PABITS) not implemented */
     /* 1k pages not implemented */
     env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
                          (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
+    compute_hflags(env);
+    restore_pamask(env);
 }
 
 void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0f875be..bb219ea 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -5666,6 +5666,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             check_insn(ctx, ISA_MIPS32R2);
             gen_helper_mtc0_pagegrain(cpu_env, arg);
             rn = "PageGrain";
+            ctx->bstate = BS_STOP;
             break;
         default:
             goto cp0_unimplemented;
@@ -19526,7 +19527,6 @@ void cpu_state_reset(CPUMIPSState *env)
     }
 #endif
     env->PABITS = env->cpu_model->PABITS;
-    env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
     env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
     env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
     env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
@@ -19647,6 +19647,7 @@ void cpu_state_reset(CPUMIPSState *env)
     compute_hflags(env);
     restore_rounding_mode(env);
     restore_flush_mode(env);
+    restore_pamask(env);
     cs->exception_index = EXCP_NONE;
 }
 

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
                   ` (2 preceding siblings ...)
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  2015-04-28 15:52   ` James Hogan
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 5/7] target-mips: correct MFC0 for CP0.EntryLo in MIPS64 Leon Alrae
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Implement MTHC0 and MFHC0 instructions. In MIPS32 they allow to access
upper word of extended to 64-bits CP0 registers.

In MIPS64, when CP0 destination register specified is the EntryLo0 or
EntryLo1, bits 1:0 of the GPR appear at bits 31:30 of EntryLo0 or
EntryLo1. This is to compensate for RI and XI, which were shifted to bits
63:62 by MTC0 to EntryLo0 or EntryLo1. Therefore creating separate
functions generating for EntryLo0 and EntryLo1.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 disas/mips.c            |   2 +
 target-mips/cpu.h       |   1 +
 target-mips/translate.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+)

diff --git a/disas/mips.c b/disas/mips.c
index 1afe0c5..c236495 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -2238,6 +2238,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"ceil.l.s", "D,S",	0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I3|I33	},
 {"ceil.w.d", "D,S",	0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I2	},
 {"ceil.w.s", "D,S",	0x4600000e, 0xffff003f, WR_D|RD_S|FP_S,		0,		I2	},
+{"mfhc0",   "t,G,H",    0x40400000, 0xffe007f8, LCD|WR_t|RD_C0,        0, I33 },
+{"mthc0",   "t,G,H",    0x40c00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC,  0, I33 },
 {"cfc0",    "t,G",	0x40400000, 0xffe007ff,	LCD|WR_t|RD_C0,		0,		I1	},
 {"cfc1",    "t,G",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
 {"cfc1",    "t,S",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index bcd1e2b..cfc6ac7 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -473,6 +473,7 @@ struct CPUMIPSState {
 #define CP0C5_UFE        9
 #define CP0C5_FRE        8
 #define CP0C5_SBRI       6
+#define CP0C5_MVH        5
 #define CP0C5_UFR        2
 #define CP0C5_NFExists   0
     int32_t CP0_Config6;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index bb219ea..f95b655 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -868,8 +868,10 @@ enum {
 enum {
     OPC_MFC0     = (0x00 << 21) | OPC_CP0,
     OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
+    OPC_MFHC0    = (0x02 << 21) | OPC_CP0,
     OPC_MTC0     = (0x04 << 21) | OPC_CP0,
     OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
+    OPC_MTHC0    = (0x06 << 21) | OPC_CP0,
     OPC_MFTR     = (0x08 << 21) | OPC_CP0,
     OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
     OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
@@ -1423,6 +1425,8 @@ typedef struct DisasContext {
     int ie;
     bool bi;
     bool bp;
+    uint64_t PAMask;
+    bool mvh;
 } DisasContext;
 
 enum {
@@ -1769,6 +1773,13 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
    This is enabled by CP0 Status register MX(24) bit.
  */
 
+static inline void check_mvh(DisasContext *ctx)
+{
+    if (unlikely(!(ctx->mvh))) {
+        generate_exception(ctx, EXCP_RI);
+    }
+}
+
 static inline void check_dsp(DisasContext *ctx)
 {
     if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
@@ -4820,6 +4831,60 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
 
 #ifndef CONFIG_USER_ONLY
 /* CP0 (MMU and control) */
+static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t0, arg);
+    tcg_gen_ld_i64(t1, cpu_env, off);
+#if defined(TARGET_MIPS64)
+    tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
+#else
+    tcg_gen_concat32_i64(t1, t1, t0);
+#endif
+    tcg_gen_st_i64(t1, cpu_env, off);
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t0);
+}
+
+static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+    TCGv_i64 t1 = tcg_temp_new_i64();
+
+    tcg_gen_ext_tl_i64(t0, arg);
+    tcg_gen_ld_i64(t1, cpu_env, off);
+    tcg_gen_concat32_i64(t1, t1, t0);
+    tcg_gen_st_i64(t1, cpu_env, off);
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t0);
+}
+
+static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+
+    tcg_gen_ld_i64(t0, cpu_env, off);
+#if defined(TARGET_MIPS64)
+    tcg_gen_shri_i64(t0, t0, 30);
+#else
+    tcg_gen_shri_i64(t0, t0, 32);
+#endif
+    tcg_gen_trunc_i64_tl(arg, t0);
+    tcg_temp_free_i64(t0);
+}
+
+static inline void gen_mfhc0_load64(TCGv arg, target_ulong off)
+{
+    TCGv_i64 t0 = tcg_temp_new_i64();
+
+    tcg_gen_ld_i64(t0, cpu_env, off);
+    tcg_gen_shri_i64(t0, t0, 32);
+    tcg_gen_trunc_i64_tl(arg, t0);
+    tcg_temp_free_i64(t0);
+}
+
 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
@@ -4850,6 +4915,134 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
     tcg_gen_st_tl(arg, cpu_env, off);
 }
 
+static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
+{
+    const char *rn = "invalid";
+
+    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
+        goto mfhc0_read_zero;
+    }
+
+    switch (reg) {
+    case 2:
+        switch (sel) {
+        case 0:
+            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
+            rn = "EntryLo0";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
+            rn = "EntryLo1";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr));
+            rn = "LLAddr";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo));
+            rn = "TagLo";
+            break;
+        default:
+            goto mfhc0_read_zero;
+        }
+        break;
+    default:
+        goto mfhc0_read_zero;
+    }
+
+    (void)rn; /* avoid a compiler warning */
+    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
+    return;
+
+mfhc0_read_zero:
+    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
+    tcg_gen_movi_tl(arg, 0);
+}
+
+static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
+{
+    const char *rn = "invalid";
+
+    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
+        goto mthc0_nop;
+    }
+
+    tcg_gen_andi_tl(arg, arg, ctx->PAMask >> 36);
+
+    switch (reg) {
+    case 2:
+        switch (sel) {
+        case 0:
+            gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
+            rn = "EntryLo0";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+            gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
+            rn = "EntryLo1";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+            gen_mthc0_store64(arg, offsetof(CPUMIPSState, lladdr));
+            rn = "LLAddr";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
+            rn = "TagLo";
+            break;
+        default:
+            goto mthc0_nop;
+        }
+        break;
+    default:
+        goto mthc0_nop;
+    }
+
+    (void)rn; /* avoid a compiler warning */
+mthc0_nop:
+    LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
+}
+
 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
 {
     if (ctx->insn_flags & ISA_MIPS32R6) {
@@ -7847,6 +8040,25 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
         opn = "dmtc0";
         break;
 #endif
+    case OPC_MFHC0:
+        check_mvh(ctx);
+        if (rt == 0) {
+            /* Treat as NOP. */
+            return;
+        }
+        gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
+        opn = "mfhc0";
+        break;
+    case OPC_MTHC0:
+        check_mvh(ctx);
+        {
+            TCGv t0 = tcg_temp_new();
+            gen_load_gpr(t0, rt);
+            gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
+            tcg_temp_free(t0);
+        }
+        opn = "mthc0";
+        break;
     case OPC_MFTR:
         check_insn(ctx, ASE_MT);
         if (rd == 0) {
@@ -18571,6 +18783,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
         case OPC_MTC0:
         case OPC_MFTR:
         case OPC_MTTR:
+        case OPC_MFHC0:
+        case OPC_MTHC0:
 #if defined(TARGET_MIPS64)
         case OPC_DMFC0:
         case OPC_DMTC0:
@@ -19141,6 +19355,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
     ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
     ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
     ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
+    ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
+    ctx.PAMask = env->PAMask;
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 5/7] target-mips: correct MFC0 for CP0.EntryLo in MIPS64
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
                   ` (3 preceding siblings ...)
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c Leon Alrae
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 7/7] target-mips: enable XPA and LPA features Leon Alrae
  6 siblings, 0 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Since PFNX is now supported the bits 31:30 have to be cleared.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/translate.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index f95b655..a41fc98 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -5144,10 +5144,10 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
 #if defined(TARGET_MIPS64)
             if (ctx->rxi) {
+                /* Move RI/XI fields to bits 31:30 */
                 TCGv tmp = tcg_temp_new();
-                tcg_gen_andi_tl(tmp, arg, (3ull << CP0EnLo_XI));
-                tcg_gen_shri_tl(tmp, tmp, 32);
-                tcg_gen_or_tl(arg, arg, tmp);
+                tcg_gen_shri_tl(tmp, arg, CP0EnLo_XI);
+                tcg_gen_deposit_tl(arg, arg, tmp, 30, 2);
                 tcg_temp_free(tmp);
             }
 #endif
@@ -5199,10 +5199,10 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
 #if defined(TARGET_MIPS64)
             if (ctx->rxi) {
+                /* Move RI/XI fields to bits 31:30 */
                 TCGv tmp = tcg_temp_new();
-                tcg_gen_andi_tl(tmp, arg, (3ull << CP0EnLo_XI));
-                tcg_gen_shri_tl(tmp, tmp, 32);
-                tcg_gen_or_tl(arg, arg, tmp);
+                tcg_gen_shri_tl(tmp, arg, CP0EnLo_XI);
+                tcg_gen_deposit_tl(arg, arg, tmp, 30, 2);
                 tcg_temp_free(tmp);
             }
 #endif

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
                   ` (4 preceding siblings ...)
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 5/7] target-mips: correct MFC0 for CP0.EntryLo in MIPS64 Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  2015-04-28 21:50   ` James Hogan
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 7/7] target-mips: enable XPA and LPA features Leon Alrae
  6 siblings, 1 reply; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/translate_init.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 8e088c9..af6fb7a 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -553,9 +553,6 @@ static const mips_def_t mips_defs[] =
                     (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
                     (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 42,
-        /* The architectural limit is 59, but we have hardcoded 36 bit
-           in some places...
-        .PABITS = 59, */ /* the architectural limit */
         .PABITS = 36,
         .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
         .mmu_type = MMU_TYPE_R4000,
@@ -636,9 +633,6 @@ static const mips_def_t mips_defs[] =
                     (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 42,
-        /* The architectural limit is 59, but we have hardcoded 36 bit
-           in some places...
-        .PABITS = 59, */ /* the architectural limit */
         .PABITS = 36,
         .insn_flags = CPU_MIPS64R6,
         .mmu_type = MMU_TYPE_R4000,
@@ -702,9 +696,6 @@ static const mips_def_t mips_defs[] =
                     (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
                     (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 42,
-        /* The architectural limit is 59, but we have hardcoded 36 bit
-           in some places...
-        .PABITS = 59, */ /* the architectural limit */
         .PABITS = 36,
         .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
         .mmu_type = MMU_TYPE_R4000,

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 7/7] target-mips: enable XPA and LPA features
  2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
                   ` (5 preceding siblings ...)
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c Leon Alrae
@ 2015-04-28 12:41 ` Leon Alrae
  6 siblings, 0 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 12:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien

Enable XPA in MIPS32R5-generic and LPA in MIPS64R6-generic.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 target-mips/translate_init.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index af6fb7a..8674118 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -400,10 +400,11 @@ static const mips_def_t mips_defs[] =
                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
                        (1 << CP0C1_CA),
         .CP0_Config2 = MIPS_CONFIG2,
-        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP),
+        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
+                       (1 << CP0C3_LPA),
         .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M),
         .CP0_Config4_rw_bitmask = 0,
-        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR),
+        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR) | (1 << CP0C5_MVH),
         .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) |
                                   (1 << CP0C5_CV) | (0 << CP0C5_EVA) |
                                   (1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) |
@@ -413,11 +414,12 @@ static const mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x3778FF1F,
+        .CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA),
         .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) |
                     (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x93 << FCR0_PRID),
         .SEGBITS = 32,
-        .PABITS = 32,
+        .PABITS = 40,
         .insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_MSA,
         .mmu_type = MMU_TYPE_R4000,
     },
@@ -616,7 +618,8 @@ static const mips_def_t mips_defs[] =
                        (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
         .CP0_Config2 = MIPS_CONFIG2,
         .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
-                       (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
+                       (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1 << CP0C3_LPA) |
+                       (1U << CP0C3_M),
         .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
                        (3 << CP0C4_IE) | (1 << CP0C4_M),
         .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
@@ -628,12 +631,12 @@ static const mips_def_t mips_defs[] =
         .CP0_Status_rw_bitmask = 0x30D8FFFF,
         .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
                          (1U << CP0PG_RIE),
-        .CP0_PageGrain_rw_bitmask = 0,
+        .CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA),
         .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) |
                     (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 42,
-        .PABITS = 36,
+        .PABITS = 48,
         .insn_flags = CPU_MIPS64R6,
         .mmu_type = MMU_TYPE_R4000,
     },

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field Leon Alrae
@ 2015-04-28 13:35   ` James Hogan
  2015-04-28 13:47     ` James Hogan
  2015-04-28 15:59     ` Leon Alrae
  0 siblings, 2 replies; 18+ messages in thread
From: James Hogan @ 2015-04-28 13:35 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

[-- Attachment #1: Type: text/plain, Size: 3677 bytes --]



On 28/04/15 13:41, Leon Alrae wrote:
> Update tlb->PFN to contain PFN concatenated with PFNX. PFNX is 0 if large
> physical address is not supported.
> 
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  target-mips/op_helper.c | 32 ++++++++++++++++++++++++++------
>  1 file changed, 26 insertions(+), 6 deletions(-)
> 
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index c9a60bd..6bff927 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1825,6 +1825,16 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
>      }
>  }
>  
> +static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
> +{
> +#if defined(TARGET_MIPS64)
> +    return extract64(entrylo, 6, 54);
> +#else
> +    return extract64(entrylo, 6, 24) | /* PFN */
> +           (extract64(entrylo, 32, 32) << 24); /* PFNX */

Where does the 32,32 come from? The PRA I have seems to imply that PFNX
starts at bit 30 and goes up to bit 54.

That would of course also mean that the code for mfc0 EntryLo* needs
tweaking so that PFNX doesn't cause XI/RI bits to be set at bits 30,31
(haven't looked at other patches yet).

> +#endif
> +}
> +
>  static void r4k_fill_tlb(CPUMIPSState *env, int idx)
>  {
>      r4k_tlb_t *tlb;
> @@ -1848,13 +1858,13 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
>      tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
>      tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
>      tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
> -    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
> +    tlb->PFN[0] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) << 12;
>      tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
>      tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
>      tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
>      tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
>      tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
> -    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
> +    tlb->PFN[1] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) << 12;
>  }
>  
>  void r4k_helper_tlbinv(CPUMIPSState *env)
> @@ -1971,6 +1981,16 @@ void r4k_helper_tlbp(CPUMIPSState *env)
>      }
>  }
>  
> +static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
> +{
> +#if defined(TARGET_MIPS64)
> +    return tlb_pfn << 6;
> +#else
> +    return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
> +           (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */

same again. shouldn't it be 25 bits starting at bit 24, shifted to start
at bit 30?

Cheers
James

> +#endif
> +}
> +
>  void r4k_helper_tlbr(CPUMIPSState *env)
>  {
>      r4k_tlb_t *tlb;
> @@ -1997,12 +2017,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
>          env->CP0_PageMask = tlb->PageMask;
>          env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
>                          ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
> -                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) |
> -                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
> +                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
> +                        get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
>          env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
>                          ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
> -                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) |
> -                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
> +                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
> +                        get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
>      }
>  }
>  
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field
  2015-04-28 13:35   ` James Hogan
@ 2015-04-28 13:47     ` James Hogan
  2015-04-28 15:59     ` Leon Alrae
  1 sibling, 0 replies; 18+ messages in thread
From: James Hogan @ 2015-04-28 13:47 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

[-- Attachment #1: Type: text/plain, Size: 4239 bytes --]

On 28/04/15 14:35, James Hogan wrote:
> 
> 
> On 28/04/15 13:41, Leon Alrae wrote:
>> Update tlb->PFN to contain PFN concatenated with PFNX. PFNX is 0 if large
>> physical address is not supported.
>>
>> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
>> ---
>>  target-mips/op_helper.c | 32 ++++++++++++++++++++++++++------
>>  1 file changed, 26 insertions(+), 6 deletions(-)
>>
>> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
>> index c9a60bd..6bff927 100644
>> --- a/target-mips/op_helper.c
>> +++ b/target-mips/op_helper.c
>> @@ -1825,6 +1825,16 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
>>      }
>>  }
>>  
>> +static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
>> +{
>> +#if defined(TARGET_MIPS64)
>> +    return extract64(entrylo, 6, 54);
>> +#else
>> +    return extract64(entrylo, 6, 24) | /* PFN */
>> +           (extract64(entrylo, 32, 32) << 24); /* PFNX */
> 
> Where does the 32,32 come from? The PRA I have seems to imply that PFNX
> starts at bit 30 and goes up to bit 54.

Ah right, I guess this is from the output of MFHC0/MTHC0 instructions.
The specification of those instructions specify the mangling they do:

GPR[rt]_31:0 <- data_61..30
GPR[rt]_63..32 <- (data_61)^31 // sign-extend

Note how the field it extracts starts at bit 30. IMO the stored values
of EntryLo PFN should be continuous rather than split up like the
MFHC0/MTHC0 versions.

Cheers
James

> 
> That would of course also mean that the code for mfc0 EntryLo* needs
> tweaking so that PFNX doesn't cause XI/RI bits to be set at bits 30,31
> (haven't looked at other patches yet).
> 
>> +#endif
>> +}
>> +
>>  static void r4k_fill_tlb(CPUMIPSState *env, int idx)
>>  {
>>      r4k_tlb_t *tlb;
>> @@ -1848,13 +1858,13 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
>>      tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
>>      tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
>>      tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
>> -    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
>> +    tlb->PFN[0] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) << 12;
>>      tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
>>      tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
>>      tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
>>      tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
>>      tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
>> -    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
>> +    tlb->PFN[1] = get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) << 12;
>>  }
>>  
>>  void r4k_helper_tlbinv(CPUMIPSState *env)
>> @@ -1971,6 +1981,16 @@ void r4k_helper_tlbp(CPUMIPSState *env)
>>      }
>>  }
>>  
>> +static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
>> +{
>> +#if defined(TARGET_MIPS64)
>> +    return tlb_pfn << 6;
>> +#else
>> +    return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */
>> +           (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */
> 
> same again. shouldn't it be 25 bits starting at bit 24, shifted to start
> at bit 30?
> 
> Cheers
> James
> 
>> +#endif
>> +}
>> +
>>  void r4k_helper_tlbr(CPUMIPSState *env)
>>  {
>>      r4k_tlb_t *tlb;
>> @@ -1997,12 +2017,12 @@ void r4k_helper_tlbr(CPUMIPSState *env)
>>          env->CP0_PageMask = tlb->PageMask;
>>          env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
>>                          ((uint64_t)tlb->RI0 << CP0EnLo_RI) |
>> -                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) |
>> -                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
>> +                        ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) |
>> +                        get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12);
>>          env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
>>                          ((uint64_t)tlb->RI1 << CP0EnLo_RI) |
>> -                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) |
>> -                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
>> +                        ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) |
>> +                        get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12);
>>      }
>>  }
>>  
>>
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support Leon Alrae
@ 2015-04-28 15:08   ` James Hogan
  2015-04-29 11:35     ` Leon Alrae
  0 siblings, 1 reply; 18+ messages in thread
From: James Hogan @ 2015-04-28 15:08 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

[-- Attachment #1: Type: text/plain, Size: 9936 bytes --]

Hi Leon,

On 28/04/15 13:41, Leon Alrae wrote:
> CP0.PageGrain.ELPA enables support for large physical addresses. This field
> is encoded as follows:
> 0: Large physical address support is disabled.
> 1: Large physical address support is enabled.
> 
> If this bit is a 1, the following changes occur to coprocessor 0 registers:
> - The PFNX field of the EntryLo0 and EntryLo1 registers is writable and
>   concatenated with the PFN field to form the full page frame number.
> - Access to optional COP0 registers with PA extension, LLAddr, TagLo is
>   defined.
> 
> P5600 can operate in 32-bit or 40-bit Physical Address Mode. Therefore if
> XPA is disabled (CP0.PageGrain.ELPA = 0) then assuming 32-bit Address Mode.
> For MIPS64 default PABITS are 36.
> 
> env->PABITS value is constant and indicates maximum PABITS available on
> a core, whereas env->PAMask is calculated from env->PABITS and is also
> affected by CP0.PageGrain.ELPA.
> 
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  target-mips/cpu.h       | 27 +++++++++++++++++++++++++--
>  target-mips/machine.c   |  1 +
>  target-mips/mips-defs.h |  4 ++--
>  target-mips/op_helper.c | 24 +++++++++++++++++-------
>  target-mips/translate.c |  3 ++-
>  5 files changed, 47 insertions(+), 12 deletions(-)
> 
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 2dfa139..bcd1e2b 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -224,8 +224,14 @@ struct CPUMIPSState {
>  
>      uint32_t SEGBITS;
>      uint32_t PABITS;
> +#if defined(TARGET_MIPS64)
> +# define DEFAULT_PABITS 36
> +#else
> +# define DEFAULT_PABITS 32
> +#endif
>      target_ulong SEGMask;
>      uint64_t PAMask;
> +#define DEFAULT_PAMASK ((1ULL << DEFAULT_PABITS) - 1)
>  
>      int32_t msair;
>  #define MSAIR_ProcID    8
> @@ -289,6 +295,7 @@ struct CPUMIPSState {
>      int32_t CP0_PageGrain;
>  #define CP0PG_RIE 31
>  #define CP0PG_XIE 30
> +#define CP0PG_ELPA 29
>  #define CP0PG_IEC 27
>      int32_t CP0_Wired;
>      int32_t CP0_SRSConf0_rw_bitmask;
> @@ -517,7 +524,7 @@ struct CPUMIPSState {
>  #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
>      uint32_t hflags;    /* CPU State */
>      /* TMASK defines different execution modes */
> -#define MIPS_HFLAG_TMASK  0x35807FF
> +#define MIPS_HFLAG_TMASK  0x75807FF
>  #define MIPS_HFLAG_MODE   0x00007 /* execution modes                    */
>      /* The KSU flags must be the lowest bits in hflags. The flag order
>         must be the same as defined for CP0 Status. This allows to use
> @@ -565,6 +572,7 @@ struct CPUMIPSState {
>  #define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot                   */
>  #define MIPS_HFLAG_MSA   0x1000000
>  #define MIPS_HFLAG_FRE   0x2000000 /* FRE enabled */
> +#define MIPS_HFLAG_ELPA  0x4000000
>      target_ulong btarget;        /* Jump / branch target               */
>      target_ulong bcond;          /* Branch condition (if needed)       */
>  
> @@ -800,6 +808,15 @@ static inline void restore_msa_fp_status(CPUMIPSState *env)
>      set_flush_inputs_to_zero(flush_to_zero, status);
>  }
>  
> +static inline void restore_pamask(CPUMIPSState *env)
> +{
> +    if (env->hflags & MIPS_HFLAG_ELPA) {
> +        env->PAMask = (1ULL << env->PABITS) - 1;
> +    } else {
> +        env->PAMask = DEFAULT_PAMASK;
> +    }
> +}
> +
>  static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
>                                          target_ulong *cs_base, int *flags)
>  {
> @@ -847,7 +864,8 @@ static inline void compute_hflags(CPUMIPSState *env)
>      env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
>                       MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
>                       MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
> -                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
> +                     MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
> +                     MIPS_HFLAG_ELPA);
>      if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
>          !(env->CP0_Status & (1 << CP0St_ERL)) &&
>          !(env->hflags & MIPS_HFLAG_DM)) {
> @@ -933,6 +951,11 @@ static inline void compute_hflags(CPUMIPSState *env)
>              env->hflags |= MIPS_HFLAG_FRE;
>          }
>      }
> +    if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
> +        if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
> +            env->hflags |= MIPS_HFLAG_ELPA;
> +        }
> +    }
>  }
>  
>  #ifndef CONFIG_USER_ONLY
> diff --git a/target-mips/machine.c b/target-mips/machine.c
> index 559402c..8fa755c 100644
> --- a/target-mips/machine.c
> +++ b/target-mips/machine.c
> @@ -10,6 +10,7 @@ static int cpu_post_load(void *opaque, int version_id)
>      restore_fp_status(env);
>      restore_msa_fp_status(env);
>      compute_hflags(env);
> +    restore_pamask(env);
>  
>      return 0;
>  }
> diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
> index 1784227..20aa87c 100644
> --- a/target-mips/mips-defs.h
> +++ b/target-mips/mips-defs.h
> @@ -10,11 +10,11 @@
>  
>  #if defined(TARGET_MIPS64)
>  #define TARGET_LONG_BITS 64
> -#define TARGET_PHYS_ADDR_SPACE_BITS 36
> +#define TARGET_PHYS_ADDR_SPACE_BITS 48
>  #define TARGET_VIRT_ADDR_SPACE_BITS 42
>  #else
>  #define TARGET_LONG_BITS 32
> -#define TARGET_PHYS_ADDR_SPACE_BITS 36
> +#define TARGET_PHYS_ADDR_SPACE_BITS 40

Out of interest, is there a particular reason not to put this up to 59,
the max supported by the architecture, rather than just what P5600 supports?

>  #define TARGET_VIRT_ADDR_SPACE_BITS 32
>  #endif
>  
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 6bff927..4b1b0ec 100644
> --- a/target-mips/op_helper.c
> +++ b/target-mips/op_helper.c
> @@ -1067,19 +1067,28 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
>      env->CP0_VPEOpt = arg1 & 0x0000ffff;
>  }
>  
> +static inline target_ulong get_mtc0_entrylo_mask(const CPUMIPSState *env)
> +{
> +#if defined(TARGET_MIPS64)
> +    return env->PAMask >> 6;

I think this case is suitable for dmtc0 EntryLo regardless of MIPS64/MIPS32?

> +#else
> +    return (env->PAMask >> 6) & 0x3FFFFFFF;

mtc0 sets bits 61:30 of EntryLo to 0 on MIPS64 too, so this case is
suitable for mtc0 regardless of MIPS64/MIPS32?

Cheers
James

> +#endif
> +}
> +
>  void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
>  {
> -    /* Large physaddr (PABITS) not implemented */
>      /* 1k pages not implemented */
>      target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
> -    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
> +    env->CP0_EntryLo0 = (arg1 & get_mtc0_entrylo_mask(env))
> +                        | (rxi << (CP0EnLo_XI - 30));
>  }
>  
>  #if defined(TARGET_MIPS64)
>  void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
>  {
>      uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
> -    env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
> +    env->CP0_EntryLo0 = (arg1 & get_mtc0_entrylo_mask(env)) | rxi;
>  }
>  #endif
>  
> @@ -1245,17 +1254,17 @@ void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
>  
>  void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
>  {
> -    /* Large physaddr (PABITS) not implemented */
>      /* 1k pages not implemented */
>      target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
> -    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
> +    env->CP0_EntryLo1 = (arg1 & get_mtc0_entrylo_mask(env))
> +                        | (rxi << (CP0EnLo_XI - 30));
>  }
>  
>  #if defined(TARGET_MIPS64)
>  void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
>  {
>      uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
> -    env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
> +    env->CP0_EntryLo1 = (arg1 & get_mtc0_entrylo_mask(env)) | rxi;
>  }
>  #endif
>  
> @@ -1278,10 +1287,11 @@ void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
>  void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
>  {
>      /* SmartMIPS not implemented */
> -    /* Large physaddr (PABITS) not implemented */
>      /* 1k pages not implemented */
>      env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
>                           (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
> +    compute_hflags(env);
> +    restore_pamask(env);
>  }
>  
>  void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 0f875be..bb219ea 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -5666,6 +5666,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>              check_insn(ctx, ISA_MIPS32R2);
>              gen_helper_mtc0_pagegrain(cpu_env, arg);
>              rn = "PageGrain";
> +            ctx->bstate = BS_STOP;
>              break;
>          default:
>              goto cp0_unimplemented;
> @@ -19526,7 +19527,6 @@ void cpu_state_reset(CPUMIPSState *env)
>      }
>  #endif
>      env->PABITS = env->cpu_model->PABITS;
> -    env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
>      env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
>      env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
>      env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
> @@ -19647,6 +19647,7 @@ void cpu_state_reset(CPUMIPSState *env)
>      compute_hflags(env);
>      restore_rounding_mode(env);
>      restore_flush_mode(env);
> +    restore_pamask(env);
>      cs->exception_index = EXCP_NONE;
>  }
>  
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions Leon Alrae
@ 2015-04-28 15:52   ` James Hogan
  2015-04-29 14:26     ` Leon Alrae
  0 siblings, 1 reply; 18+ messages in thread
From: James Hogan @ 2015-04-28 15:52 UTC (permalink / raw)
  To: Leon Alrae, qemu-devel; +Cc: aurelien

[-- Attachment #1: Type: text/plain, Size: 11290 bytes --]

Hi Leon,

On 28/04/15 13:41, Leon Alrae wrote:
> Implement MTHC0 and MFHC0 instructions. In MIPS32 they allow to access
> upper word of extended to 64-bits CP0 registers.
> 
> In MIPS64, when CP0 destination register specified is the EntryLo0 or
> EntryLo1, bits 1:0 of the GPR appear at bits 31:30 of EntryLo0 or
> EntryLo1. This is to compensate for RI and XI, which were shifted to bits
> 63:62 by MTC0 to EntryLo0 or EntryLo1. Therefore creating separate
> functions generating for EntryLo0 and EntryLo1.
> 
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
>  disas/mips.c            |   2 +
>  target-mips/cpu.h       |   1 +
>  target-mips/translate.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 219 insertions(+)
> 
> diff --git a/disas/mips.c b/disas/mips.c
> index 1afe0c5..c236495 100644
> --- a/disas/mips.c
> +++ b/disas/mips.c
> @@ -2238,6 +2238,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
>  {"ceil.l.s", "D,S",	0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I3|I33	},
>  {"ceil.w.d", "D,S",	0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I2	},
>  {"ceil.w.s", "D,S",	0x4600000e, 0xffff003f, WR_D|RD_S|FP_S,		0,		I2	},
> +{"mfhc0",   "t,G,H",    0x40400000, 0xffe007f8, LCD|WR_t|RD_C0,        0, I33 },
> +{"mthc0",   "t,G,H",    0x40c00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC,  0, I33 },

whitespace appears to be inconsistent here (the context uses tabs).

>  {"cfc0",    "t,G",	0x40400000, 0xffe007ff,	LCD|WR_t|RD_C0,		0,		I1	},
>  {"cfc1",    "t,G",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
>  {"cfc1",    "t,S",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index bcd1e2b..cfc6ac7 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -473,6 +473,7 @@ struct CPUMIPSState {
>  #define CP0C5_UFE        9
>  #define CP0C5_FRE        8
>  #define CP0C5_SBRI       6
> +#define CP0C5_MVH        5
>  #define CP0C5_UFR        2
>  #define CP0C5_NFExists   0
>      int32_t CP0_Config6;
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index bb219ea..f95b655 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -868,8 +868,10 @@ enum {
>  enum {
>      OPC_MFC0     = (0x00 << 21) | OPC_CP0,
>      OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
> +    OPC_MFHC0    = (0x02 << 21) | OPC_CP0,
>      OPC_MTC0     = (0x04 << 21) | OPC_CP0,
>      OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
> +    OPC_MTHC0    = (0x06 << 21) | OPC_CP0,
>      OPC_MFTR     = (0x08 << 21) | OPC_CP0,
>      OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
>      OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
> @@ -1423,6 +1425,8 @@ typedef struct DisasContext {
>      int ie;
>      bool bi;
>      bool bp;
> +    uint64_t PAMask;
> +    bool mvh;
>  } DisasContext;
>  
>  enum {
> @@ -1769,6 +1773,13 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
>     This is enabled by CP0 Status register MX(24) bit.
>   */
>  
> +static inline void check_mvh(DisasContext *ctx)
> +{
> +    if (unlikely(!(ctx->mvh))) {

superfluous brackets around ctx->mvh.

> +        generate_exception(ctx, EXCP_RI);
> +    }
> +}
> +
>  static inline void check_dsp(DisasContext *ctx)
>  {
>      if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
> @@ -4820,6 +4831,60 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
>  
>  #ifndef CONFIG_USER_ONLY
>  /* CP0 (MMU and control) */
> +static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
> +{
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +    TCGv_i64 t1 = tcg_temp_new_i64();
> +
> +    tcg_gen_ext_tl_i64(t0, arg);
> +    tcg_gen_ld_i64(t1, cpu_env, off);
> +#if defined(TARGET_MIPS64)
> +    tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
> +#else
> +    tcg_gen_concat32_i64(t1, t1, t0);

I don't get what this case is about. what's wrong with the above case
for MIPS64 and MIPS32?

> +#endif
> +    tcg_gen_st_i64(t1, cpu_env, off);
> +    tcg_temp_free_i64(t1);
> +    tcg_temp_free_i64(t0);
> +}
> +
> +static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
> +{
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +    TCGv_i64 t1 = tcg_temp_new_i64();
> +
> +    tcg_gen_ext_tl_i64(t0, arg);
> +    tcg_gen_ld_i64(t1, cpu_env, off);
> +    tcg_gen_concat32_i64(t1, t1, t0);
> +    tcg_gen_st_i64(t1, cpu_env, off);
> +    tcg_temp_free_i64(t1);
> +    tcg_temp_free_i64(t0);

simpler to just store a 32-bit value (st32_tl) to the appropriate half,
depending on host endianness? (i.e. +4 if little endian)

> +}
> +
> +static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
> +{
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +
> +    tcg_gen_ld_i64(t0, cpu_env, off);
> +#if defined(TARGET_MIPS64)
> +    tcg_gen_shri_i64(t0, t0, 30);

need to mask off the xi/ri bits?

> +#else
> +    tcg_gen_shri_i64(t0, t0, 32);

Again, I'm not convinced MIPS32 needs special handling here.

> +#endif
> +    tcg_gen_trunc_i64_tl(arg, t0);
> +    tcg_temp_free_i64(t0);
> +}
> +
> +static inline void gen_mfhc0_load64(TCGv arg, target_ulong off)
> +{
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +
> +    tcg_gen_ld_i64(t0, cpu_env, off);
> +    tcg_gen_shri_i64(t0, t0, 32);

simpler to just load a signed 32-bit value (ld32s_tl) from the
appropriate half, depending on host endianness? (i.e. +4 if little endian)

> +    tcg_gen_trunc_i64_tl(arg, t0);
> +    tcg_temp_free_i64(t0);
> +}
> +
>  static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
>  {
>      TCGv_i32 t0 = tcg_temp_new_i32();
> @@ -4850,6 +4915,134 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
>      tcg_gen_st_tl(arg, cpu_env, off);
>  }
>  
> +static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
> +{
> +    const char *rn = "invalid";
> +
> +    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {

worth reusing the CP0_CHECK stuff?

> +        goto mfhc0_read_zero;
> +    }
> +
> +    switch (reg) {
> +    case 2:
> +        switch (sel) {
> +        case 0:
> +            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
> +            rn = "EntryLo0";
> +            break;
> +        default:
> +            goto mfhc0_read_zero;
> +        }
> +        break;
> +    case 3:
> +        switch (sel) {
> +        case 0:
> +            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
> +            rn = "EntryLo1";
> +            break;
> +        default:
> +            goto mfhc0_read_zero;
> +        }
> +        break;
> +    case 17:
> +        switch (sel) {
> +        case 0:
> +            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr));
> +            rn = "LLAddr";
> +            break;
> +        default:
> +            goto mfhc0_read_zero;
> +        }
> +        break;
> +    case 28:
> +        switch (sel) {
> +        case 0:
> +        case 2:
> +        case 4:
> +        case 6:
> +            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo));
> +            rn = "TagLo";
> +            break;
> +        default:
> +            goto mfhc0_read_zero;
> +        }
> +        break;
> +    default:
> +        goto mfhc0_read_zero;
> +    }
> +
> +    (void)rn; /* avoid a compiler warning */
> +    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
> +    return;
> +
> +mfhc0_read_zero:
> +    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
> +    tcg_gen_movi_tl(arg, 0);
> +}
> +
> +static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
> +{
> +    const char *rn = "invalid";
> +
> +    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
> +        goto mthc0_nop;
> +    }
> +
> +    tcg_gen_andi_tl(arg, arg, ctx->PAMask >> 36);

Shouldn't this depend on the register? LLAddr shift varies per core
(CP0_LLAddr_shift), but EntryLo shift will be the same for each core.

Cheers
James

> +
> +    switch (reg) {
> +    case 2:
> +        switch (sel) {
> +        case 0:
> +            gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
> +            rn = "EntryLo0";
> +            break;
> +        default:
> +            goto mthc0_nop;
> +        }
> +        break;
> +    case 3:
> +        switch (sel) {
> +        case 0:
> +            gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
> +            rn = "EntryLo1";
> +            break;
> +        default:
> +            goto mthc0_nop;
> +        }
> +        break;
> +    case 17:
> +        switch (sel) {
> +        case 0:
> +            gen_mthc0_store64(arg, offsetof(CPUMIPSState, lladdr));
> +            rn = "LLAddr";
> +            break;
> +        default:
> +            goto mthc0_nop;
> +        }
> +        break;
> +    case 28:
> +        switch (sel) {
> +        case 0:
> +        case 2:
> +        case 4:
> +        case 6:
> +            gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
> +            rn = "TagLo";
> +            break;
> +        default:
> +            goto mthc0_nop;
> +        }
> +        break;
> +    default:
> +        goto mthc0_nop;
> +    }
> +
> +    (void)rn; /* avoid a compiler warning */
> +mthc0_nop:
> +    LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
> +}
> +
>  static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
>  {
>      if (ctx->insn_flags & ISA_MIPS32R6) {
> @@ -7847,6 +8040,25 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
>          opn = "dmtc0";
>          break;
>  #endif
> +    case OPC_MFHC0:
> +        check_mvh(ctx);
> +        if (rt == 0) {
> +            /* Treat as NOP. */
> +            return;
> +        }
> +        gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
> +        opn = "mfhc0";
> +        break;
> +    case OPC_MTHC0:
> +        check_mvh(ctx);
> +        {
> +            TCGv t0 = tcg_temp_new();
> +            gen_load_gpr(t0, rt);
> +            gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
> +            tcg_temp_free(t0);
> +        }
> +        opn = "mthc0";
> +        break;
>      case OPC_MFTR:
>          check_insn(ctx, ASE_MT);
>          if (rd == 0) {
> @@ -18571,6 +18783,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
>          case OPC_MTC0:
>          case OPC_MFTR:
>          case OPC_MTTR:
> +        case OPC_MFHC0:
> +        case OPC_MTHC0:
>  #if defined(TARGET_MIPS64)
>          case OPC_DMFC0:
>          case OPC_DMTC0:
> @@ -19141,6 +19355,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>      ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
>      ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
>      ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
> +    ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
> +    ctx.PAMask = env->PAMask;
>      /* Restore delay slot state from the tb context.  */
>      ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
>      ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field
  2015-04-28 13:35   ` James Hogan
  2015-04-28 13:47     ` James Hogan
@ 2015-04-28 15:59     ` Leon Alrae
  2015-04-28 21:39       ` James Hogan
  1 sibling, 1 reply; 18+ messages in thread
From: Leon Alrae @ 2015-04-28 15:59 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: aurelien

Hi James,

On 28/04/2015 14:35, James Hogan wrote:
> 
> 
> On 28/04/15 13:41, Leon Alrae wrote:
>> Update tlb->PFN to contain PFN concatenated with PFNX. PFNX is 0 if large
>> physical address is not supported.
>>
>> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
>> ---
>>  target-mips/op_helper.c | 32 ++++++++++++++++++++++++++------
>>  1 file changed, 26 insertions(+), 6 deletions(-)
>>
>> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
>> index c9a60bd..6bff927 100644
>> --- a/target-mips/op_helper.c
>> +++ b/target-mips/op_helper.c
>> @@ -1825,6 +1825,16 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
>>      }
>>  }
>>  
>> +static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
>> +{
>> +#if defined(TARGET_MIPS64)
>> +    return extract64(entrylo, 6, 54);
>> +#else
>> +    return extract64(entrylo, 6, 24) | /* PFN */
>> +           (extract64(entrylo, 32, 32) << 24); /* PFNX */
> 
> Where does the 32,32 come from? The PRA I have seems to imply that PFNX
> starts at bit 30 and goes up to bit 54.

This comes directly from MIPS32 PRA (I presume you are looking at MIPS64
PRA). Note that EntryLo.PFNX starts at bit 32 as there is 2-bit gap
occupied by RI/XI (unlike MIPS64 where it starts at bit 30).

Regards,
Leon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field
  2015-04-28 15:59     ` Leon Alrae
@ 2015-04-28 21:39       ` James Hogan
  2015-04-29 15:31         ` Leon Alrae
  0 siblings, 1 reply; 18+ messages in thread
From: James Hogan @ 2015-04-28 21:39 UTC (permalink / raw)
  To: Leon Alrae; +Cc: qemu-devel, aurelien

[-- Attachment #1: Type: text/plain, Size: 2147 bytes --]

On Tue, Apr 28, 2015 at 04:59:20PM +0100, Leon Alrae wrote:
> Hi James,
> 
> On 28/04/2015 14:35, James Hogan wrote:
> > 
> > 
> > On 28/04/15 13:41, Leon Alrae wrote:
> >> Update tlb->PFN to contain PFN concatenated with PFNX. PFNX is 0 if large
> >> physical address is not supported.
> >>
> >> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> >> ---
> >>  target-mips/op_helper.c | 32 ++++++++++++++++++++++++++------
> >>  1 file changed, 26 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> >> index c9a60bd..6bff927 100644
> >> --- a/target-mips/op_helper.c
> >> +++ b/target-mips/op_helper.c
> >> @@ -1825,6 +1825,16 @@ static void r4k_mips_tlb_flush_extra (CPUMIPSState *env, int first)
> >>      }
> >>  }
> >>  
> >> +static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo)
> >> +{
> >> +#if defined(TARGET_MIPS64)
> >> +    return extract64(entrylo, 6, 54);
> >> +#else
> >> +    return extract64(entrylo, 6, 24) | /* PFN */
> >> +           (extract64(entrylo, 32, 32) << 24); /* PFNX */
> > 
> > Where does the 32,32 come from? The PRA I have seems to imply that PFNX
> > starts at bit 30 and goes up to bit 54.
> 
> This comes directly from MIPS32 PRA (I presume you are looking at MIPS64
> PRA).

Right, the MIPS32 64-bit representation is the same as what mfc0 and
mfhc0 would give you, and I see that the raw EntryLo representation in
QEMU already has XI/RI in different places depending on MIPS64/MIPS32,
i.e. following how each PRA represents the raw state differently.

I think I wasn't expecting that because 32-bit kernels can run on MIPS64
hardware using the same mfc0/mfhc0 instructions, so having a single
internal representation in QEMU seemed simpler & less fragile, since the
same source code needs to support both MIPS32 and MIPS64 anyway.

> Note that EntryLo.PFNX starts at bit 32 as there is 2-bit gap
> occupied by RI/XI (unlike MIPS64 where it starts at bit 30).

Well, from a programmer point of view mfc0 and mfhc0 with EntryLo behave
identically on both MIPS32 and MIPS64.

Thanks
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c
  2015-04-28 12:41 ` [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c Leon Alrae
@ 2015-04-28 21:50   ` James Hogan
  0 siblings, 0 replies; 18+ messages in thread
From: James Hogan @ 2015-04-28 21:50 UTC (permalink / raw)
  To: Leon Alrae; +Cc: qemu-devel, aurelien

[-- Attachment #1: Type: text/plain, Size: 2074 bytes --]

On Tue, Apr 28, 2015 at 01:41:13PM +0100, Leon Alrae wrote:
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>

I think this deserves a bit more explanation. Isn't 59 bits still the
true architectural limit?

Cheers
James
> ---
>  target-mips/translate_init.c | 9 ---------
>  1 file changed, 9 deletions(-)
> 
> diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
> index 8e088c9..af6fb7a 100644
> --- a/target-mips/translate_init.c
> +++ b/target-mips/translate_init.c
> @@ -553,9 +553,6 @@ static const mips_def_t mips_defs[] =
>                      (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
>                      (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
>          .SEGBITS = 42,
> -        /* The architectural limit is 59, but we have hardcoded 36 bit
> -           in some places...
> -        .PABITS = 59, */ /* the architectural limit */
>          .PABITS = 36,
>          .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
>          .mmu_type = MMU_TYPE_R4000,
> @@ -636,9 +633,6 @@ static const mips_def_t mips_defs[] =
>                      (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
>                      (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
>          .SEGBITS = 42,
> -        /* The architectural limit is 59, but we have hardcoded 36 bit
> -           in some places...
> -        .PABITS = 59, */ /* the architectural limit */
>          .PABITS = 36,
>          .insn_flags = CPU_MIPS64R6,
>          .mmu_type = MMU_TYPE_R4000,
> @@ -702,9 +696,6 @@ static const mips_def_t mips_defs[] =
>                      (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
>                      (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
>          .SEGBITS = 42,
> -        /* The architectural limit is 59, but we have hardcoded 36 bit
> -           in some places...
> -        .PABITS = 59, */ /* the architectural limit */
>          .PABITS = 36,
>          .insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
>          .mmu_type = MMU_TYPE_R4000,
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support
  2015-04-28 15:08   ` James Hogan
@ 2015-04-29 11:35     ` Leon Alrae
  0 siblings, 0 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-29 11:35 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: aurelien

Hi James,

On 28/04/2015 16:08, James Hogan wrote:
>> diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
>> index 1784227..20aa87c 100644
>> --- a/target-mips/mips-defs.h
>> +++ b/target-mips/mips-defs.h
>> @@ -10,11 +10,11 @@
>>  
>>  #if defined(TARGET_MIPS64)
>>  #define TARGET_LONG_BITS 64
>> -#define TARGET_PHYS_ADDR_SPACE_BITS 36
>> +#define TARGET_PHYS_ADDR_SPACE_BITS 48
>>  #define TARGET_VIRT_ADDR_SPACE_BITS 42
>>  #else
>>  #define TARGET_LONG_BITS 32
>> -#define TARGET_PHYS_ADDR_SPACE_BITS 36
>> +#define TARGET_PHYS_ADDR_SPACE_BITS 40
> 
> Out of interest, is there a particular reason not to put this up to 59,
> the max supported by the architecture, rather than just what P5600 supports?

More bits we declare then more levels of page tables QEMU will have,
which means more time spent on page walking. Therefore I don't think
it's a good idea to put the architectural limit if we don't have to.

>>  #define TARGET_VIRT_ADDR_SPACE_BITS 32
>>  #endif
>>  
>> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
>> index 6bff927..4b1b0ec 100644
>> --- a/target-mips/op_helper.c
>> +++ b/target-mips/op_helper.c
>> @@ -1067,19 +1067,28 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
>>      env->CP0_VPEOpt = arg1 & 0x0000ffff;
>>  }
>>  
>> +static inline target_ulong get_mtc0_entrylo_mask(const CPUMIPSState *env)
>> +{
>> +#if defined(TARGET_MIPS64)
>> +    return env->PAMask >> 6;
> 
> I think this case is suitable for dmtc0 EntryLo regardless of MIPS64/MIPS32?
> 
>> +#else
>> +    return (env->PAMask >> 6) & 0x3FFFFFFF;
> 
> mtc0 sets bits 61:30 of EntryLo to 0 on MIPS64 too, so this case is
> suitable for mtc0 regardless of MIPS64/MIPS32?

I must have assumed here that mtc0 and dmtc0 do the same thing in MIPS64
(apart from having RI/XI bits in different places). I'll fix it, thanks.

Leon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions
  2015-04-28 15:52   ` James Hogan
@ 2015-04-29 14:26     ` Leon Alrae
  0 siblings, 0 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-29 14:26 UTC (permalink / raw)
  To: James Hogan, qemu-devel; +Cc: aurelien

On 28/04/2015 16:52, James Hogan wrote:
>> diff --git a/disas/mips.c b/disas/mips.c
>> index 1afe0c5..c236495 100644
>> --- a/disas/mips.c
>> +++ b/disas/mips.c
>> @@ -2238,6 +2238,8 @@ const struct mips_opcode mips_builtin_opcodes[] =
>>  {"ceil.l.s", "D,S",	0x4600000a, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I3|I33	},
>>  {"ceil.w.d", "D,S",	0x4620000e, 0xffff003f, WR_D|RD_S|FP_S|FP_D,	0,		I2	},
>>  {"ceil.w.s", "D,S",	0x4600000e, 0xffff003f, WR_D|RD_S|FP_S,		0,		I2	},
>> +{"mfhc0",   "t,G,H",    0x40400000, 0xffe007f8, LCD|WR_t|RD_C0,        0, I33 },
>> +{"mthc0",   "t,G,H",    0x40c00000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC,  0, I33 },
> 
> whitespace appears to be inconsistent here (the context uses tabs).

According to QEMU Coding Style we never use tabs, so we cannot avoid
this inconsistency unless we modify all entries in the table.

> 
>>  {"cfc0",    "t,G",	0x40400000, 0xffe007ff,	LCD|WR_t|RD_C0,		0,		I1	},
>>  {"cfc1",    "t,G",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
>>  {"cfc1",    "t,S",	0x44400000, 0xffe007ff,	LCD|WR_t|RD_C1|FP_S,	0,		I1	},
>> diff --git a/target-mips/translate.c b/target-mips/translate.c
>> index bb219ea..f95b655 100644
>> --- a/target-mips/translate.c
>> +++ b/target-mips/translate.c
>> @@ -868,8 +868,10 @@ enum {
>>  enum {
>>      OPC_MFC0     = (0x00 << 21) | OPC_CP0,
>>      OPC_DMFC0    = (0x01 << 21) | OPC_CP0,
>> +    OPC_MFHC0    = (0x02 << 21) | OPC_CP0,
>>      OPC_MTC0     = (0x04 << 21) | OPC_CP0,
>>      OPC_DMTC0    = (0x05 << 21) | OPC_CP0,
>> +    OPC_MTHC0    = (0x06 << 21) | OPC_CP0,
>>      OPC_MFTR     = (0x08 << 21) | OPC_CP0,
>>      OPC_RDPGPR   = (0x0A << 21) | OPC_CP0,
>>      OPC_MFMC0    = (0x0B << 21) | OPC_CP0,
>> @@ -1423,6 +1425,8 @@ typedef struct DisasContext {
>>      int ie;
>>      bool bi;
>>      bool bp;
>> +    uint64_t PAMask;
>> +    bool mvh;
>>  } DisasContext;
>>  
>>  enum {
>> @@ -1769,6 +1773,13 @@ static inline void check_cp1_registers(DisasContext *ctx, int regs)
>>     This is enabled by CP0 Status register MX(24) bit.
>>   */
>>  
>> +static inline void check_mvh(DisasContext *ctx)
>> +{
>> +    if (unlikely(!(ctx->mvh))) {
> 
> superfluous brackets around ctx->mvh.

Will remove.

> 
>> +        generate_exception(ctx, EXCP_RI);
>> +    }
>> +}
>> +
>>  static inline void check_dsp(DisasContext *ctx)
>>  {
>>      if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
>> @@ -4820,6 +4831,60 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
>>  
>>  #ifndef CONFIG_USER_ONLY
>>  /* CP0 (MMU and control) */
>> +static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
>> +{
>> +    TCGv_i64 t0 = tcg_temp_new_i64();
>> +    TCGv_i64 t1 = tcg_temp_new_i64();
>> +
>> +    tcg_gen_ext_tl_i64(t0, arg);
>> +    tcg_gen_ld_i64(t1, cpu_env, off);
>> +#if defined(TARGET_MIPS64)
>> +    tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
>> +#else
>> +    tcg_gen_concat32_i64(t1, t1, t0);
> 
> I don't get what this case is about. what's wrong with the above case
> for MIPS64 and MIPS32?

As already clarified in the other email EntryLo.PFNX in MIPS32 starts at 32.

> 
>> +#endif
>> +    tcg_gen_st_i64(t1, cpu_env, off);
>> +    tcg_temp_free_i64(t1);
>> +    tcg_temp_free_i64(t0);
>> +}
>> +
>> +static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
>> +{
>> +    TCGv_i64 t0 = tcg_temp_new_i64();
>> +    TCGv_i64 t1 = tcg_temp_new_i64();
>> +
>> +    tcg_gen_ext_tl_i64(t0, arg);
>> +    tcg_gen_ld_i64(t1, cpu_env, off);
>> +    tcg_gen_concat32_i64(t1, t1, t0);
>> +    tcg_gen_st_i64(t1, cpu_env, off);
>> +    tcg_temp_free_i64(t1);
>> +    tcg_temp_free_i64(t0);
> 
> simpler to just store a 32-bit value (st32_tl) to the appropriate half,
> depending on host endianness? (i.e. +4 if little endian)

Using the #ifdef HOST_WORDS_BIGENDIAN seems a bit ugly to me. I
personally prefer the current implementation.

> 
>> +}
>> +
>> +static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
>> +{
>> +    TCGv_i64 t0 = tcg_temp_new_i64();
>> +
>> +    tcg_gen_ld_i64(t0, cpu_env, off);
>> +#if defined(TARGET_MIPS64)
>> +    tcg_gen_shri_i64(t0, t0, 30);
> 
> need to mask off the xi/ri bits?

Yeh, it was there before I did the last minute "improvements" (for some
reason I assumed that the trunc below would take care of it so masking
off was not required, but now I can see I was wrong). Thanks for
catching this.

> 
>> +#else
>> +    tcg_gen_shri_i64(t0, t0, 32);
> 
> Again, I'm not convinced MIPS32 needs special handling here.
> 
>> +#endif
>> +    tcg_gen_trunc_i64_tl(arg, t0);
>> +    tcg_temp_free_i64(t0);
>> +}
>> +
>> +static inline void gen_mfhc0_load64(TCGv arg, target_ulong off)
>> +{
>> +    TCGv_i64 t0 = tcg_temp_new_i64();
>> +
>> +    tcg_gen_ld_i64(t0, cpu_env, off);
>> +    tcg_gen_shri_i64(t0, t0, 32);
> 
> simpler to just load a signed 32-bit value (ld32s_tl) from the
> appropriate half, depending on host endianness? (i.e. +4 if little endian)
> 
>> +    tcg_gen_trunc_i64_tl(arg, t0);
>> +    tcg_temp_free_i64(t0);
>> +}
>> +
>>  static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
>>  {
>>      TCGv_i32 t0 = tcg_temp_new_i32();
>> @@ -4850,6 +4915,134 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
>>      tcg_gen_st_tl(arg, cpu_env, off);
>>  }
>>  
>> +static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>> +{
>> +    const char *rn = "invalid";
>> +
>> +    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
> 
> worth reusing the CP0_CHECK stuff?

Currently CP0_CHECK tests only for unimplemented registers which I think
doesn’t fit well here.

> 
>> +        goto mfhc0_read_zero;
>> +    }
>> +
>> +    switch (reg) {
>> +    case 2:
>> +        switch (sel) {
>> +        case 0:
>> +            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
>> +            rn = "EntryLo0";
>> +            break;
>> +        default:
>> +            goto mfhc0_read_zero;
>> +        }
>> +        break;
>> +    case 3:
>> +        switch (sel) {
>> +        case 0:
>> +            gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
>> +            rn = "EntryLo1";
>> +            break;
>> +        default:
>> +            goto mfhc0_read_zero;
>> +        }
>> +        break;
>> +    case 17:
>> +        switch (sel) {
>> +        case 0:
>> +            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr));
>> +            rn = "LLAddr";
>> +            break;
>> +        default:
>> +            goto mfhc0_read_zero;
>> +        }
>> +        break;
>> +    case 28:
>> +        switch (sel) {
>> +        case 0:
>> +        case 2:
>> +        case 4:
>> +        case 6:
>> +            gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo));
>> +            rn = "TagLo";
>> +            break;
>> +        default:
>> +            goto mfhc0_read_zero;
>> +        }
>> +        break;
>> +    default:
>> +        goto mfhc0_read_zero;
>> +    }
>> +
>> +    (void)rn; /* avoid a compiler warning */
>> +    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
>> +    return;
>> +
>> +mfhc0_read_zero:
>> +    LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
>> +    tcg_gen_movi_tl(arg, 0);
>> +}
>> +
>> +static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
>> +{
>> +    const char *rn = "invalid";
>> +
>> +    if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
>> +        goto mthc0_nop;
>> +    }
>> +
>> +    tcg_gen_andi_tl(arg, arg, ctx->PAMask >> 36);
> 
> Shouldn't this depend on the register? LLAddr shift varies per core
> (CP0_LLAddr_shift), but EntryLo shift will be the same for each core.

Yes, it should. I'll correct that.

Thanks,
Leon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field
  2015-04-28 21:39       ` James Hogan
@ 2015-04-29 15:31         ` Leon Alrae
  0 siblings, 0 replies; 18+ messages in thread
From: Leon Alrae @ 2015-04-29 15:31 UTC (permalink / raw)
  To: James Hogan; +Cc: qemu-devel, aurelien

> I think I wasn't expecting that because 32-bit kernels can run on MIPS64
> hardware using the same mfc0/mfhc0 instructions, so having a single
> internal representation in QEMU seemed simpler & less fragile, since the
> same source code needs to support both MIPS32 and MIPS64 anyway.

In my opinion implementing MIPS32 details in a different way than
specified in MIPS32 PRA would be actually more fragile. That could cause
just more confusion when implementing future MIPS32 PRA changes
affecting this area.

Leon

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2015-04-29 15:32 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-28 12:41 [Qemu-devel] [PATCH 0/7] target-mips: add support for large physical addresses Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 1/7] target-mips: extend selected CP0 registers to 64-bits in MIPS32 Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 2/7] target-mips: support Page Frame Number Extension field Leon Alrae
2015-04-28 13:35   ` James Hogan
2015-04-28 13:47     ` James Hogan
2015-04-28 15:59     ` Leon Alrae
2015-04-28 21:39       ` James Hogan
2015-04-29 15:31         ` Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 3/7] target-mips: add CP0.PageGrain.ELPA support Leon Alrae
2015-04-28 15:08   ` James Hogan
2015-04-29 11:35     ` Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 4/7] target-mips: add MTHC0 and MFHC0 instructions Leon Alrae
2015-04-28 15:52   ` James Hogan
2015-04-29 14:26     ` Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 5/7] target-mips: correct MFC0 for CP0.EntryLo in MIPS64 Leon Alrae
2015-04-28 12:41 ` [Qemu-devel] [PATCH 6/7] target-mips: remove invalid comments in translate_init.c Leon Alrae
2015-04-28 21:50   ` James Hogan
2015-04-28 12:41 ` [Qemu-devel] [PATCH 7/7] target-mips: enable XPA and LPA features Leon Alrae

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.