pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t entry; int i; unsigned long nptes; entry = *ptep; if (pte_present(entry)) mm->context.huge_pte_count--; addr &= HPAGE_MASK; nptes = 1 << HUGETLB_PAGE_ORDER; for (i = 0; i < nptes; i++) { *ptep = __pte(0UL); addr += PAGE_SIZE; ptep++; } /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ addr -= REAL_HPAGE_SIZE; ptep -= nptes / 2; maybe_tlb_batch_add(mm, addr, ptep, entry, 0); addr -= REAL_HPAGE_SIZE; ptep -= nptes / 2; maybe_tlb_batch_add(mm, addr, ptep, entry, 0); return entry; }
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t entry) { unsigned int i, nptes, orig_shift, shift; unsigned long size; pte_t orig; size = huge_tte_to_size(entry); shift = size >= HPAGE_SIZE ? PMD_SHIFT : PAGE_SHIFT; nptes = size >> shift; if (!pte_present(*ptep) && pte_present(entry)) mm->context.hugetlb_pte_count += nptes; addr &= ~(size - 1); orig = *ptep; orig_shift = pte_none(orig) ? PAGE_SHIFT : huge_tte_to_shift(orig); for (i = 0; i < nptes; i++) ptep[i] = __pte(pte_val(entry) + (i << shift)); maybe_tlb_batch_add(mm, addr, ptep, orig, 0, orig_shift); /* An HPAGE_SIZE'ed page is composed of two REAL_HPAGE_SIZE'ed pages */ if (size == HPAGE_SIZE) maybe_tlb_batch_add(mm, addr + REAL_HPAGE_SIZE, ptep, orig, 0, orig_shift); }
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t entry) { int i; pte_t orig[2]; unsigned long nptes; if (!pte_present(*ptep) && pte_present(entry)) mm->context.huge_pte_count++; addr &= HPAGE_MASK; nptes = 1 << HUGETLB_PAGE_ORDER; orig[0] = *ptep; orig[1] = *(ptep + nptes / 2); for (i = 0; i < nptes; i++) { *ptep = entry; ptep++; addr += PAGE_SIZE; pte_val(entry) += PAGE_SIZE; } /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ addr -= REAL_HPAGE_SIZE; ptep -= nptes / 2; maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0); addr -= REAL_HPAGE_SIZE; ptep -= nptes / 2; maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0); }