[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;
>>> }
>>>
>>
>
- Re: [PATCH 1/7] target/ppc: Enforce that the root page directory size must be at least 5, (continued)
[PATCH 5/7] target/ppc: Rework ppc_radix64_walk_tree() for partition-scoped translation, Cédric Le Goater, 2020/03/30
[PATCH 6/7] target/ppc: Extend ppc_radix64_check_prot() with a 'partition_scoped' bool, Cédric Le Goater, 2020/03/30