diff options
-rw-r--r-- | arch/powerpc/include/asm/pgtable.h | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/eeh.c | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/io-workarounds.c | 10 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rm_mmu.c | 30 | ||||
-rw-r--r-- | arch/powerpc/kvm/e500_mmu_host.c | 14 | ||||
-rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 22 | ||||
-rw-r--r-- | arch/powerpc/perf/callchain.c | 24 |
9 files changed, 88 insertions, 36 deletions
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 92fe01c355a9..11a38635dd65 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
@@ -247,8 +247,17 @@ extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, | |||
247 | #define pmd_large(pmd) 0 | 247 | #define pmd_large(pmd) 0 |
248 | #define has_transparent_hugepage() 0 | 248 | #define has_transparent_hugepage() 0 |
249 | #endif | 249 | #endif |
250 | pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, | 250 | pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, |
251 | unsigned *shift); | 251 | unsigned *shift); |
252 | static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, | ||
253 | unsigned *shift) | ||
254 | { | ||
255 | if (!arch_irqs_disabled()) { | ||
256 | pr_info("%s called with irq enabled\n", __func__); | ||
257 | dump_stack(); | ||
258 | } | ||
259 | return __find_linux_pte_or_hugepte(pgdir, ea, shift); | ||
260 | } | ||
252 | #endif /* __ASSEMBLY__ */ | 261 | #endif /* __ASSEMBLY__ */ |
253 | 262 | ||
254 | #endif /* __KERNEL__ */ | 263 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index a4c62eb0ee48..44b480e3a5af 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -334,9 +334,11 @@ static inline unsigned long eeh_token_to_phys(unsigned long token) | |||
334 | int hugepage_shift; | 334 | int hugepage_shift; |
335 | 335 | ||
336 | /* | 336 | /* |
337 | * We won't find hugepages here, iomem | 337 | * We won't find hugepages here(this is iomem). Hence we are not |
338 | * worried about _PAGE_SPLITTING/collapse. Also we will not hit | ||
339 | * page table free, because of init_mm. | ||
338 | */ | 340 | */ |
339 | ptep = find_linux_pte_or_hugepte(init_mm.pgd, token, &hugepage_shift); | 341 | ptep = __find_linux_pte_or_hugepte(init_mm.pgd, token, &hugepage_shift); |
340 | if (!ptep) | 342 | if (!ptep) |
341 | return token; | 343 | return token; |
342 | WARN_ON(hugepage_shift); | 344 | WARN_ON(hugepage_shift); |
diff --git a/arch/powerpc/kernel/io-workarounds.c b/arch/powerpc/kernel/io-workarounds.c index 24b968f8e4d8..63d9cc4d7366 100644 --- a/arch/powerpc/kernel/io-workarounds.c +++ b/arch/powerpc/kernel/io-workarounds.c | |||
@@ -71,15 +71,15 @@ struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr) | |||
71 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | 71 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); |
72 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) | 72 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) |
73 | return NULL; | 73 | return NULL; |
74 | 74 | /* | |
75 | ptep = find_linux_pte_or_hugepte(init_mm.pgd, vaddr, | 75 | * We won't find huge pages here (iomem). Also can't hit |
76 | * a page table free due to init_mm | ||
77 | */ | ||
78 | ptep = __find_linux_pte_or_hugepte(init_mm.pgd, vaddr, | ||
76 | &hugepage_shift); | 79 | &hugepage_shift); |
77 | if (ptep == NULL) | 80 | if (ptep == NULL) |
78 | paddr = 0; | 81 | paddr = 0; |
79 | else { | 82 | else { |
80 | /* | ||
81 | * we don't have hugepages backing iomem | ||
82 | */ | ||
83 | WARN_ON(hugepage_shift); | 83 | WARN_ON(hugepage_shift); |
84 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | 84 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; |
85 | } | 85 | } |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 534acb3c6c3d..26df3864d85a 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -539,12 +539,13 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
539 | if (!writing && hpte_is_writable(r)) { | 539 | if (!writing && hpte_is_writable(r)) { |
540 | unsigned int hugepage_shift; | 540 | unsigned int hugepage_shift; |
541 | pte_t *ptep, pte; | 541 | pte_t *ptep, pte; |
542 | unsigned long flags; | ||
542 | 543 | ||
543 | /* | 544 | /* |
544 | * We need to protect against page table destruction | 545 | * We need to protect against page table destruction |
545 | * while looking up and updating the pte. | 546 | * while looking up and updating the pte. |
546 | */ | 547 | */ |
547 | rcu_read_lock_sched(); | 548 | local_irq_save(flags); |
548 | ptep = find_linux_pte_or_hugepte(current->mm->pgd, | 549 | ptep = find_linux_pte_or_hugepte(current->mm->pgd, |
549 | hva, &hugepage_shift); | 550 | hva, &hugepage_shift); |
550 | if (ptep) { | 551 | if (ptep) { |
@@ -553,7 +554,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
553 | if (pte_write(pte)) | 554 | if (pte_write(pte)) |
554 | write_ok = 1; | 555 | write_ok = 1; |
555 | } | 556 | } |
556 | rcu_read_unlock_sched(); | 557 | local_irq_restore(flags); |
557 | } | 558 | } |
558 | } | 559 | } |
559 | 560 | ||
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 73e083cb9f7e..f559b25de173 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -26,11 +26,14 @@ static void *real_vmalloc_addr(void *x) | |||
26 | { | 26 | { |
27 | unsigned long addr = (unsigned long) x; | 27 | unsigned long addr = (unsigned long) x; |
28 | pte_t *p; | 28 | pte_t *p; |
29 | 29 | /* | |
30 | p = find_linux_pte_or_hugepte(swapper_pg_dir, addr, NULL); | 30 | * assume we don't have huge pages in vmalloc space... |
31 | * So don't worry about THP collapse/split. Called | ||
32 | * Only in realmode, hence won't need irq_save/restore. | ||
33 | */ | ||
34 | p = __find_linux_pte_or_hugepte(swapper_pg_dir, addr, NULL); | ||
31 | if (!p || !pte_present(*p)) | 35 | if (!p || !pte_present(*p)) |
32 | return NULL; | 36 | return NULL; |
33 | /* assume we don't have huge pages in vmalloc space... */ | ||
34 | addr = (pte_pfn(*p) << PAGE_SHIFT) | (addr & ~PAGE_MASK); | 37 | addr = (pte_pfn(*p) << PAGE_SHIFT) | (addr & ~PAGE_MASK); |
35 | return __va(addr); | 38 | return __va(addr); |
36 | } | 39 | } |
@@ -153,7 +156,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
153 | pte_t *ptep; | 156 | pte_t *ptep; |
154 | unsigned int writing; | 157 | unsigned int writing; |
155 | unsigned long mmu_seq; | 158 | unsigned long mmu_seq; |
156 | unsigned long rcbits; | 159 | unsigned long rcbits, irq_flags = 0; |
157 | 160 | ||
158 | psize = hpte_page_size(pteh, ptel); | 161 | psize = hpte_page_size(pteh, ptel); |
159 | if (!psize) | 162 | if (!psize) |
@@ -189,7 +192,16 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
189 | 192 | ||
190 | /* Translate to host virtual address */ | 193 | /* Translate to host virtual address */ |
191 | hva = __gfn_to_hva_memslot(memslot, gfn); | 194 | hva = __gfn_to_hva_memslot(memslot, gfn); |
192 | ptep = find_linux_pte_or_hugepte(pgdir, hva, &hpage_shift); | 195 | /* |
196 | * If we had a page table table change after lookup, we would | ||
197 | * retry via mmu_notifier_retry. | ||
198 | */ | ||
199 | if (realmode) | ||
200 | ptep = __find_linux_pte_or_hugepte(pgdir, hva, &hpage_shift); | ||
201 | else { | ||
202 | local_irq_save(irq_flags); | ||
203 | ptep = find_linux_pte_or_hugepte(pgdir, hva, &hpage_shift); | ||
204 | } | ||
193 | if (ptep) { | 205 | if (ptep) { |
194 | pte_t pte; | 206 | pte_t pte; |
195 | unsigned int host_pte_size; | 207 | unsigned int host_pte_size; |
@@ -202,9 +214,11 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
202 | * We should always find the guest page size | 214 | * We should always find the guest page size |
203 | * to <= host page size, if host is using hugepage | 215 | * to <= host page size, if host is using hugepage |
204 | */ | 216 | */ |
205 | if (host_pte_size < psize) | 217 | if (host_pte_size < psize) { |
218 | if (!realmode) | ||
219 | local_irq_restore(flags); | ||
206 | return H_PARAMETER; | 220 | return H_PARAMETER; |
207 | 221 | } | |
208 | pte = kvmppc_read_update_linux_pte(ptep, writing, hpage_shift); | 222 | pte = kvmppc_read_update_linux_pte(ptep, writing, hpage_shift); |
209 | if (pte_present(pte) && !pte_protnone(pte)) { | 223 | if (pte_present(pte) && !pte_protnone(pte)) { |
210 | if (writing && !pte_write(pte)) | 224 | if (writing && !pte_write(pte)) |
@@ -216,6 +230,8 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
216 | pa |= gpa & ~PAGE_MASK; | 230 | pa |= gpa & ~PAGE_MASK; |
217 | } | 231 | } |
218 | } | 232 | } |
233 | if (!realmode) | ||
234 | local_irq_restore(irq_flags); | ||
219 | 235 | ||
220 | ptel &= ~(HPTE_R_PP0 - psize); | 236 | ptel &= ~(HPTE_R_PP0 - psize); |
221 | ptel |= pa; | 237 | ptel |= pa; |
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index a1f5b0d4b1d6..4d33e199edcc 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c | |||
@@ -338,6 +338,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
338 | pte_t *ptep; | 338 | pte_t *ptep; |
339 | unsigned int wimg = 0; | 339 | unsigned int wimg = 0; |
340 | pgd_t *pgdir; | 340 | pgd_t *pgdir; |
341 | unsigned long flags; | ||
341 | 342 | ||
342 | /* used to check for invalidations in progress */ | 343 | /* used to check for invalidations in progress */ |
343 | mmu_seq = kvm->mmu_notifier_seq; | 344 | mmu_seq = kvm->mmu_notifier_seq; |
@@ -468,14 +469,23 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
468 | 469 | ||
469 | 470 | ||
470 | pgdir = vcpu_e500->vcpu.arch.pgdir; | 471 | pgdir = vcpu_e500->vcpu.arch.pgdir; |
472 | /* | ||
473 | * We are just looking at the wimg bits, so we don't | ||
474 | * care much about the trans splitting bit. | ||
475 | * We are holding kvm->mmu_lock so a notifier invalidate | ||
476 | * can't run hence pfn won't change. | ||
477 | */ | ||
478 | local_irq_save(flags); | ||
471 | ptep = find_linux_pte_or_hugepte(pgdir, hva, NULL); | 479 | ptep = find_linux_pte_or_hugepte(pgdir, hva, NULL); |
472 | if (ptep) { | 480 | if (ptep) { |
473 | pte_t pte = READ_ONCE(*ptep); | 481 | pte_t pte = READ_ONCE(*ptep); |
474 | 482 | ||
475 | if (pte_present(pte)) | 483 | if (pte_present(pte)) { |
476 | wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) & | 484 | wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) & |
477 | MAS2_WIMGE_MASK; | 485 | MAS2_WIMGE_MASK; |
478 | else { | 486 | local_irq_restore(flags); |
487 | } else { | ||
488 | local_irq_restore(flags); | ||
479 | pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n", | 489 | pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n", |
480 | __func__, (long)gfn, pfn); | 490 | __func__, (long)gfn, pfn); |
481 | ret = -EINVAL; | 491 | ret = -EINVAL; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 2c2022d16059..444f7a5b859b 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -1066,7 +1066,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, | |||
1066 | #endif /* CONFIG_PPC_64K_PAGES */ | 1066 | #endif /* CONFIG_PPC_64K_PAGES */ |
1067 | 1067 | ||
1068 | /* Get PTE and page size from page tables */ | 1068 | /* Get PTE and page size from page tables */ |
1069 | ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift); | 1069 | ptep = __find_linux_pte_or_hugepte(pgdir, ea, &hugeshift); |
1070 | if (ptep == NULL || !pte_present(*ptep)) { | 1070 | if (ptep == NULL || !pte_present(*ptep)) { |
1071 | DBG_LOW(" no PTE !\n"); | 1071 | DBG_LOW(" no PTE !\n"); |
1072 | rc = 1; | 1072 | rc = 1; |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 2cb278a2f658..a9dbb27ca887 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -109,7 +109,7 @@ int pgd_huge(pgd_t pgd) | |||
109 | pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) | 109 | pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) |
110 | { | 110 | { |
111 | /* Only called for hugetlbfs pages, hence can ignore THP */ | 111 | /* Only called for hugetlbfs pages, hence can ignore THP */ |
112 | return find_linux_pte_or_hugepte(mm->pgd, addr, NULL); | 112 | return __find_linux_pte_or_hugepte(mm->pgd, addr, NULL); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | 115 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, |
@@ -682,28 +682,35 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, | |||
682 | } while (addr = next, addr != end); | 682 | } while (addr = next, addr != end); |
683 | } | 683 | } |
684 | 684 | ||
685 | /* | ||
686 | * We are holding mmap_sem, so a parallel huge page collapse cannot run. | ||
687 | * To prevent hugepage split, disable irq. | ||
688 | */ | ||
685 | struct page * | 689 | struct page * |
686 | follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) | 690 | follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) |
687 | { | 691 | { |
688 | pte_t *ptep; | 692 | pte_t *ptep; |
689 | struct page *page; | 693 | struct page *page; |
690 | unsigned shift; | 694 | unsigned shift; |
691 | unsigned long mask; | 695 | unsigned long mask, flags; |
692 | /* | 696 | /* |
693 | * Transparent hugepages are handled by generic code. We can skip them | 697 | * Transparent hugepages are handled by generic code. We can skip them |
694 | * here. | 698 | * here. |
695 | */ | 699 | */ |
700 | local_irq_save(flags); | ||
696 | ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); | 701 | ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); |
697 | 702 | ||
698 | /* Verify it is a huge page else bail. */ | 703 | /* Verify it is a huge page else bail. */ |
699 | if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) | 704 | if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) { |
705 | local_irq_restore(flags); | ||
700 | return ERR_PTR(-EINVAL); | 706 | return ERR_PTR(-EINVAL); |
701 | 707 | } | |
702 | mask = (1UL << shift) - 1; | 708 | mask = (1UL << shift) - 1; |
703 | page = pte_page(*ptep); | 709 | page = pte_page(*ptep); |
704 | if (page) | 710 | if (page) |
705 | page += (address & mask) / PAGE_SIZE; | 711 | page += (address & mask) / PAGE_SIZE; |
706 | 712 | ||
713 | local_irq_restore(flags); | ||
707 | return page; | 714 | return page; |
708 | } | 715 | } |
709 | 716 | ||
@@ -950,9 +957,12 @@ void flush_dcache_icache_hugepage(struct page *page) | |||
950 | * | 957 | * |
951 | * So long as we atomically load page table pointers we are safe against teardown, | 958 | * So long as we atomically load page table pointers we are safe against teardown, |
952 | * we can follow the address down to the the page and take a ref on it. | 959 | * we can follow the address down to the the page and take a ref on it. |
960 | * This function need to be called with interrupts disabled. We use this variant | ||
961 | * when we have MSR[EE] = 0 but the paca->soft_enabled = 1 | ||
953 | */ | 962 | */ |
954 | 963 | ||
955 | pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift) | 964 | pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, |
965 | unsigned *shift) | ||
956 | { | 966 | { |
957 | pgd_t pgd, *pgdp; | 967 | pgd_t pgd, *pgdp; |
958 | pud_t pud, *pudp; | 968 | pud_t pud, *pudp; |
@@ -1031,7 +1041,7 @@ out: | |||
1031 | *shift = pdshift; | 1041 | *shift = pdshift; |
1032 | return ret_pte; | 1042 | return ret_pte; |
1033 | } | 1043 | } |
1034 | EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte); | 1044 | EXPORT_SYMBOL_GPL(__find_linux_pte_or_hugepte); |
1035 | 1045 | ||
1036 | int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, | 1046 | int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, |
1037 | unsigned long end, int write, struct page **pages, int *nr) | 1047 | unsigned long end, int write, struct page **pages, int *nr) |
diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index ead55351b254..ff09cde20cd2 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c | |||
@@ -111,41 +111,45 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
111 | * interrupt context, so if the access faults, we read the page tables | 111 | * interrupt context, so if the access faults, we read the page tables |
112 | * to find which page (if any) is mapped and access it directly. | 112 | * to find which page (if any) is mapped and access it directly. |
113 | */ | 113 | */ |
114 | static int read_user_stack_slow(void __user *ptr, void *ret, int nb) | 114 | static int read_user_stack_slow(void __user *ptr, void *buf, int nb) |
115 | { | 115 | { |
116 | int ret = -EFAULT; | ||
116 | pgd_t *pgdir; | 117 | pgd_t *pgdir; |
117 | pte_t *ptep, pte; | 118 | pte_t *ptep, pte; |
118 | unsigned shift; | 119 | unsigned shift; |
119 | unsigned long addr = (unsigned long) ptr; | 120 | unsigned long addr = (unsigned long) ptr; |
120 | unsigned long offset; | 121 | unsigned long offset; |
121 | unsigned long pfn; | 122 | unsigned long pfn, flags; |
122 | void *kaddr; | 123 | void *kaddr; |
123 | 124 | ||
124 | pgdir = current->mm->pgd; | 125 | pgdir = current->mm->pgd; |
125 | if (!pgdir) | 126 | if (!pgdir) |
126 | return -EFAULT; | 127 | return -EFAULT; |
127 | 128 | ||
129 | local_irq_save(flags); | ||
128 | ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift); | 130 | ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift); |
131 | if (!ptep) | ||
132 | goto err_out; | ||
129 | if (!shift) | 133 | if (!shift) |
130 | shift = PAGE_SHIFT; | 134 | shift = PAGE_SHIFT; |
131 | 135 | ||
132 | /* align address to page boundary */ | 136 | /* align address to page boundary */ |
133 | offset = addr & ((1UL << shift) - 1); | 137 | offset = addr & ((1UL << shift) - 1); |
134 | addr -= offset; | ||
135 | 138 | ||
136 | if (ptep == NULL) | 139 | pte = READ_ONCE(*ptep); |
137 | return -EFAULT; | ||
138 | pte = *ptep; | ||
139 | if (!pte_present(pte) || !(pte_val(pte) & _PAGE_USER)) | 140 | if (!pte_present(pte) || !(pte_val(pte) & _PAGE_USER)) |
140 | return -EFAULT; | 141 | goto err_out; |
141 | pfn = pte_pfn(pte); | 142 | pfn = pte_pfn(pte); |
142 | if (!page_is_ram(pfn)) | 143 | if (!page_is_ram(pfn)) |
143 | return -EFAULT; | 144 | goto err_out; |
144 | 145 | ||
145 | /* no highmem to worry about here */ | 146 | /* no highmem to worry about here */ |
146 | kaddr = pfn_to_kaddr(pfn); | 147 | kaddr = pfn_to_kaddr(pfn); |
147 | memcpy(ret, kaddr + offset, nb); | 148 | memcpy(buf, kaddr + offset, nb); |
148 | return 0; | 149 | ret = 0; |
150 | err_out: | ||
151 | local_irq_restore(flags); | ||
152 | return ret; | ||
149 | } | 153 | } |
150 | 154 | ||
151 | static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) | 155 | static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) |