[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v4 1/4] target/ppc: Introduce ppc_radix64_xlate() for Radix t
From: |
David Gibson |
Subject: |
Re: [PATCH v4 1/4] target/ppc: Introduce ppc_radix64_xlate() for Radix tree translation |
Date: |
Wed, 8 Apr 2020 12:57:37 +1000 |
On Fri, Apr 03, 2020 at 04:00:53PM +0200, Cédric Le Goater wrote:
> This is moving code under a new ppc_radix64_xlate() routine shared by
> the MMU Radix page fault handler and the 'get_phys_page_debug' PPC
> callback. The difference being that 'get_phys_page_debug' does not
> generate exceptions.
>
> The specific part of process-scoped Radix translation is moved under
> ppc_radix64_process_scoped_xlate() in preparation of the future support
> for partition-scoped Radix translation. Routines raising the exceptions
> now take a 'cause_excp' bool to cover the 'get_phys_page_debug' case.
>
> It should be functionally equivalent.
>
> Signed-off-by: Suraj Jitindar Singh <address@hidden>
> Signed-off-by: Cédric Le Goater <address@hidden>
Applied to ppc-for-5.1.
> ---
> target/ppc/mmu-radix64.c | 219 ++++++++++++++++++++++-----------------
> 1 file changed, 123 insertions(+), 96 deletions(-)
>
> diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
> index d2422d1c54c9..4b0d0ff50a3c 100644
> --- a/target/ppc/mmu-radix64.c
> +++ b/target/ppc/mmu-radix64.c
> @@ -219,17 +219,127 @@ static bool validate_pate(PowerPCCPU *cpu, uint64_t
> lpid, ppc_v3_pate_t *pate)
> return true;
> }
>
> +static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, int rwx,
> + vaddr eaddr, uint64_t pid,
> + ppc_v3_pate_t pate, hwaddr
> *g_raddr,
> + int *g_prot, int *g_page_size,
> + bool cause_excp)
> +{
> + CPUState *cs = CPU(cpu);
> + uint64_t offset, size, prtbe_addr, prtbe0, pte;
> + int fault_cause = 0;
> + hwaddr pte_addr;
> +
> + /* Index Process Table by PID to Find Corresponding Process Table Entry
> */
> + offset = pid * sizeof(struct prtb_entry);
> + size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
> + if (offset >= size) {
> + /* offset exceeds size of the process table */
> + if (cause_excp) {
> + ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
> + }
> + return 1;
> + }
> + prtbe_addr = (pate.dw1 & PATE1_R_PRTB) + offset;
> + prtbe0 = ldq_phys(cs->as, prtbe_addr);
> +
> + /* Walk Radix Tree from Process Table Entry to Convert EA to RA */
> + *g_page_size = PRTBE_R_GET_RTS(prtbe0);
> + pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK,
> + prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS,
> + g_raddr, g_page_size, &fault_cause,
> &pte_addr);
> +
> + if (!(pte & R_PTE_VALID) ||
> + ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot)) {
> + /* No valid pte or access denied due to protection */
> + if (cause_excp) {
> + ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
> + }
> + return 1;
> + }
> +
> + ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot);
> +
> + return 0;
> +}
> +
> +static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
> + bool relocation,
> + hwaddr *raddr, int *psizep, int *protp,
> + bool cause_excp)
> +{
> + uint64_t lpid = 0, pid = 0;
> + ppc_v3_pate_t pate;
> + int psize, prot;
> + hwaddr g_raddr;
> +
> + /* Virtual Mode Access - get the fully qualified address */
> + if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid,
> &pid)) {
> + if (cause_excp) {
> + ppc_radix64_raise_segi(cpu, rwx, eaddr);
> + }
> + return 1;
> + }
> +
> + /* Get Process Table */
> + if (cpu->vhyp) {
> + PPCVirtualHypervisorClass *vhc;
> + vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
> + vhc->get_pate(cpu->vhyp, &pate);
> + } else {
> + if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
> + if (cause_excp) {
> + ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
> + }
> + return 1;
> + }
> + if (!validate_pate(cpu, lpid, &pate)) {
> + if (cause_excp) {
> + ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
> + }
> + return 1;
> + }
> + /* We don't support guest mode yet */
> + if (lpid != 0) {
> + error_report("PowerNV guest support Unimplemented");
> + exit(1);
> + }
> + }
> +
> + *psizep = INT_MAX;
> + *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> +
> + /*
> + * Perform process-scoped translation if relocation enabled.
> + *
> + * - Translates an effective address to a host real address in
> + * quadrants 0 and 3 when HV=1.
> + */
> + if (relocation) {
> + int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid,
> + pate, &g_raddr, &prot,
> + &psize, cause_excp);
> + if (ret) {
> + return ret;
> + }
> + *psizep = MIN(*psizep, psize);
> + *protp &= prot;
> + } else {
> + g_raddr = eaddr & R_EADDR_MASK;
> + }
> +
> + *raddr = g_raddr;
> + return 0;
> +}
> +
> int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
> int mmu_idx)
> {
> CPUState *cs = CPU(cpu);
> CPUPPCState *env = &cpu->env;
> - PPCVirtualHypervisorClass *vhc;
> - hwaddr raddr, pte_addr;
> - uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
> - int page_size, prot, fault_cause = 0;
> - ppc_v3_pate_t pate;
> + int page_size, prot;
> bool relocation;
> + hwaddr raddr;
>
> assert(!(msr_hv && cpu->vhyp));
> assert((rwx == 0) || (rwx == 1) || (rwx == 2));
> @@ -262,55 +372,12 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr
> eaddr, int rwx,
> TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
> }
>
> - /* Virtual Mode Access - get the fully qualified address */
> - if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) {
> - ppc_radix64_raise_segi(cpu, rwx, eaddr);
> + /* Translate eaddr to raddr (where raddr is addr qemu needs for access)
> */
> + if (ppc_radix64_xlate(cpu, eaddr, rwx, relocation, &raddr,
> + &page_size, &prot, true)) {
> return 1;
> }
>
> - /* Get Process Table */
> - if (cpu->vhyp) {
> - vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
> - vhc->get_pate(cpu->vhyp, &pate);
> - } else {
> - if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
> - ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
> - return 1;
> - }
> - if (!validate_pate(cpu, lpid, &pate)) {
> - ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
> - }
> - /* We don't support guest mode yet */
> - if (lpid != 0) {
> - error_report("PowerNV guest support Unimplemented");
> - exit(1);
> - }
> - }
> -
> - /* Index Process Table by PID to Find Corresponding Process Table Entry
> */
> - offset = pid * sizeof(struct prtb_entry);
> - size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
> - if (offset >= size) {
> - /* offset exceeds size of the process table */
> - ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
> - return 1;
> - }
> - prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
> -
> - /* Walk Radix Tree from Process Table Entry to Convert EA to RA */
> - page_size = PRTBE_R_GET_RTS(prtbe0);
> - pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK,
> - prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS,
> - &raddr, &page_size, &fault_cause, &pte_addr);
> - if (!pte || ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, &prot)) {
> - /* Couldn't get pte or access denied due to protection */
> - ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
> - return 1;
> - }
> -
> - /* Update Reference and Change Bits */
> - ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, &prot);
> -
> tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
> prot, mmu_idx, 1UL << page_size);
> return 0;
> @@ -318,58 +385,18 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr
> eaddr, int rwx,
>
> hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr)
> {
> - CPUState *cs = CPU(cpu);
> CPUPPCState *env = &cpu->env;
> - PPCVirtualHypervisorClass *vhc;
> - hwaddr raddr, pte_addr;
> - uint64_t lpid = 0, pid = 0, offset, size, prtbe0, pte;
> - int page_size, fault_cause = 0;
> - ppc_v3_pate_t pate;
> + int psize, prot;
> + hwaddr raddr;
>
> /* Handle Real Mode */
> - if (msr_dr == 0) {
> + if ((msr_dr == 0) && (msr_hv || cpu->vhyp)) {
> /* In real mode top 4 effective addr bits (mostly) ignored */
> return eaddr & 0x0FFFFFFFFFFFFFFFULL;
> }
>
> - /* Virtual Mode Access - get the fully qualified address */
> - if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) {
> - return -1;
> - }
> -
> - /* Get Process Table */
> - if (cpu->vhyp) {
> - vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
> - vhc->get_pate(cpu->vhyp, &pate);
> - } else {
> - if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
> - return -1;
> - }
> - if (!validate_pate(cpu, lpid, &pate)) {
> - return -1;
> - }
> - /* We don't support guest mode yet */
> - if (lpid != 0) {
> - error_report("PowerNV guest support Unimplemented");
> - exit(1);
> - }
> - }
> -
> - /* Index Process Table by PID to Find Corresponding Process Table Entry
> */
> - offset = pid * sizeof(struct prtb_entry);
> - size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
> - if (offset >= size) {
> - /* offset exceeds size of the process table */
> - return -1;
> - }
> - prtbe0 = ldq_phys(cs->as, (pate.dw1 & PATE1_R_PRTB) + offset);
> -
> - /* Walk Radix Tree from Process Table Entry to Convert EA to RA */
> - page_size = PRTBE_R_GET_RTS(prtbe0);
> - pte = ppc_radix64_walk_tree(cpu, eaddr & R_EADDR_MASK,
> - prtbe0 & PRTBE_R_RPDB, prtbe0 & PRTBE_R_RPDS,
> - &raddr, &page_size, &fault_cause, &pte_addr);
> - if (!pte) {
> + if (ppc_radix64_xlate(cpu, eaddr, 0, msr_dr, &raddr, &psize,
> + &prot, false)) {
> return -1;
> }
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature