diff mbox

[3/6] target/ppc: SDR1 is a hypervisor resource

Message ID 20170223020936.29220-4-david@gibson.dropbear.id.au (mailing list archive)
State New, archived
Headers show

Commit Message

David Gibson Feb. 23, 2017, 2:09 a.m. UTC
At present the SDR1 register - the base of the system's hashed page table
(HPT) - is represented as an SPR with supervisor read and write permission.
However, on CPUs which have a hypervisor mode, the SDR1 is a hypervisor
only resource.  Change the permission checking on the SPR to reflect this.

Now that this is done, we don't need to check for an external HPT executing
mtsdr1: an external HPT only applies when we're emulating the behaviour of
a hypervisor, rather than modelling the CPU's hypervisor mode internally,
so if we're permitted to execute mtsdr1, we don't have an external HPT.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 target/ppc/misc_helper.c    |  8 +++-----
 target/ppc/translate_init.c | 20 ++++++++++++++++----
 2 files changed, 19 insertions(+), 9 deletions(-)

Comments

Suraj Jitindar Singh Feb. 23, 2017, 4:32 a.m. UTC | #1
On Thu, 2017-02-23 at 13:09 +1100, David Gibson wrote:
> At present the SDR1 register - the base of the system's hashed page
> table
> (HPT) - is represented as an SPR with supervisor read and write
> permission.
> However, on CPUs which have a hypervisor mode, the SDR1 is a
> hypervisor
> only resource.  Change the permission checking on the SPR to reflect
> this.
> 
> Now that this is done, we don't need to check for an external HPT
> executing
> mtsdr1: an external HPT only applies when we're emulating the
> behaviour of
> a hypervisor, rather than modelling the CPU's hypervisor mode
> internally,
> so if we're permitted to execute mtsdr1, we don't have an external
> HPT.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
>  target/ppc/misc_helper.c    |  8 +++-----
>  target/ppc/translate_init.c | 20 ++++++++++++++++----
>  2 files changed, 19 insertions(+), 9 deletions(-)
> 
> diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> index ab432ba..fa573dd 100644
> --- a/target/ppc/misc_helper.c
> +++ b/target/ppc/misc_helper.c
> @@ -82,11 +82,9 @@ void helper_store_sdr1(CPUPPCState *env,
> target_ulong val)
>  {
>      PowerPCCPU *cpu = ppc_env_get_cpu(env);
>  
> -    if (!env->external_htab) {
> -        if (env->spr[SPR_SDR1] != val) {
> -            ppc_store_sdr1(env, val);
> -            tlb_flush(CPU(cpu));
> -        }

It may have been the case we didn't have to check this before anyway...
Oh well

> +    if (env->spr[SPR_SDR1] != val) {
> +        ppc_store_sdr1(env, val);
> +        tlb_flush(CPU(cpu));
>      }
>  }
>  
> diff --git a/target/ppc/translate_init.c
> b/target/ppc/translate_init.c
> index a1405e9..c92435d 100644
> --- a/target/ppc/translate_init.c
> +++ b/target/ppc/translate_init.c
> @@ -740,10 +740,22 @@ static void gen_spr_ne_601 (CPUPPCState *env)
>                   &spr_read_decr, &spr_write_decr,
>                   0x00000000);
>      /* Memory management */
> -    spr_register(env, SPR_SDR1, "SDR1",
> -                 SPR_NOACCESS, SPR_NOACCESS,
> -                 &spr_read_generic, &spr_write_sdr1,
> -                 0x00000000);
> +#ifndef CONFIG_USER_ONLY
> +    if (env->has_hv_mode) {
> +        /* SDR1 is a hypervisor resource on CPUs which have a
> +         * hypervisor mode */
> +        spr_register_hv(env, SPR_SDR1, "SDR1",
> +                        SPR_NOACCESS, SPR_NOACCESS,
> +                        SPR_NOACCESS, SPR_NOACCESS,
> +                        &spr_read_generic, &spr_write_sdr1,
> +                        0x00000000);
> +    } else {
> +        spr_register(env, SPR_SDR1, "SDR1",
> +                     SPR_NOACCESS, SPR_NOACCESS,
> +                     &spr_read_generic, &spr_write_sdr1,
> +                     0x00000000);
> +    }
> +#endif
>  }
>  
>  /* BATs 0-3 */

