qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 4/7] target/ppc: Introduce ppc_radix64_xlate() for Radix tree


From: Cédric Le Goater
Subject: Re: [PATCH 4/7] target/ppc: Introduce ppc_radix64_xlate() for Radix tree translation
Date: Mon, 30 Mar 2020 17:34:40 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0

>>> +        /* 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,
>>> +                             uint64_t lpid, uint64_t pid, bool relocation,
>>> +                             hwaddr *raddr, int *psizep, int *protp,
>>> +                             bool cause_excp)
>>> +{
>>> +    ppc_v3_pate_t pate;
>>> +    int psize, prot;
>>> +    hwaddr g_raddr;
>>> +
>>> +    *psizep = INT_MAX;
>>> +    *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
>>> +
>>> +    /* Get Process Table */
>>> +    if (cpu->vhyp && lpid == 0) {
>>
>> Current code doesn't check lpid == 0. Not sure to see what it's for...
> 
> cpu->vhyp means a pseries machine, lpid == 0 means accessing quadrant3, 
> so it's the kernel.

Sorry. I misread that. It would pid == 0 for the kernel. 

So yes, the test cpu->vhyp && lpid == 0 might be a bit overkill, given 
that lpid is always 0 when running under a QEMU pseries machine.


C.

> 
>> especially env->spr[SPR_LPIDR] is always 0 with pseries machine types
>> AFAICT... is it even possible to have lpid != 0 here ?
> 
> When under PowerNV, SPR_LPIDR can be set, but not under pseries.
> 
> C.
> 
>>
>>
>> Rest LGTM.
>>
>>> +        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);
>>> +        }
>>> +    }
>>> +
>>> +    /*
>>> +     * 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, lpid, 
>>> 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;
>>> +    uint64_t lpid = 0, pid = 0;
>>> +    int page_size, prot;
>>>      bool relocation;
>>> +    hwaddr raddr;
>>>  
>>>      assert(!(msr_hv && cpu->vhyp));
>>>      assert((rwx == 0) || (rwx == 1) || (rwx == 2));
>>> @@ -268,48 +370,11 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, 
>>> vaddr eaddr, int rwx,
>>>          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);
>>> +    /* Translate eaddr to raddr (where raddr is addr qemu needs for 
>>> access) */
>>> +    if (ppc_radix64_xlate(cpu, eaddr, rwx, lpid, pid, relocation, &raddr,
>>> +                          &page_size, &prot, 1)) {
>>>          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);
>>> @@ -318,16 +383,13 @@ 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;
>>> +    uint64_t lpid = 0, pid = 0;
>>> +    int psize, prot;
>>> +    hwaddr raddr;
>>>  
>>>      /* Handle Real Mode */
>>> -    if (msr_dr == 0) {
>>> +    if ((msr_dr == 0) && (msr_hv || (cpu->vhyp && lpid == 0))) {
>>>          /* In real mode top 4 effective addr bits (mostly) ignored */
>>>          return eaddr & 0x0FFFFFFFFFFFFFFFULL;
>>>      }
>>> @@ -337,39 +399,8 @@ hwaddr ppc_radix64_get_phys_page_debug(PowerPCCPU 
>>> *cpu, target_ulong eaddr)
>>>          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, lpid, pid, msr_dr, &raddr, &psize,
>>> +                          &prot, 0)) {
>>>          return -1;
>>>      }
>>>  
>>
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]