0001
0002
0003
0004
0005
0006
0007 #include <linux/sched.h>
0008 #include <linux/kernel.h>
0009 #include <linux/errno.h>
0010 #include <linux/gfp.h>
0011 #include <linux/mm.h>
0012 #include <linux/swap.h>
0013 #include <linux/smp.h>
0014 #include <linux/spinlock.h>
0015 #include <linux/rcupdate.h>
0016 #include <linux/slab.h>
0017 #include <linux/swapops.h>
0018 #include <linux/sysctl.h>
0019 #include <linux/ksm.h>
0020 #include <linux/mman.h>
0021
0022 #include <asm/tlb.h>
0023 #include <asm/tlbflush.h>
0024 #include <asm/mmu_context.h>
0025 #include <asm/page-states.h>
0026
0027 pgprot_t pgprot_writecombine(pgprot_t prot)
0028 {
0029
0030
0031
0032
0033 return __pgprot(pgprot_val(prot) | mio_wb_bit_mask);
0034 }
0035 EXPORT_SYMBOL_GPL(pgprot_writecombine);
0036
0037 pgprot_t pgprot_writethrough(pgprot_t prot)
0038 {
0039
0040
0041
0042
0043 return __pgprot(pgprot_val(prot) & ~mio_wb_bit_mask);
0044 }
0045 EXPORT_SYMBOL_GPL(pgprot_writethrough);
0046
0047 static inline void ptep_ipte_local(struct mm_struct *mm, unsigned long addr,
0048 pte_t *ptep, int nodat)
0049 {
0050 unsigned long opt, asce;
0051
0052 if (MACHINE_HAS_TLB_GUEST) {
0053 opt = 0;
0054 asce = READ_ONCE(mm->context.gmap_asce);
0055 if (asce == 0UL || nodat)
0056 opt |= IPTE_NODAT;
0057 if (asce != -1UL) {
0058 asce = asce ? : mm->context.asce;
0059 opt |= IPTE_GUEST_ASCE;
0060 }
0061 __ptep_ipte(addr, ptep, opt, asce, IPTE_LOCAL);
0062 } else {
0063 __ptep_ipte(addr, ptep, 0, 0, IPTE_LOCAL);
0064 }
0065 }
0066
0067 static inline void ptep_ipte_global(struct mm_struct *mm, unsigned long addr,
0068 pte_t *ptep, int nodat)
0069 {
0070 unsigned long opt, asce;
0071
0072 if (MACHINE_HAS_TLB_GUEST) {
0073 opt = 0;
0074 asce = READ_ONCE(mm->context.gmap_asce);
0075 if (asce == 0UL || nodat)
0076 opt |= IPTE_NODAT;
0077 if (asce != -1UL) {
0078 asce = asce ? : mm->context.asce;
0079 opt |= IPTE_GUEST_ASCE;
0080 }
0081 __ptep_ipte(addr, ptep, opt, asce, IPTE_GLOBAL);
0082 } else {
0083 __ptep_ipte(addr, ptep, 0, 0, IPTE_GLOBAL);
0084 }
0085 }
0086
0087 static inline pte_t ptep_flush_direct(struct mm_struct *mm,
0088 unsigned long addr, pte_t *ptep,
0089 int nodat)
0090 {
0091 pte_t old;
0092
0093 old = *ptep;
0094 if (unlikely(pte_val(old) & _PAGE_INVALID))
0095 return old;
0096 atomic_inc(&mm->context.flush_count);
0097 if (MACHINE_HAS_TLB_LC &&
0098 cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
0099 ptep_ipte_local(mm, addr, ptep, nodat);
0100 else
0101 ptep_ipte_global(mm, addr, ptep, nodat);
0102 atomic_dec(&mm->context.flush_count);
0103 return old;
0104 }
0105
0106 static inline pte_t ptep_flush_lazy(struct mm_struct *mm,
0107 unsigned long addr, pte_t *ptep,
0108 int nodat)
0109 {
0110 pte_t old;
0111
0112 old = *ptep;
0113 if (unlikely(pte_val(old) & _PAGE_INVALID))
0114 return old;
0115 atomic_inc(&mm->context.flush_count);
0116 if (cpumask_equal(&mm->context.cpu_attach_mask,
0117 cpumask_of(smp_processor_id()))) {
0118 set_pte(ptep, set_pte_bit(*ptep, __pgprot(_PAGE_INVALID)));
0119 mm->context.flush_mm = 1;
0120 } else
0121 ptep_ipte_global(mm, addr, ptep, nodat);
0122 atomic_dec(&mm->context.flush_count);
0123 return old;
0124 }
0125
0126 static inline pgste_t pgste_get_lock(pte_t *ptep)
0127 {
0128 unsigned long new = 0;
0129 #ifdef CONFIG_PGSTE
0130 unsigned long old;
0131
0132 asm(
0133 " lg %0,%2\n"
0134 "0: lgr %1,%0\n"
0135 " nihh %0,0xff7f\n"
0136 " oihh %1,0x0080\n"
0137 " csg %0,%1,%2\n"
0138 " jl 0b\n"
0139 : "=&d" (old), "=&d" (new), "=Q" (ptep[PTRS_PER_PTE])
0140 : "Q" (ptep[PTRS_PER_PTE]) : "cc", "memory");
0141 #endif
0142 return __pgste(new);
0143 }
0144
0145 static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
0146 {
0147 #ifdef CONFIG_PGSTE
0148 asm(
0149 " nihh %1,0xff7f\n"
0150 " stg %1,%0\n"
0151 : "=Q" (ptep[PTRS_PER_PTE])
0152 : "d" (pgste_val(pgste)), "Q" (ptep[PTRS_PER_PTE])
0153 : "cc", "memory");
0154 #endif
0155 }
0156
0157 static inline pgste_t pgste_get(pte_t *ptep)
0158 {
0159 unsigned long pgste = 0;
0160 #ifdef CONFIG_PGSTE
0161 pgste = *(unsigned long *)(ptep + PTRS_PER_PTE);
0162 #endif
0163 return __pgste(pgste);
0164 }
0165
0166 static inline void pgste_set(pte_t *ptep, pgste_t pgste)
0167 {
0168 #ifdef CONFIG_PGSTE
0169 *(pgste_t *)(ptep + PTRS_PER_PTE) = pgste;
0170 #endif
0171 }
0172
0173 static inline pgste_t pgste_update_all(pte_t pte, pgste_t pgste,
0174 struct mm_struct *mm)
0175 {
0176 #ifdef CONFIG_PGSTE
0177 unsigned long address, bits, skey;
0178
0179 if (!mm_uses_skeys(mm) || pte_val(pte) & _PAGE_INVALID)
0180 return pgste;
0181 address = pte_val(pte) & PAGE_MASK;
0182 skey = (unsigned long) page_get_storage_key(address);
0183 bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
0184
0185 pgste_val(pgste) |= bits << 48;
0186
0187 pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT);
0188 pgste_val(pgste) |= (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
0189 #endif
0190 return pgste;
0191
0192 }
0193
0194 static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry,
0195 struct mm_struct *mm)
0196 {
0197 #ifdef CONFIG_PGSTE
0198 unsigned long address;
0199 unsigned long nkey;
0200
0201 if (!mm_uses_skeys(mm) || pte_val(entry) & _PAGE_INVALID)
0202 return;
0203 VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID));
0204 address = pte_val(entry) & PAGE_MASK;
0205
0206
0207
0208
0209
0210 nkey = (pgste_val(pgste) & (PGSTE_ACC_BITS | PGSTE_FP_BIT)) >> 56;
0211 nkey |= (pgste_val(pgste) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 48;
0212 page_set_storage_key(address, nkey, 0);
0213 #endif
0214 }
0215
0216 static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
0217 {
0218 #ifdef CONFIG_PGSTE
0219 if ((pte_val(entry) & _PAGE_PRESENT) &&
0220 (pte_val(entry) & _PAGE_WRITE) &&
0221 !(pte_val(entry) & _PAGE_INVALID)) {
0222 if (!MACHINE_HAS_ESOP) {
0223
0224
0225
0226
0227 entry = set_pte_bit(entry, __pgprot(_PAGE_DIRTY));
0228 entry = clear_pte_bit(entry, __pgprot(_PAGE_PROTECT));
0229 }
0230 if (!(pte_val(entry) & _PAGE_PROTECT))
0231
0232 pgste_val(pgste) |= PGSTE_UC_BIT;
0233 }
0234 #endif
0235 set_pte(ptep, entry);
0236 return pgste;
0237 }
0238
0239 static inline pgste_t pgste_pte_notify(struct mm_struct *mm,
0240 unsigned long addr,
0241 pte_t *ptep, pgste_t pgste)
0242 {
0243 #ifdef CONFIG_PGSTE
0244 unsigned long bits;
0245
0246 bits = pgste_val(pgste) & (PGSTE_IN_BIT | PGSTE_VSIE_BIT);
0247 if (bits) {
0248 pgste_val(pgste) ^= bits;
0249 ptep_notify(mm, addr, ptep, bits);
0250 }
0251 #endif
0252 return pgste;
0253 }
0254
0255 static inline pgste_t ptep_xchg_start(struct mm_struct *mm,
0256 unsigned long addr, pte_t *ptep)
0257 {
0258 pgste_t pgste = __pgste(0);
0259
0260 if (mm_has_pgste(mm)) {
0261 pgste = pgste_get_lock(ptep);
0262 pgste = pgste_pte_notify(mm, addr, ptep, pgste);
0263 }
0264 return pgste;
0265 }
0266
0267 static inline pte_t ptep_xchg_commit(struct mm_struct *mm,
0268 unsigned long addr, pte_t *ptep,
0269 pgste_t pgste, pte_t old, pte_t new)
0270 {
0271 if (mm_has_pgste(mm)) {
0272 if (pte_val(old) & _PAGE_INVALID)
0273 pgste_set_key(ptep, pgste, new, mm);
0274 if (pte_val(new) & _PAGE_INVALID) {
0275 pgste = pgste_update_all(old, pgste, mm);
0276 if ((pgste_val(pgste) & _PGSTE_GPS_USAGE_MASK) ==
0277 _PGSTE_GPS_USAGE_UNUSED)
0278 old = set_pte_bit(old, __pgprot(_PAGE_UNUSED));
0279 }
0280 pgste = pgste_set_pte(ptep, pgste, new);
0281 pgste_set_unlock(ptep, pgste);
0282 } else {
0283 set_pte(ptep, new);
0284 }
0285 return old;
0286 }
0287
0288 pte_t ptep_xchg_direct(struct mm_struct *mm, unsigned long addr,
0289 pte_t *ptep, pte_t new)
0290 {
0291 pgste_t pgste;
0292 pte_t old;
0293 int nodat;
0294
0295 preempt_disable();
0296 pgste = ptep_xchg_start(mm, addr, ptep);
0297 nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT);
0298 old = ptep_flush_direct(mm, addr, ptep, nodat);
0299 old = ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
0300 preempt_enable();
0301 return old;
0302 }
0303 EXPORT_SYMBOL(ptep_xchg_direct);
0304
0305 pte_t ptep_xchg_lazy(struct mm_struct *mm, unsigned long addr,
0306 pte_t *ptep, pte_t new)
0307 {
0308 pgste_t pgste;
0309 pte_t old;
0310 int nodat;
0311
0312 preempt_disable();
0313 pgste = ptep_xchg_start(mm, addr, ptep);
0314 nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT);
0315 old = ptep_flush_lazy(mm, addr, ptep, nodat);
0316 old = ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
0317 preempt_enable();
0318 return old;
0319 }
0320 EXPORT_SYMBOL(ptep_xchg_lazy);
0321
0322 pte_t ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr,
0323 pte_t *ptep)
0324 {
0325 pgste_t pgste;
0326 pte_t old;
0327 int nodat;
0328 struct mm_struct *mm = vma->vm_mm;
0329
0330 preempt_disable();
0331 pgste = ptep_xchg_start(mm, addr, ptep);
0332 nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT);
0333 old = ptep_flush_lazy(mm, addr, ptep, nodat);
0334 if (mm_has_pgste(mm)) {
0335 pgste = pgste_update_all(old, pgste, mm);
0336 pgste_set(ptep, pgste);
0337 }
0338 return old;
0339 }
0340
0341 void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr,
0342 pte_t *ptep, pte_t old_pte, pte_t pte)
0343 {
0344 pgste_t pgste;
0345 struct mm_struct *mm = vma->vm_mm;
0346
0347 if (!MACHINE_HAS_NX)
0348 pte = clear_pte_bit(pte, __pgprot(_PAGE_NOEXEC));
0349 if (mm_has_pgste(mm)) {
0350 pgste = pgste_get(ptep);
0351 pgste_set_key(ptep, pgste, pte, mm);
0352 pgste = pgste_set_pte(ptep, pgste, pte);
0353 pgste_set_unlock(ptep, pgste);
0354 } else {
0355 set_pte(ptep, pte);
0356 }
0357 preempt_enable();
0358 }
0359
0360 static inline void pmdp_idte_local(struct mm_struct *mm,
0361 unsigned long addr, pmd_t *pmdp)
0362 {
0363 if (MACHINE_HAS_TLB_GUEST)
0364 __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE,
0365 mm->context.asce, IDTE_LOCAL);
0366 else
0367 __pmdp_idte(addr, pmdp, 0, 0, IDTE_LOCAL);
0368 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
0369 gmap_pmdp_idte_local(mm, addr);
0370 }
0371
0372 static inline void pmdp_idte_global(struct mm_struct *mm,
0373 unsigned long addr, pmd_t *pmdp)
0374 {
0375 if (MACHINE_HAS_TLB_GUEST) {
0376 __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE,
0377 mm->context.asce, IDTE_GLOBAL);
0378 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
0379 gmap_pmdp_idte_global(mm, addr);
0380 } else if (MACHINE_HAS_IDTE) {
0381 __pmdp_idte(addr, pmdp, 0, 0, IDTE_GLOBAL);
0382 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
0383 gmap_pmdp_idte_global(mm, addr);
0384 } else {
0385 __pmdp_csp(pmdp);
0386 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
0387 gmap_pmdp_csp(mm, addr);
0388 }
0389 }
0390
0391 static inline pmd_t pmdp_flush_direct(struct mm_struct *mm,
0392 unsigned long addr, pmd_t *pmdp)
0393 {
0394 pmd_t old;
0395
0396 old = *pmdp;
0397 if (pmd_val(old) & _SEGMENT_ENTRY_INVALID)
0398 return old;
0399 atomic_inc(&mm->context.flush_count);
0400 if (MACHINE_HAS_TLB_LC &&
0401 cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
0402 pmdp_idte_local(mm, addr, pmdp);
0403 else
0404 pmdp_idte_global(mm, addr, pmdp);
0405 atomic_dec(&mm->context.flush_count);
0406 return old;
0407 }
0408
0409 static inline pmd_t pmdp_flush_lazy(struct mm_struct *mm,
0410 unsigned long addr, pmd_t *pmdp)
0411 {
0412 pmd_t old;
0413
0414 old = *pmdp;
0415 if (pmd_val(old) & _SEGMENT_ENTRY_INVALID)
0416 return old;
0417 atomic_inc(&mm->context.flush_count);
0418 if (cpumask_equal(&mm->context.cpu_attach_mask,
0419 cpumask_of(smp_processor_id()))) {
0420 set_pmd(pmdp, set_pmd_bit(*pmdp, __pgprot(_SEGMENT_ENTRY_INVALID)));
0421 mm->context.flush_mm = 1;
0422 if (mm_has_pgste(mm))
0423 gmap_pmdp_invalidate(mm, addr);
0424 } else {
0425 pmdp_idte_global(mm, addr, pmdp);
0426 }
0427 atomic_dec(&mm->context.flush_count);
0428 return old;
0429 }
0430
0431 #ifdef CONFIG_PGSTE
0432 static int pmd_lookup(struct mm_struct *mm, unsigned long addr, pmd_t **pmdp)
0433 {
0434 struct vm_area_struct *vma;
0435 pgd_t *pgd;
0436 p4d_t *p4d;
0437 pud_t *pud;
0438
0439
0440 vma = vma_lookup(mm, addr);
0441 if (!vma)
0442 return -EFAULT;
0443
0444 pgd = pgd_offset(mm, addr);
0445 if (!pgd_present(*pgd))
0446 return -ENOENT;
0447
0448 p4d = p4d_offset(pgd, addr);
0449 if (!p4d_present(*p4d))
0450 return -ENOENT;
0451
0452 pud = pud_offset(p4d, addr);
0453 if (!pud_present(*pud))
0454 return -ENOENT;
0455
0456
0457 if (pud_large(*pud))
0458 return -EFAULT;
0459
0460 *pmdp = pmd_offset(pud, addr);
0461 return 0;
0462 }
0463 #endif
0464
0465 pmd_t pmdp_xchg_direct(struct mm_struct *mm, unsigned long addr,
0466 pmd_t *pmdp, pmd_t new)
0467 {
0468 pmd_t old;
0469
0470 preempt_disable();
0471 old = pmdp_flush_direct(mm, addr, pmdp);
0472 set_pmd(pmdp, new);
0473 preempt_enable();
0474 return old;
0475 }
0476 EXPORT_SYMBOL(pmdp_xchg_direct);
0477
0478 pmd_t pmdp_xchg_lazy(struct mm_struct *mm, unsigned long addr,
0479 pmd_t *pmdp, pmd_t new)
0480 {
0481 pmd_t old;
0482
0483 preempt_disable();
0484 old = pmdp_flush_lazy(mm, addr, pmdp);
0485 set_pmd(pmdp, new);
0486 preempt_enable();
0487 return old;
0488 }
0489 EXPORT_SYMBOL(pmdp_xchg_lazy);
0490
0491 static inline void pudp_idte_local(struct mm_struct *mm,
0492 unsigned long addr, pud_t *pudp)
0493 {
0494 if (MACHINE_HAS_TLB_GUEST)
0495 __pudp_idte(addr, pudp, IDTE_NODAT | IDTE_GUEST_ASCE,
0496 mm->context.asce, IDTE_LOCAL);
0497 else
0498 __pudp_idte(addr, pudp, 0, 0, IDTE_LOCAL);
0499 }
0500
0501 static inline void pudp_idte_global(struct mm_struct *mm,
0502 unsigned long addr, pud_t *pudp)
0503 {
0504 if (MACHINE_HAS_TLB_GUEST)
0505 __pudp_idte(addr, pudp, IDTE_NODAT | IDTE_GUEST_ASCE,
0506 mm->context.asce, IDTE_GLOBAL);
0507 else if (MACHINE_HAS_IDTE)
0508 __pudp_idte(addr, pudp, 0, 0, IDTE_GLOBAL);
0509 else
0510
0511
0512
0513
0514 __pmdp_csp((pmd_t *) pudp);
0515 }
0516
0517 static inline pud_t pudp_flush_direct(struct mm_struct *mm,
0518 unsigned long addr, pud_t *pudp)
0519 {
0520 pud_t old;
0521
0522 old = *pudp;
0523 if (pud_val(old) & _REGION_ENTRY_INVALID)
0524 return old;
0525 atomic_inc(&mm->context.flush_count);
0526 if (MACHINE_HAS_TLB_LC &&
0527 cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
0528 pudp_idte_local(mm, addr, pudp);
0529 else
0530 pudp_idte_global(mm, addr, pudp);
0531 atomic_dec(&mm->context.flush_count);
0532 return old;
0533 }
0534
0535 pud_t pudp_xchg_direct(struct mm_struct *mm, unsigned long addr,
0536 pud_t *pudp, pud_t new)
0537 {
0538 pud_t old;
0539
0540 preempt_disable();
0541 old = pudp_flush_direct(mm, addr, pudp);
0542 set_pud(pudp, new);
0543 preempt_enable();
0544 return old;
0545 }
0546 EXPORT_SYMBOL(pudp_xchg_direct);
0547
0548 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
0549 void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
0550 pgtable_t pgtable)
0551 {
0552 struct list_head *lh = (struct list_head *) pgtable;
0553
0554 assert_spin_locked(pmd_lockptr(mm, pmdp));
0555
0556
0557 if (!pmd_huge_pte(mm, pmdp))
0558 INIT_LIST_HEAD(lh);
0559 else
0560 list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp));
0561 pmd_huge_pte(mm, pmdp) = pgtable;
0562 }
0563
0564 pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
0565 {
0566 struct list_head *lh;
0567 pgtable_t pgtable;
0568 pte_t *ptep;
0569
0570 assert_spin_locked(pmd_lockptr(mm, pmdp));
0571
0572
0573 pgtable = pmd_huge_pte(mm, pmdp);
0574 lh = (struct list_head *) pgtable;
0575 if (list_empty(lh))
0576 pmd_huge_pte(mm, pmdp) = NULL;
0577 else {
0578 pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;
0579 list_del(lh);
0580 }
0581 ptep = (pte_t *) pgtable;
0582 set_pte(ptep, __pte(_PAGE_INVALID));
0583 ptep++;
0584 set_pte(ptep, __pte(_PAGE_INVALID));
0585 return pgtable;
0586 }
0587 #endif
0588
0589 #ifdef CONFIG_PGSTE
0590 void ptep_set_pte_at(struct mm_struct *mm, unsigned long addr,
0591 pte_t *ptep, pte_t entry)
0592 {
0593 pgste_t pgste;
0594
0595
0596 preempt_disable();
0597 pgste = pgste_get_lock(ptep);
0598 pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
0599 pgste_set_key(ptep, pgste, entry, mm);
0600 pgste = pgste_set_pte(ptep, pgste, entry);
0601 pgste_set_unlock(ptep, pgste);
0602 preempt_enable();
0603 }
0604
0605 void ptep_set_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
0606 {
0607 pgste_t pgste;
0608
0609 preempt_disable();
0610 pgste = pgste_get_lock(ptep);
0611 pgste_val(pgste) |= PGSTE_IN_BIT;
0612 pgste_set_unlock(ptep, pgste);
0613 preempt_enable();
0614 }
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 int ptep_force_prot(struct mm_struct *mm, unsigned long addr,
0628 pte_t *ptep, int prot, unsigned long bit)
0629 {
0630 pte_t entry;
0631 pgste_t pgste;
0632 int pte_i, pte_p, nodat;
0633
0634 pgste = pgste_get_lock(ptep);
0635 entry = *ptep;
0636
0637 pte_i = pte_val(entry) & _PAGE_INVALID;
0638 pte_p = pte_val(entry) & _PAGE_PROTECT;
0639 if ((pte_i && (prot != PROT_NONE)) ||
0640 (pte_p && (prot & PROT_WRITE))) {
0641 pgste_set_unlock(ptep, pgste);
0642 return -EAGAIN;
0643 }
0644
0645 nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT);
0646 if (prot == PROT_NONE && !pte_i) {
0647 ptep_flush_direct(mm, addr, ptep, nodat);
0648 pgste = pgste_update_all(entry, pgste, mm);
0649 entry = set_pte_bit(entry, __pgprot(_PAGE_INVALID));
0650 }
0651 if (prot == PROT_READ && !pte_p) {
0652 ptep_flush_direct(mm, addr, ptep, nodat);
0653 entry = clear_pte_bit(entry, __pgprot(_PAGE_INVALID));
0654 entry = set_pte_bit(entry, __pgprot(_PAGE_PROTECT));
0655 }
0656 pgste_val(pgste) |= bit;
0657 pgste = pgste_set_pte(ptep, pgste, entry);
0658 pgste_set_unlock(ptep, pgste);
0659 return 0;
0660 }
0661
0662 int ptep_shadow_pte(struct mm_struct *mm, unsigned long saddr,
0663 pte_t *sptep, pte_t *tptep, pte_t pte)
0664 {
0665 pgste_t spgste, tpgste;
0666 pte_t spte, tpte;
0667 int rc = -EAGAIN;
0668
0669 if (!(pte_val(*tptep) & _PAGE_INVALID))
0670 return 0;
0671 spgste = pgste_get_lock(sptep);
0672 spte = *sptep;
0673 if (!(pte_val(spte) & _PAGE_INVALID) &&
0674 !((pte_val(spte) & _PAGE_PROTECT) &&
0675 !(pte_val(pte) & _PAGE_PROTECT))) {
0676 pgste_val(spgste) |= PGSTE_VSIE_BIT;
0677 tpgste = pgste_get_lock(tptep);
0678 tpte = __pte((pte_val(spte) & PAGE_MASK) |
0679 (pte_val(pte) & _PAGE_PROTECT));
0680
0681 tpgste = pgste_set_pte(tptep, tpgste, tpte);
0682 pgste_set_unlock(tptep, tpgste);
0683 rc = 1;
0684 }
0685 pgste_set_unlock(sptep, spgste);
0686 return rc;
0687 }
0688
0689 void ptep_unshadow_pte(struct mm_struct *mm, unsigned long saddr, pte_t *ptep)
0690 {
0691 pgste_t pgste;
0692 int nodat;
0693
0694 pgste = pgste_get_lock(ptep);
0695
0696 nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT);
0697 ptep_flush_direct(mm, saddr, ptep, nodat);
0698
0699 pgste = pgste_set_pte(ptep, pgste, __pte(_PAGE_INVALID));
0700 pgste_set_unlock(ptep, pgste);
0701 }
0702
0703 static void ptep_zap_swap_entry(struct mm_struct *mm, swp_entry_t entry)
0704 {
0705 if (!non_swap_entry(entry))
0706 dec_mm_counter(mm, MM_SWAPENTS);
0707 else if (is_migration_entry(entry)) {
0708 struct page *page = pfn_swap_entry_to_page(entry);
0709
0710 dec_mm_counter(mm, mm_counter(page));
0711 }
0712 free_swap_and_cache(entry);
0713 }
0714
0715 void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
0716 pte_t *ptep, int reset)
0717 {
0718 unsigned long pgstev;
0719 pgste_t pgste;
0720 pte_t pte;
0721
0722
0723 preempt_disable();
0724 pgste = pgste_get_lock(ptep);
0725 pgstev = pgste_val(pgste);
0726 pte = *ptep;
0727 if (!reset && pte_swap(pte) &&
0728 ((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED ||
0729 (pgstev & _PGSTE_GPS_ZERO))) {
0730 ptep_zap_swap_entry(mm, pte_to_swp_entry(pte));
0731 pte_clear(mm, addr, ptep);
0732 }
0733 if (reset)
0734 pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
0735 pgste_set_unlock(ptep, pgste);
0736 preempt_enable();
0737 }
0738
0739 void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
0740 {
0741 unsigned long ptev;
0742 pgste_t pgste;
0743
0744
0745 preempt_disable();
0746 pgste = pgste_get_lock(ptep);
0747 pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT);
0748 pgste_val(pgste) |= PGSTE_GR_BIT | PGSTE_GC_BIT;
0749 ptev = pte_val(*ptep);
0750 if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE))
0751 page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 0);
0752 pgste_set_unlock(ptep, pgste);
0753 preempt_enable();
0754 }
0755
0756
0757
0758
0759 bool ptep_test_and_clear_uc(struct mm_struct *mm, unsigned long addr,
0760 pte_t *ptep)
0761 {
0762 pgste_t pgste;
0763 pte_t pte;
0764 bool dirty;
0765 int nodat;
0766
0767 pgste = pgste_get_lock(ptep);
0768 dirty = !!(pgste_val(pgste) & PGSTE_UC_BIT);
0769 pgste_val(pgste) &= ~PGSTE_UC_BIT;
0770 pte = *ptep;
0771 if (dirty && (pte_val(pte) & _PAGE_PRESENT)) {
0772 pgste = pgste_pte_notify(mm, addr, ptep, pgste);
0773 nodat = !!(pgste_val(pgste) & _PGSTE_GPS_NODAT);
0774 ptep_ipte_global(mm, addr, ptep, nodat);
0775 if (MACHINE_HAS_ESOP || !(pte_val(pte) & _PAGE_WRITE))
0776 pte = set_pte_bit(pte, __pgprot(_PAGE_PROTECT));
0777 else
0778 pte = set_pte_bit(pte, __pgprot(_PAGE_INVALID));
0779 set_pte(ptep, pte);
0780 }
0781 pgste_set_unlock(ptep, pgste);
0782 return dirty;
0783 }
0784 EXPORT_SYMBOL_GPL(ptep_test_and_clear_uc);
0785
0786 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
0787 unsigned char key, bool nq)
0788 {
0789 unsigned long keyul, paddr;
0790 spinlock_t *ptl;
0791 pgste_t old, new;
0792 pmd_t *pmdp;
0793 pte_t *ptep;
0794
0795
0796
0797
0798
0799 switch (pmd_lookup(mm, addr, &pmdp)) {
0800 case -ENOENT:
0801 return key ? -EFAULT : 0;
0802 case 0:
0803 break;
0804 default:
0805 return -EFAULT;
0806 }
0807
0808 ptl = pmd_lock(mm, pmdp);
0809 if (!pmd_present(*pmdp)) {
0810 spin_unlock(ptl);
0811 return key ? -EFAULT : 0;
0812 }
0813
0814 if (pmd_large(*pmdp)) {
0815 paddr = pmd_val(*pmdp) & HPAGE_MASK;
0816 paddr |= addr & ~HPAGE_MASK;
0817
0818
0819
0820
0821 page_set_storage_key(paddr, key, 1);
0822 spin_unlock(ptl);
0823 return 0;
0824 }
0825 spin_unlock(ptl);
0826
0827 ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
0828 new = old = pgste_get_lock(ptep);
0829 pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
0830 PGSTE_ACC_BITS | PGSTE_FP_BIT);
0831 keyul = (unsigned long) key;
0832 pgste_val(new) |= (keyul & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48;
0833 pgste_val(new) |= (keyul & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
0834 if (!(pte_val(*ptep) & _PAGE_INVALID)) {
0835 unsigned long bits, skey;
0836
0837 paddr = pte_val(*ptep) & PAGE_MASK;
0838 skey = (unsigned long) page_get_storage_key(paddr);
0839 bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
0840 skey = key & (_PAGE_ACC_BITS | _PAGE_FP_BIT);
0841
0842 page_set_storage_key(paddr, skey, !nq);
0843
0844 pgste_val(new) |= bits << 52;
0845 }
0846
0847 if ((pgste_val(new) ^ pgste_val(old)) &
0848 (PGSTE_ACC_BITS | PGSTE_FP_BIT | PGSTE_GR_BIT | PGSTE_GC_BIT))
0849 pgste_val(new) |= PGSTE_UC_BIT;
0850
0851 pgste_set_unlock(ptep, new);
0852 pte_unmap_unlock(ptep, ptl);
0853 return 0;
0854 }
0855 EXPORT_SYMBOL(set_guest_storage_key);
0856
0857
0858
0859
0860
0861
0862
0863
0864 int cond_set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
0865 unsigned char key, unsigned char *oldkey,
0866 bool nq, bool mr, bool mc)
0867 {
0868 unsigned char tmp, mask = _PAGE_ACC_BITS | _PAGE_FP_BIT;
0869 int rc;
0870
0871
0872 if (mr | mc) {
0873 rc = get_guest_storage_key(current->mm, addr, &tmp);
0874 if (rc)
0875 return rc;
0876 if (oldkey)
0877 *oldkey = tmp;
0878 if (!mr)
0879 mask |= _PAGE_REFERENCED;
0880 if (!mc)
0881 mask |= _PAGE_CHANGED;
0882 if (!((tmp ^ key) & mask))
0883 return 0;
0884 }
0885 rc = set_guest_storage_key(current->mm, addr, key, nq);
0886 return rc < 0 ? rc : 1;
0887 }
0888 EXPORT_SYMBOL(cond_set_guest_storage_key);
0889
0890
0891
0892
0893
0894
0895 int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr)
0896 {
0897 spinlock_t *ptl;
0898 unsigned long paddr;
0899 pgste_t old, new;
0900 pmd_t *pmdp;
0901 pte_t *ptep;
0902 int cc = 0;
0903
0904
0905
0906
0907
0908 switch (pmd_lookup(mm, addr, &pmdp)) {
0909 case -ENOENT:
0910 return 0;
0911 case 0:
0912 break;
0913 default:
0914 return -EFAULT;
0915 }
0916
0917 ptl = pmd_lock(mm, pmdp);
0918 if (!pmd_present(*pmdp)) {
0919 spin_unlock(ptl);
0920 return 0;
0921 }
0922
0923 if (pmd_large(*pmdp)) {
0924 paddr = pmd_val(*pmdp) & HPAGE_MASK;
0925 paddr |= addr & ~HPAGE_MASK;
0926 cc = page_reset_referenced(paddr);
0927 spin_unlock(ptl);
0928 return cc;
0929 }
0930 spin_unlock(ptl);
0931
0932 ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
0933 new = old = pgste_get_lock(ptep);
0934
0935 pgste_val(new) &= ~PGSTE_GR_BIT;
0936
0937 if (!(pte_val(*ptep) & _PAGE_INVALID)) {
0938 paddr = pte_val(*ptep) & PAGE_MASK;
0939 cc = page_reset_referenced(paddr);
0940
0941 pgste_val(new) |= ((unsigned long) cc << 53) & PGSTE_HR_BIT;
0942 }
0943
0944 cc |= (pgste_val(old) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 49;
0945
0946 if ((pgste_val(new) ^ pgste_val(old)) & PGSTE_GR_BIT)
0947 pgste_val(new) |= PGSTE_UC_BIT;
0948
0949 pgste_set_unlock(ptep, new);
0950 pte_unmap_unlock(ptep, ptl);
0951 return cc;
0952 }
0953 EXPORT_SYMBOL(reset_guest_reference_bit);
0954
0955 int get_guest_storage_key(struct mm_struct *mm, unsigned long addr,
0956 unsigned char *key)
0957 {
0958 unsigned long paddr;
0959 spinlock_t *ptl;
0960 pgste_t pgste;
0961 pmd_t *pmdp;
0962 pte_t *ptep;
0963
0964
0965
0966
0967
0968 *key = 0;
0969
0970 switch (pmd_lookup(mm, addr, &pmdp)) {
0971 case -ENOENT:
0972 return 0;
0973 case 0:
0974 break;
0975 default:
0976 return -EFAULT;
0977 }
0978
0979 ptl = pmd_lock(mm, pmdp);
0980 if (!pmd_present(*pmdp)) {
0981 spin_unlock(ptl);
0982 return 0;
0983 }
0984
0985 if (pmd_large(*pmdp)) {
0986 paddr = pmd_val(*pmdp) & HPAGE_MASK;
0987 paddr |= addr & ~HPAGE_MASK;
0988 *key = page_get_storage_key(paddr);
0989 spin_unlock(ptl);
0990 return 0;
0991 }
0992 spin_unlock(ptl);
0993
0994 ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
0995 pgste = pgste_get_lock(ptep);
0996 *key = (pgste_val(pgste) & (PGSTE_ACC_BITS | PGSTE_FP_BIT)) >> 56;
0997 paddr = pte_val(*ptep) & PAGE_MASK;
0998 if (!(pte_val(*ptep) & _PAGE_INVALID))
0999 *key = page_get_storage_key(paddr);
1000
1001 *key |= (pgste_val(pgste) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 48;
1002 pgste_set_unlock(ptep, pgste);
1003 pte_unmap_unlock(ptep, ptl);
1004 return 0;
1005 }
1006 EXPORT_SYMBOL(get_guest_storage_key);
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc,
1021 unsigned long *oldpte, unsigned long *oldpgste)
1022 {
1023 struct vm_area_struct *vma;
1024 unsigned long pgstev;
1025 spinlock_t *ptl;
1026 pgste_t pgste;
1027 pte_t *ptep;
1028 int res = 0;
1029
1030 WARN_ON_ONCE(orc > ESSA_MAX);
1031 if (unlikely(orc > ESSA_MAX))
1032 return -EINVAL;
1033
1034 vma = vma_lookup(mm, hva);
1035 if (!vma || is_vm_hugetlb_page(vma))
1036 return -EFAULT;
1037 ptep = get_locked_pte(mm, hva, &ptl);
1038 if (unlikely(!ptep))
1039 return -EFAULT;
1040 pgste = pgste_get_lock(ptep);
1041 pgstev = pgste_val(pgste);
1042 if (oldpte)
1043 *oldpte = pte_val(*ptep);
1044 if (oldpgste)
1045 *oldpgste = pgstev;
1046
1047 switch (orc) {
1048 case ESSA_GET_STATE:
1049 break;
1050 case ESSA_SET_STABLE:
1051 pgstev &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT);
1052 pgstev |= _PGSTE_GPS_USAGE_STABLE;
1053 break;
1054 case ESSA_SET_UNUSED:
1055 pgstev &= ~_PGSTE_GPS_USAGE_MASK;
1056 pgstev |= _PGSTE_GPS_USAGE_UNUSED;
1057 if (pte_val(*ptep) & _PAGE_INVALID)
1058 res = 1;
1059 break;
1060 case ESSA_SET_VOLATILE:
1061 pgstev &= ~_PGSTE_GPS_USAGE_MASK;
1062 pgstev |= _PGSTE_GPS_USAGE_VOLATILE;
1063 if (pte_val(*ptep) & _PAGE_INVALID)
1064 res = 1;
1065 break;
1066 case ESSA_SET_POT_VOLATILE:
1067 pgstev &= ~_PGSTE_GPS_USAGE_MASK;
1068 if (!(pte_val(*ptep) & _PAGE_INVALID)) {
1069 pgstev |= _PGSTE_GPS_USAGE_POT_VOLATILE;
1070 break;
1071 }
1072 if (pgstev & _PGSTE_GPS_ZERO) {
1073 pgstev |= _PGSTE_GPS_USAGE_VOLATILE;
1074 break;
1075 }
1076 if (!(pgstev & PGSTE_GC_BIT)) {
1077 pgstev |= _PGSTE_GPS_USAGE_VOLATILE;
1078 res = 1;
1079 break;
1080 }
1081 break;
1082 case ESSA_SET_STABLE_RESIDENT:
1083 pgstev &= ~_PGSTE_GPS_USAGE_MASK;
1084 pgstev |= _PGSTE_GPS_USAGE_STABLE;
1085
1086
1087
1088
1089
1090 break;
1091 case ESSA_SET_STABLE_IF_RESIDENT:
1092 if (!(pte_val(*ptep) & _PAGE_INVALID)) {
1093 pgstev &= ~_PGSTE_GPS_USAGE_MASK;
1094 pgstev |= _PGSTE_GPS_USAGE_STABLE;
1095 }
1096 break;
1097 case ESSA_SET_STABLE_NODAT:
1098 pgstev &= ~_PGSTE_GPS_USAGE_MASK;
1099 pgstev |= _PGSTE_GPS_USAGE_STABLE | _PGSTE_GPS_NODAT;
1100 break;
1101 default:
1102
1103 break;
1104 }
1105
1106 if (res)
1107 pgstev |= _PGSTE_GPS_ZERO;
1108
1109 pgste_val(pgste) = pgstev;
1110 pgste_set_unlock(ptep, pgste);
1111 pte_unmap_unlock(ptep, ptl);
1112 return res;
1113 }
1114 EXPORT_SYMBOL(pgste_perform_essa);
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126 int set_pgste_bits(struct mm_struct *mm, unsigned long hva,
1127 unsigned long bits, unsigned long value)
1128 {
1129 struct vm_area_struct *vma;
1130 spinlock_t *ptl;
1131 pgste_t new;
1132 pte_t *ptep;
1133
1134 vma = vma_lookup(mm, hva);
1135 if (!vma || is_vm_hugetlb_page(vma))
1136 return -EFAULT;
1137 ptep = get_locked_pte(mm, hva, &ptl);
1138 if (unlikely(!ptep))
1139 return -EFAULT;
1140 new = pgste_get_lock(ptep);
1141
1142 pgste_val(new) &= ~bits;
1143 pgste_val(new) |= value & bits;
1144
1145 pgste_set_unlock(ptep, new);
1146 pte_unmap_unlock(ptep, ptl);
1147 return 0;
1148 }
1149 EXPORT_SYMBOL(set_pgste_bits);
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159 int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep)
1160 {
1161 struct vm_area_struct *vma;
1162 spinlock_t *ptl;
1163 pte_t *ptep;
1164
1165 vma = vma_lookup(mm, hva);
1166 if (!vma || is_vm_hugetlb_page(vma))
1167 return -EFAULT;
1168 ptep = get_locked_pte(mm, hva, &ptl);
1169 if (unlikely(!ptep))
1170 return -EFAULT;
1171 *pgstep = pgste_val(pgste_get(ptep));
1172 pte_unmap_unlock(ptep, ptl);
1173 return 0;
1174 }
1175 EXPORT_SYMBOL(get_pgste);
1176 #endif