Reviewed-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
David Gibson Feb. 23, 2017, 5:11 a.m. UTC | #2
On Thu, Feb 23, 2017 at 03:32:04PM +1100, Suraj Jitindar Singh wrote:
> On Thu, 2017-02-23 at 13:09 +1100, David Gibson wrote:
> > At present the SDR1 register - the base of the system's hashed page
> > table
> > (HPT) - is represented as an SPR with supervisor read and write
> > permission.
> > However, on CPUs which have a hypervisor mode, the SDR1 is a
> > hypervisor
> > only resource.  Change the permission checking on the SPR to reflect
> > this.
> > 
> > Now that this is done, we don't need to check for an external HPT
> > executing
> > mtsdr1: an external HPT only applies when we're emulating the
> > behaviour of
> > a hypervisor, rather than modelling the CPU's hypervisor mode
> > internally,
> > so if we're permitted to execute mtsdr1, we don't have an external
> > HPT.
> > 
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  target/ppc/misc_helper.c    |  8 +++-----
> >  target/ppc/translate_init.c | 20 ++++++++++++++++----
> >  2 files changed, 19 insertions(+), 9 deletions(-)
> > 
> > diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
> > index ab432ba..fa573dd 100644
> > --- a/target/ppc/misc_helper.c
> > +++ b/target/ppc/misc_helper.c
> > @@ -82,11 +82,9 @@ void helper_store_sdr1(CPUPPCState *env,
> > target_ulong val)
> >  {
> >      PowerPCCPU *cpu = ppc_env_get_cpu(env);
> >  
> > -    if (!env->external_htab) {
> > -        if (env->spr[SPR_SDR1] != val) {
> > -            ppc_store_sdr1(env, val);
> > -            tlb_flush(CPU(cpu));
> > -        }
> 
> It may have been the case we didn't have to check this before anyway...
> Oh well

Actually I think we did.  At least with a TCG (and maybe KVM PR)
guest, because the SDR1 was previously treated as a supervisor
resource, the guest could have issued an mtsdr1, changing the size of
the HPT.  We still would have read from the external_htab, but if the
size was changed the guest could have triggered accesses beyond the
end of it, crashing qemu.

With this check in place the behaviour of mtsdr1 was wrong (it was a
no-op instead of causing a privlieged instruction exception), but not
dangerous.

>
> > +    if (env->spr[SPR_SDR1] != val) {
> > +        ppc_store_sdr1(env, val);
> > +        tlb_flush(CPU(cpu));
> >      }
> >  }
> >  
> > diff --git a/target/ppc/translate_init.c
> > b/target/ppc/translate_init.c
> > index a1405e9..c92435d 100644
> > --- a/target/ppc/translate_init.c
> > +++ b/target/ppc/translate_init.c
> > @@ -740,10 +740,22 @@ static void gen_spr_ne_601 (CPUPPCState *env)
> >                   &spr_read_decr, &spr_write_decr,
> >                   0x00000000);
> >      /* Memory management */
> > -    spr_register(env, SPR_SDR1, "SDR1",
> > -                 SPR_NOACCESS, SPR_NOACCESS,
> > -                 &spr_read_generic, &spr_write_sdr1,
> > -                 0x00000000);
> > +#ifndef CONFIG_USER_ONLY
> > +    if (env->has_hv_mode) {
> > +        /* SDR1 is a hypervisor resource on CPUs which have a
> > +         * hypervisor mode */
> > +        spr_register_hv(env, SPR_SDR1, "SDR1",
> > +                        SPR_NOACCESS, SPR_NOACCESS,
> > +                        SPR_NOACCESS, SPR_NOACCESS,
> > +                        &spr_read_generic, &spr_write_sdr1,
> > +                        0x00000000);
> > +    } else {
> > +        spr_register(env, SPR_SDR1, "SDR1",
> > +                     SPR_NOACCESS, SPR_NOACCESS,
> > +                     &spr_read_generic, &spr_write_sdr1,
> > +                     0x00000000);
> > +    }
> > +#endif
> >  }
> >  
> >  /* BATs 0-3 */
> 
> Reviewed-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
>
diff mbox

Patch

diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index ab432ba..fa573dd 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -82,11 +82,9 @@  void helper_store_sdr1(CPUPPCState *env, target_ulong val)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
 
-    if (!env->external_htab) {
-        if (env->spr[SPR_SDR1] != val) {
-            ppc_store_sdr1(env, val);
-            tlb_flush(CPU(cpu));
-        }
+    if (env->spr[SPR_SDR1] != val) {
+        ppc_store_sdr1(env, val);
+        tlb_flush(CPU(cpu));
     }
 }
 
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index a1405e9..c92435d 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -740,10 +740,22 @@  static void gen_spr_ne_601 (CPUPPCState *env)
                  &spr_read_decr, &spr_write_decr,
                  0x00000000);
     /* Memory management */
-    spr_register(env, SPR_SDR1, "SDR1",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_sdr1,
-                 0x00000000);
+#ifndef CONFIG_USER_ONLY
+    if (env->has_hv_mode) {
+        /* SDR1 is a hypervisor resource on CPUs which have a
+         * hypervisor mode */
+        spr_register_hv(env, SPR_SDR1, "SDR1",
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        SPR_NOACCESS, SPR_NOACCESS,
+                        &spr_read_generic, &spr_write_sdr1,
+                        0x00000000);
+    } else {
+        spr_register(env, SPR_SDR1, "SDR1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_sdr1,
+                     0x00000000);
+    }
+#endif
 }
 
 /* BATs 0-3 */