Re: [Qemu-devel] [QEMU-PPC] [PATCH 07/13] target/ppc: Handle partition scoped radix tree translation

2019-05-09 Thread David Gibson
On Fri, May 03, 2019 at 03:53:10PM +1000, Suraj Jitindar Singh wrote:
> Radix tree translation is a 2 step process:
> 
> Process Scoped Translation:
> Effective Address (EA) -> Virtual Address (VA)
> 
> Paritition Scoped Translation:
> Virtual Address (VA) -> Real Address (RA)
> 
> Performed based on:
>   MSR[HV]
>---
>| | HV = 0| HV = 1|
>---
>| Relocation  |   Partition   |  No   |
>| = Off   |Scoped |  Translation  |
> Relocation ---
>| Relocation  |  Partition &  |Process|
>| = On|Process Scoped |Scoped |
>---
> 
> Currently only process scoped translation is handled.
> Implement partitition scoped translation.
> 
> The process of using the radix trees to perform partition scoped
> translation is identical to process scoped translation, however
> hypervisor exceptions are generated, and thus we can reuse the radix
> tree traversing code.
> 
> Signed-off-by: Suraj Jitindar Singh 
> ---
>  target/ppc/cpu.h |   2 +
>  target/ppc/excp_helper.c |   3 +-
>  target/ppc/mmu-radix64.c | 407 
> +--
>  3 files changed, 293 insertions(+), 119 deletions(-)
> 
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 1d2a088391..3acc248f40 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -501,6 +501,8 @@ typedef struct ppc_v3_pate_t {
>  /* Unsupported Radix Tree Configuration */
>  #define DSISR_R_BADCONFIG0x0008
>  #define DSISR_ATOMIC_RC  0x0004
> +/* Unable to translate address of (guest) pde or process/page table entry */
> +#define DSISR_PRTABLE_FAULT  0x0002
>  
>  /* SRR1 error code fields */
>  
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 7a4da7bdba..10091d4624 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -441,9 +441,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  case POWERPC_EXCP_ISEG:  /* Instruction segment exception
> */
>  case POWERPC_EXCP_TRACE: /* Trace exception  
> */
>  break;
> +case POWERPC_EXCP_HISI:  /* Hypervisor instruction storage exception 
> */
> +msr |= env->error_code;
>  case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception 
> */
>  case POWERPC_EXCP_HDSI:  /* Hypervisor data storage exception
> */
> -case POWERPC_EXCP_HISI:  /* Hypervisor instruction storage exception 
> */
>  case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception
> */
>  case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception 
> */
>  case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt
> */
> diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
> index afa5ba506a..6118ad1b00 100644
> --- a/target/ppc/mmu-radix64.c
> +++ b/target/ppc/mmu-radix64.c
> @@ -112,9 +112,31 @@ static void ppc_radix64_raise_si(PowerPCCPU *cpu, int 
> rwx, vaddr eaddr,
>  }
>  }
>  
> +static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, int rwx, vaddr eaddr,
> +  hwaddr g_raddr, uint32_t cause)
> +{
> +CPUState *cs = CPU(cpu);
> +CPUPPCState *env = >env;
> +
> +if (rwx == 2) { /* H Instruction Storage Interrupt */
> +cs->exception_index = POWERPC_EXCP_HISI;
> +env->spr[SPR_ASDR] = g_raddr;
> +env->error_code = cause;
> +} else { /* H Data Storage Interrupt */
> +cs->exception_index = POWERPC_EXCP_HDSI;
> +if (rwx == 1) { /* Write -> Store */
> +cause |= DSISR_ISSTORE;
> +}
> +env->spr[SPR_HDSISR] = cause;
> +env->spr[SPR_HDAR] = eaddr;
> +env->spr[SPR_ASDR] = g_raddr;
> +env->error_code = 0;
> +}
> +}
>  
>  static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte,
> -   int *fault_cause, int *prot)
> +   int *fault_cause, int *prot,
> +   bool partition_scoped)
>  {
>  CPUPPCState *env = >env;
>  const int need_prot[] = { PAGE_READ, PAGE_WRITE, PAGE_EXEC };
> @@ -130,11 +152,11 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int 
> rwx, uint64_t pte,
>  }
>  
>  /* Determine permissions allowed by Encoded Access Authority */
> -if ((pte & R_PTE_EAA_PRIV) && msr_pr) { /* Insufficient Privilege */
> +if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) {
>  *prot = 0;
> -} else if (msr_pr || (pte & R_PTE_EAA_PRIV)) {
> +} else if (msr_pr || (pte & R_PTE_EAA_PRIV) 

[Qemu-devel] [QEMU-PPC] [PATCH 07/13] target/ppc: Handle partition scoped radix tree translation

2019-05-02 Thread Suraj Jitindar Singh
Radix tree translation is a 2 step process:

Process Scoped Translation:
Effective Address (EA) -> Virtual Address (VA)

Paritition Scoped Translation:
Virtual Address (VA) -> Real Address (RA)

Performed based on:
  MSR[HV]
   ---
   | | HV = 0| HV = 1|
   ---
   | Relocation  |   Partition   |  No   |
   | = Off   |Scoped |  Translation  |
Relocation ---
   | Relocation  |  Partition &  |Process|
   | = On|Process Scoped |Scoped |
   ---

Currently only process scoped translation is handled.
Implement partitition scoped translation.

The process of using the radix trees to perform partition scoped
translation is identical to process scoped translation, however
hypervisor exceptions are generated, and thus we can reuse the radix
tree traversing code.

Signed-off-by: Suraj Jitindar Singh 
---
 target/ppc/cpu.h |   2 +
 target/ppc/excp_helper.c |   3 +-
 target/ppc/mmu-radix64.c | 407 +--
 3 files changed, 293 insertions(+), 119 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 1d2a088391..3acc248f40 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -501,6 +501,8 @@ typedef struct ppc_v3_pate_t {
 /* Unsupported Radix Tree Configuration */
 #define DSISR_R_BADCONFIG0x0008
 #define DSISR_ATOMIC_RC  0x0004
+/* Unable to translate address of (guest) pde or process/page table entry */
+#define DSISR_PRTABLE_FAULT  0x0002
 
 /* SRR1 error code fields */
 
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 7a4da7bdba..10091d4624 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -441,9 +441,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 case POWERPC_EXCP_ISEG:  /* Instruction segment exception*/
 case POWERPC_EXCP_TRACE: /* Trace exception  */
 break;
+case POWERPC_EXCP_HISI:  /* Hypervisor instruction storage exception */
+msr |= env->error_code;
 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
 case POWERPC_EXCP_HDSI:  /* Hypervisor data storage exception*/
-case POWERPC_EXCP_HISI:  /* Hypervisor instruction storage exception */
 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception*/
 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
 case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt*/
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index afa5ba506a..6118ad1b00 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -112,9 +112,31 @@ static void ppc_radix64_raise_si(PowerPCCPU *cpu, int rwx, 
vaddr eaddr,
 }
 }
 
+static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, int rwx, vaddr eaddr,
+  hwaddr g_raddr, uint32_t cause)
+{
+CPUState *cs = CPU(cpu);
+CPUPPCState *env = >env;
+
+if (rwx == 2) { /* H Instruction Storage Interrupt */
+cs->exception_index = POWERPC_EXCP_HISI;
+env->spr[SPR_ASDR] = g_raddr;
+env->error_code = cause;
+} else { /* H Data Storage Interrupt */
+cs->exception_index = POWERPC_EXCP_HDSI;
+if (rwx == 1) { /* Write -> Store */
+cause |= DSISR_ISSTORE;
+}
+env->spr[SPR_HDSISR] = cause;
+env->spr[SPR_HDAR] = eaddr;
+env->spr[SPR_ASDR] = g_raddr;
+env->error_code = 0;
+}
+}
 
 static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int rwx, uint64_t pte,
-   int *fault_cause, int *prot)
+   int *fault_cause, int *prot,
+   bool partition_scoped)
 {
 CPUPPCState *env = >env;
 const int need_prot[] = { PAGE_READ, PAGE_WRITE, PAGE_EXEC };
@@ -130,11 +152,11 @@ static bool ppc_radix64_check_prot(PowerPCCPU *cpu, int 
rwx, uint64_t pte,
 }
 
 /* Determine permissions allowed by Encoded Access Authority */
-if ((pte & R_PTE_EAA_PRIV) && msr_pr) { /* Insufficient Privilege */
+if (!partition_scoped && (pte & R_PTE_EAA_PRIV) && msr_pr) {
 *prot = 0;
-} else if (msr_pr || (pte & R_PTE_EAA_PRIV)) {
+} else if (msr_pr || (pte & R_PTE_EAA_PRIV) || partition_scoped) {
 *prot = ppc_radix64_get_prot_eaa(pte);
-} else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) */
+} else { /* !msr_pr && !(pte & R_PTE_EAA_PRIV) && !partition_scoped */
 *prot = ppc_radix64_get_prot_eaa(pte);
 *prot &= ppc_radix64_get_prot_amr(cpu); /* Least combined