Patchwork [1/1] Added PMCR support

login
register
mail settings
Submitter matt.waddel@linaro.org
Date Aug. 3, 2010, 6:14 p.m.
Message ID <1280859290-25983-1-git-send-email-matt.waddel@linaro.org>
Download mbox | patch
Permalink /patch/60784/
State New
Headers show

Comments

matt.waddel@linaro.org - Aug. 3, 2010, 6:14 p.m.
From: Matt Waddel <matt.waddel@linaro.org>

Added support for the CP15c9-CR12 register(Performance Monitor Control
Register).  Calls to this register are being implemented in the ARM Linux
kernel.  The register has several bit fields, as described in the ARM
technical reference manual, but right now I only implemented it as a
single register.

Signed-off-by: Matt Waddel <matt.waddel@linaro.org>
---
 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |   20 ++++++++++++++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 24 insertions(+), 1 deletions(-)
Loïc Minier - Aug. 22, 2010, 6:24 p.m.
We've been using a cp15 fix for a while to fix modern ARM kernels (with
 perf support) from booting.  e.g. both the Ubuntu versatile and OMAP
 kernels fail to boot without this fix (the latter only boots with the
 OMAP patches too of course).

   Thanks!

On Tue, Aug 03, 2010, Matt Waddel wrote:
> From: Matt Waddel <matt.waddel@linaro.org>
> 
> Added support for the CP15c9-CR12 register(Performance Monitor Control
> Register).  Calls to this register are being implemented in the ARM Linux
> kernel.  The register has several bit fields, as described in the ARM
> technical reference manual, but right now I only implemented it as a
> single register.
> 
> Signed-off-by: Matt Waddel <matt.waddel@linaro.org>
> ---
>  target-arm/cpu.h     |    3 ++-
>  target-arm/helper.c  |   20 ++++++++++++++++++++
>  target-arm/machine.c |    2 ++
>  3 files changed, 24 insertions(+), 1 deletions(-)
> 
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 39c4a0e..a96c512 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -126,6 +126,7 @@ typedef struct CPUARMState {
>          uint32_t c6_data;
>          uint32_t c9_insn; /* Cache lockdown registers.  */
>          uint32_t c9_data;
> +        uint32_t c9_pmcr; /* Performance Monitor Control Register */
>          uint32_t c13_fcse; /* FCSE PID.  */
>          uint32_t c13_context; /* Context ID.  */
>          uint32_t c13_tls1; /* User RW Thread register.  */
> @@ -414,7 +415,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
>  #define cpu_signal_handler cpu_arm_signal_handler
>  #define cpu_list arm_cpu_list
>  
> -#define CPU_SAVE_VERSION 2
> +#define CPU_SAVE_VERSION 3
>  
>  /* MMU modes definitions */
>  #define MMU_MODE0_SUFFIX _kernel
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 2dd64d9..2272e8c 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1484,6 +1484,16 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
>          case 1: /* TCM memory region registers.  */
>              /* Not implemented.  */
>              goto bad_reg;
> +        case 12: /* PM control register */
> +            switch (op2) {
> +            case 0:
> +                /* c9_pmcr register has several bit-fields */
> +                env->cp15.c9_pmcr = val;
> +                break;
> +            default:
> +               goto bad_reg;
> +            }
> +            break;
>          default:
>              goto bad_reg;
>          }
> @@ -1774,6 +1784,16 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
>                  goto bad_reg;
>              /* L2 Lockdown and Auxiliary control.  */
>              return 0;
> +        case 12: /* PM control register */
> +            switch (op2) {
> +            case 0:
> +                /* c9_pmcr register has several bit-fields */
> +                return env->cp15.c9_pmcr;
> +                break;
> +            default:
> +               goto bad_reg;
> +            }
> +            break;
>          default:
>              goto bad_reg;
>          }
> diff --git a/target-arm/machine.c b/target-arm/machine.c
> index 3925d3a..efe9a02 100644
> --- a/target-arm/machine.c
> +++ b/target-arm/machine.c
> @@ -43,6 +43,7 @@ void cpu_save(QEMUFile *f, void *opaque)
>      qemu_put_be32(f, env->cp15.c6_data);
>      qemu_put_be32(f, env->cp15.c9_insn);
>      qemu_put_be32(f, env->cp15.c9_data);
> +    qemu_put_be32(f, env->cp15.c9_pmcr);
>      qemu_put_be32(f, env->cp15.c13_fcse);
>      qemu_put_be32(f, env->cp15.c13_context);
>      qemu_put_be32(f, env->cp15.c13_tls1);
> @@ -150,6 +151,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
>      env->cp15.c6_data = qemu_get_be32(f);
>      env->cp15.c9_insn = qemu_get_be32(f);
>      env->cp15.c9_data = qemu_get_be32(f);
> +    env->cp15.c9_pmcr = qemu_get_be32(f);
>      env->cp15.c13_fcse = qemu_get_be32(f);
>      env->cp15.c13_context = qemu_get_be32(f);
>      env->cp15.c13_tls1 = qemu_get_be32(f);
> -- 
> 1.7.0.4
> 
>

Patch

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 39c4a0e..a96c512 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -126,6 +126,7 @@  typedef struct CPUARMState {
         uint32_t c6_data;
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
+        uint32_t c9_pmcr; /* Performance Monitor Control Register */
         uint32_t c13_fcse; /* FCSE PID.  */
         uint32_t c13_context; /* Context ID.  */
         uint32_t c13_tls1; /* User RW Thread register.  */
@@ -414,7 +415,7 @@  void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 2
+#define CPU_SAVE_VERSION 3
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2dd64d9..2272e8c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1484,6 +1484,16 @@  void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         case 1: /* TCM memory region registers.  */
             /* Not implemented.  */
             goto bad_reg;
+        case 12: /* PM control register */
+            switch (op2) {
+            case 0:
+                /* c9_pmcr register has several bit-fields */
+                env->cp15.c9_pmcr = val;
+                break;
+            default:
+               goto bad_reg;
+            }
+            break;
         default:
             goto bad_reg;
         }
@@ -1774,6 +1784,16 @@  uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
                 goto bad_reg;
             /* L2 Lockdown and Auxiliary control.  */
             return 0;
+        case 12: /* PM control register */
+            switch (op2) {
+            case 0:
+                /* c9_pmcr register has several bit-fields */
+                return env->cp15.c9_pmcr;
+                break;
+            default:
+               goto bad_reg;
+            }
+            break;
         default:
             goto bad_reg;
         }
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 3925d3a..efe9a02 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -43,6 +43,7 @@  void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c6_data);
     qemu_put_be32(f, env->cp15.c9_insn);
     qemu_put_be32(f, env->cp15.c9_data);
+    qemu_put_be32(f, env->cp15.c9_pmcr);
     qemu_put_be32(f, env->cp15.c13_fcse);
     qemu_put_be32(f, env->cp15.c13_context);
     qemu_put_be32(f, env->cp15.c13_tls1);
@@ -150,6 +151,7 @@  int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c6_data = qemu_get_be32(f);
     env->cp15.c9_insn = qemu_get_be32(f);
     env->cp15.c9_data = qemu_get_be32(f);
+    env->cp15.c9_pmcr = qemu_get_be32(f);
     env->cp15.c13_fcse = qemu_get_be32(f);
     env->cp15.c13_context = qemu_get_be32(f);
     env->cp15.c13_tls1 = qemu_get_be32(f);