📄 xlate.c
字号:
if (f != NULL) put_domain(f); return H_PTEG_Full;}static void h_enter(struct cpu_user_regs *regs){ ulong flags = regs->gprs[4]; ulong ptex = regs->gprs[5]; ulong vsid = regs->gprs[6]; ulong rpn = regs->gprs[7]; long ret; ret = pte_enter(flags, ptex, vsid, rpn); if (ret >= 0) { regs->gprs[3] = H_Success; regs->gprs[4] = ret; } else regs->gprs[3] = ret;}static void h_protect(struct cpu_user_regs *regs){ ulong flags = regs->gprs[4]; ulong ptex = regs->gprs[5]; ulong avpn = regs->gprs[6]; struct vcpu *v = get_current(); struct domain *d = v->domain; struct domain_htab *htab = &d->arch.htab; union pte volatile *ppte; union pte lpte; DBG_LOW("%s: flags: 0x%lx ptex: 0x%lx avpn: 0x%lx\n", __func__, flags, ptex, avpn); if ( ptex > (1UL << htab->log_num_ptes) ) { DBG("%s: bad ptex: 0x%lx\n", __func__, ptex); regs->gprs[3] = H_Parameter; return; } ppte = &htab->map[ptex]; lpte.words.vsid = ppte->words.vsid; lpte.words.rpn = ppte->words.rpn; /* the AVPN param occupies the bit-space of the word */ if ( (flags & H_AVPN) && lpte.bits.avpn != avpn >> 7 ) { DBG_LOW("%s: %p: AVPN check failed: 0x%lx, 0x%lx\n", __func__, ppte, lpte.words.vsid, lpte.words.rpn); regs->gprs[3] = H_Not_Found; return; } if (lpte.bits.v == 0) { /* the PAPR does not specify what to do here, this is because * we invalidate entires where the PAPR says to 0 the whole hi * dword, so the AVPN should catch this first */ DBG("%s: pte invalid\n", __func__); regs->gprs[3] = H_Not_Found; return; } lpte.bits.v = 0; /* ppte->words.vsid = lpte.words.vsid; */ asm volatile( "eieio; std %1, 0(%0); ptesync" : : "b" (ppte), "r" (0) : "memory"); pte_tlbie(&lpte, ptex); /* We never touch pp0, and PP bits in flags are in the right * order */ lpte.bits.pp1 = flags & (H_PP1 | H_PP2); lpte.bits.n = (flags & H_N) ? 1 : 0; lpte.bits.v = 1; lpte.bits.r = 0; asm volatile( "std %1, 8(%0); eieio; std %2, 0(%0); ptesync" : : "b" (ppte), "r" (lpte.words.rpn), "r" (lpte.words.vsid) : "memory"); regs->gprs[3] = H_Success;}static void h_clear_ref(struct cpu_user_regs *regs){ ulong ptex = regs->gprs[5]; struct vcpu *v = get_current(); struct domain *d = v->domain; struct domain_htab *htab = &d->arch.htab; union pte volatile *pte; union pte lpte; DBG_LOW("%s: flags: 0x%lx ptex: 0x%lx\n", __func__, regs->gprs[4], ptex);#ifdef DEBUG if (regs->gprs[4] != 0) { DBG("WARNING: %s: " "flags are undefined and should be 0: 0x%lx\n", __func__, regs->gprs[4]); }#endif if (ptex > (1UL << htab->log_num_ptes)) { DBG("%s: bad ptex: 0x%lx\n", __func__, ptex); regs->gprs[3] = H_Parameter; return; } pte = &htab->map[ptex]; lpte.words.rpn = pte->words.rpn; regs->gprs[4] = lpte.words.rpn; if (lpte.bits.r != 0) { lpte.bits.r = 0; asm volatile("std %1, 8(%0); eieio; ptesync" : : "b" (pte), "r" (lpte.words.rpn) : "memory"); pte_tlbie(&lpte, ptex); } regs->gprs[3] = H_Success;}static void h_clear_mod(struct cpu_user_regs *regs){ ulong ptex = regs->gprs[5]; struct vcpu *v = get_current(); struct domain *d = v->domain; struct domain_htab *htab = &d->arch.htab; union pte volatile *pte; union pte lpte; DBG_LOW("%s: flags: 0x%lx ptex: 0x%lx\n", __func__, regs->gprs[4], ptex);#ifdef DEBUG if (regs->gprs[4] != 0) { DBG("WARNING: %s: " "flags are undefined and should be 0: 0x%lx\n", __func__, regs->gprs[4]); }#endif if (ptex > (1UL << htab->log_num_ptes)) { DBG("%s: bad ptex: 0x%lx\n", __func__, ptex); regs->gprs[3] = H_Parameter; return; } pte = &htab->map[ptex]; lpte.words.vsid = pte->words.vsid; lpte.words.rpn = pte->words.rpn; regs->gprs[3] = H_Success; regs->gprs[4] = lpte.words.rpn; if (lpte.bits.c != 0) { /* invalidate */ asm volatile( "eieio; std %1, 0(%0); ptesync" : : "b" (pte), "r" (0) : "memory"); pte_tlbie(&lpte, ptex); lpte.bits.c = 0; asm volatile( "std %1, 8(%0); eieio; std %2, 0(%0); ptesync" : : "b" (pte), "r" (lpte.words.rpn), "r" (lpte.words.vsid) : "memory"); }}long pte_remove(ulong flags, ulong ptex, ulong avpn, ulong *hi, ulong *lo){ struct vcpu *v = get_current(); struct domain *d = v->domain; struct domain_htab *htab = &d->arch.htab; union pte volatile *pte; union pte lpte; DBG_LOW("%s: flags: 0x%lx ptex: 0x%lx avpn: 0x%lx\n", __func__, flags, ptex, avpn); if ( ptex > (1UL << htab->log_num_ptes) ) { DBG("%s: bad ptex: 0x%lx\n", __func__, ptex); return H_Parameter; } pte = &htab->map[ptex]; lpte.words.vsid = pte->words.vsid; lpte.words.rpn = pte->words.rpn; if ((flags & H_AVPN) && lpte.bits.avpn != (avpn >> 7)) { DBG_LOW("%s: AVPN does not match\n", __func__); return H_Not_Found; } if ((flags & H_ANDCOND) && ((avpn & pte->words.vsid) != 0)) { DBG("%s: andcond does not match\n", __func__); return H_Not_Found; } /* return old PTE in regs 4 and 5 */ *hi = lpte.words.vsid; *lo = lpte.words.rpn;#ifdef DEBUG_LOW /* XXX - I'm very skeptical of doing ANYTHING if not bits.v */ /* XXX - I think the spec should be questioned in this case (MFM) */ if (lpte.bits.v == 0) { DBG_LOW("%s: removing invalid entry\n", __func__); }#endif if (lpte.bits.v) { ulong mfn = lpte.bits.rpn; if (!platform_io_mfn(mfn)) { struct page_info *pg = mfn_to_page(mfn); struct domain *f = page_get_owner(pg); if (f != d) { put_domain(f); put_page(pg); } } } asm volatile("eieio; std %1, 0(%0); ptesync" : : "b" (pte), "r" (0) : "memory"); pte_tlbie(&lpte, ptex); return H_Success;}static void h_remove(struct cpu_user_regs *regs){ ulong flags = regs->gprs[4]; ulong ptex = regs->gprs[5]; ulong avpn = regs->gprs[6]; ulong hi, lo; long ret; ret = pte_remove(flags, ptex, avpn, &hi, &lo); regs->gprs[3] = ret; if (ret == H_Success) { regs->gprs[4] = hi; regs->gprs[5] = lo; } return;}static void h_read(struct cpu_user_regs *regs){ ulong flags = regs->gprs[4]; ulong ptex = regs->gprs[5]; struct vcpu *v = get_current(); struct domain *d = v->domain; struct domain_htab *htab = &d->arch.htab; union pte volatile *pte; if (flags & H_READ_4) ptex &= ~0x3UL; if (ptex > (1UL << htab->log_num_ptes)) { DBG("%s: bad ptex: 0x%lx\n", __func__, ptex); regs->gprs[3] = H_Parameter; return; } pte = &htab->map[ptex]; regs->gprs[4] = pte[0].words.vsid; regs->gprs[5] = pte[0].words.rpn; if (!(flags & H_READ_4)) { /* dump another 3 PTEs */ regs->gprs[6] = pte[1].words.vsid; regs->gprs[7] = pte[1].words.rpn; regs->gprs[8] = pte[2].words.vsid; regs->gprs[9] = pte[2].words.rpn; regs->gprs[10] = pte[3].words.vsid; regs->gprs[11] = pte[3].words.rpn; } regs->gprs[3] = H_Success;}__init_papr_hcall(H_ENTER, h_enter);__init_papr_hcall(H_READ, h_read);__init_papr_hcall(H_REMOVE, h_remove);__init_papr_hcall(H_CLEAR_MOD, h_clear_mod);__init_papr_hcall(H_CLEAR_REF, h_clear_ref);__init_papr_hcall(H_PROTECT, h_protect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -