Skip to content

Commit 25be68b

Browse files
committed
Merge: s390/mm: add support for UFFDIO_POISON
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6304 JIRA: https://issues.redhat.com/browse/RHEL-74362 These are complementary to commit 8a13897 (2097286 in RHEL) for s390x. Signed-off-by: Aristeu Rozanski <arozansk@redhat.com> Approved-by: Herton R. Krzesinski <herton@redhat.com> Approved-by: Thomas Huth <thuth@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Patrick Talbert <ptalbert@redhat.com>
2 parents 6e18394 + 8abcb48 commit 25be68b

File tree

6 files changed

+133
-39
lines changed

6 files changed

+133
-39
lines changed

arch/s390/include/asm/gmap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#define GMAP_NOTIFY_MPROT 0x1
1818

1919
/* Status bits only for huge segment entries */
20-
#define _SEGMENT_ENTRY_GMAP_IN 0x8000 /* invalidation notify bit */
21-
#define _SEGMENT_ENTRY_GMAP_UC 0x4000 /* dirty (migration) */
20+
#define _SEGMENT_ENTRY_GMAP_IN 0x0800 /* invalidation notify bit */
21+
#define _SEGMENT_ENTRY_GMAP_UC 0x0002 /* dirty (migration) */
2222

2323
/**
2424
* struct gmap_struct - guest address space

arch/s390/include/asm/hugetlb.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#define _ASM_S390_HUGETLB_H
1111

1212
#include <linux/pgtable.h>
13+
#include <linux/swap.h>
14+
#include <linux/swapops.h>
1315
#include <asm/page.h>
1416

1517
#define hugetlb_free_pgd_range free_pgd_range
@@ -91,7 +93,7 @@ static inline int huge_pte_none(pte_t pte)
9193

9294
static inline int huge_pte_none_mostly(pte_t pte)
9395
{
94-
return huge_pte_none(pte);
96+
return huge_pte_none(pte) || is_pte_marker(pte);
9597
}
9698

9799
static inline int huge_pte_write(pte_t pte)

arch/s390/include/asm/pgtable.h

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -259,24 +259,34 @@ static inline int is_module_addr(void *addr)
259259
#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID)
260260
#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
261261
#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID)
262-
#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
262+
#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH | \
263+
_REGION3_ENTRY_PRESENT)
263264
#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID)
264265

265266
#define _REGION3_ENTRY_ORIGIN_LARGE ~0x7fffffffUL /* large page address */
266267
#define _REGION3_ENTRY_DIRTY 0x2000 /* SW region dirty bit */
267268
#define _REGION3_ENTRY_YOUNG 0x1000 /* SW region young bit */
269+
#define _REGION3_ENTRY_COMM 0x0010 /* Common-Region, marks swap entry */
268270
#define _REGION3_ENTRY_LARGE 0x0400 /* RTTE-format control, large page */
269-
#define _REGION3_ENTRY_READ 0x0002 /* SW region read bit */
270-
#define _REGION3_ENTRY_WRITE 0x0001 /* SW region write bit */
271+
#define _REGION3_ENTRY_WRITE 0x8000 /* SW region write bit */
272+
#define _REGION3_ENTRY_READ 0x4000 /* SW region read bit */
271273

272274
#ifdef CONFIG_MEM_SOFT_DIRTY
273-
#define _REGION3_ENTRY_SOFT_DIRTY 0x4000 /* SW region soft dirty bit */
275+
#define _REGION3_ENTRY_SOFT_DIRTY 0x0002 /* SW region soft dirty bit */
274276
#else
275277
#define _REGION3_ENTRY_SOFT_DIRTY 0x0000 /* SW region soft dirty bit */
276278
#endif
277279

278280
#define _REGION_ENTRY_BITS 0xfffffffffffff22fUL
279281

282+
/*
283+
* SW region present bit. For non-leaf region-third-table entries, bits 62-63
284+
* indicate the TABLE LENGTH and both must be set to 1. But such entries
285+
* would always be considered as present, so it is safe to use bit 63 as
286+
* PRESENT bit for PUD.
287+
*/
288+
#define _REGION3_ENTRY_PRESENT 0x0001
289+
280290
/* Bits in the segment table entry */
281291
#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL
282292
#define _SEGMENT_ENTRY_HARDWARE_BITS 0xfffffffffffffe30UL
@@ -288,21 +298,29 @@ static inline int is_module_addr(void *addr)
288298
#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */
289299
#define _SEGMENT_ENTRY_TYPE_MASK 0x0c /* segment table type mask */
290300

291-
#define _SEGMENT_ENTRY (0)
301+
#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PRESENT)
292302
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID)
293303

294304
#define _SEGMENT_ENTRY_DIRTY 0x2000 /* SW segment dirty bit */
295305
#define _SEGMENT_ENTRY_YOUNG 0x1000 /* SW segment young bit */
306+
307+
#define _SEGMENT_ENTRY_COMM 0x0010 /* Common-Segment, marks swap entry */
296308
#define _SEGMENT_ENTRY_LARGE 0x0400 /* STE-format control, large page */
297-
#define _SEGMENT_ENTRY_WRITE 0x0002 /* SW segment write bit */
298-
#define _SEGMENT_ENTRY_READ 0x0001 /* SW segment read bit */
309+
#define _SEGMENT_ENTRY_WRITE 0x8000 /* SW segment write bit */
310+
#define _SEGMENT_ENTRY_READ 0x4000 /* SW segment read bit */
299311

300312
#ifdef CONFIG_MEM_SOFT_DIRTY
301-
#define _SEGMENT_ENTRY_SOFT_DIRTY 0x4000 /* SW segment soft dirty bit */
313+
#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0002 /* SW segment soft dirty bit */
302314
#else
303315
#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0000 /* SW segment soft dirty bit */
304316
#endif
305317

318+
#define _SEGMENT_ENTRY_PRESENT 0x0001 /* SW segment present bit */
319+
320+
/* Common bits in region and segment table entries, for swap entries */
321+
#define _RST_ENTRY_COMM 0x0010 /* Common-Region/Segment, marks swap entry */
322+
#define _RST_ENTRY_INVALID 0x0020 /* invalid region/segment table entry */
323+
306324
#define _CRST_ENTRIES 2048 /* number of region/segment table entries */
307325
#define _PAGE_ENTRIES 256 /* number of page table entries */
308326

@@ -434,17 +452,22 @@ static inline int is_module_addr(void *addr)
434452
/*
435453
* Segment entry (large page) protection definitions.
436454
*/
437-
#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \
455+
#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_PRESENT | \
456+
_SEGMENT_ENTRY_INVALID | \
438457
_SEGMENT_ENTRY_PROTECT)
439-
#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PROTECT | \
458+
#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PRESENT | \
459+
_SEGMENT_ENTRY_PROTECT | \
440460
_SEGMENT_ENTRY_READ | \
441461
_SEGMENT_ENTRY_NOEXEC)
442-
#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PROTECT | \
462+
#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PRESENT | \
463+
_SEGMENT_ENTRY_PROTECT | \
443464
_SEGMENT_ENTRY_READ)
444-
#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_READ | \
465+
#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_PRESENT | \
466+
_SEGMENT_ENTRY_READ | \
445467
_SEGMENT_ENTRY_WRITE | \
446468
_SEGMENT_ENTRY_NOEXEC)
447-
#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_READ | \
469+
#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_PRESENT | \
470+
_SEGMENT_ENTRY_READ | \
448471
_SEGMENT_ENTRY_WRITE)
449472
#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \
450473
_SEGMENT_ENTRY_LARGE | \
@@ -471,19 +494,22 @@ static inline int is_module_addr(void *addr)
471494
*/
472495

473496
#define REGION3_KERNEL __pgprot(_REGION_ENTRY_TYPE_R3 | \
497+
_REGION3_ENTRY_PRESENT | \
474498
_REGION3_ENTRY_LARGE | \
475499
_REGION3_ENTRY_READ | \
476500
_REGION3_ENTRY_WRITE | \
477501
_REGION3_ENTRY_YOUNG | \
478502
_REGION3_ENTRY_DIRTY | \
479503
_REGION_ENTRY_NOEXEC)
480504
#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
505+
_REGION3_ENTRY_PRESENT | \
481506
_REGION3_ENTRY_LARGE | \
482507
_REGION3_ENTRY_READ | \
483508
_REGION3_ENTRY_YOUNG | \
484509
_REGION_ENTRY_PROTECT | \
485510
_REGION_ENTRY_NOEXEC)
486511
#define REGION3_KERNEL_EXEC __pgprot(_REGION_ENTRY_TYPE_R3 | \
512+
_REGION3_ENTRY_PRESENT | \
487513
_REGION3_ENTRY_LARGE | \
488514
_REGION3_ENTRY_READ | \
489515
_REGION3_ENTRY_WRITE | \
@@ -705,7 +731,7 @@ static inline int pud_present(pud_t pud)
705731
{
706732
if (pud_folded(pud))
707733
return 1;
708-
return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL;
734+
return (pud_val(pud) & _REGION3_ENTRY_PRESENT) != 0;
709735
}
710736

711737
static inline int pud_none(pud_t pud)
@@ -720,13 +746,18 @@ static inline bool pud_leaf(pud_t pud)
720746
{
721747
if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
722748
return 0;
723-
return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
749+
return (pud_present(pud) && (pud_val(pud) & _REGION3_ENTRY_LARGE) != 0);
750+
}
751+
752+
static inline int pmd_present(pmd_t pmd)
753+
{
754+
return (pmd_val(pmd) & _SEGMENT_ENTRY_PRESENT) != 0;
724755
}
725756

726757
#define pmd_leaf pmd_leaf
727758
static inline bool pmd_leaf(pmd_t pmd)
728759
{
729-
return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
760+
return (pmd_present(pmd) && (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0);
730761
}
731762

732763
static inline int pmd_bad(pmd_t pmd)
@@ -758,11 +789,6 @@ static inline int p4d_bad(p4d_t p4d)
758789
return (p4d_val(p4d) & ~_REGION_ENTRY_BITS) != 0;
759790
}
760791

761-
static inline int pmd_present(pmd_t pmd)
762-
{
763-
return pmd_val(pmd) != _SEGMENT_ENTRY_EMPTY;
764-
}
765-
766792
static inline int pmd_none(pmd_t pmd)
767793
{
768794
return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY;
@@ -1807,7 +1833,7 @@ static inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
18071833

18081834
static inline int pmd_trans_huge(pmd_t pmd)
18091835
{
1810-
return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE;
1836+
return pmd_leaf(pmd);
18111837
}
18121838

18131839
#define has_transparent_hugepage has_transparent_hugepage
@@ -1867,6 +1893,53 @@ static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
18671893
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
18681894
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
18691895

1896+
/*
1897+
* 64 bit swap entry format for REGION3 and SEGMENT table entries (RSTE)
1898+
* Bits 59 and 63 are used to indicate the swap entry. Bit 58 marks the rste
1899+
* as invalid.
1900+
* A swap entry is indicated by bit pattern (rste & 0x011) == 0x010
1901+
* | offset |Xtype |11TT|S0|
1902+
* |0000000000111111111122222222223333333333444444444455|555555|5566|66|
1903+
* |0123456789012345678901234567890123456789012345678901|234567|8901|23|
1904+
*
1905+
* Bits 0-51 store the offset.
1906+
* Bits 53-57 store the type.
1907+
* Bit 62 (S) is used for softdirty tracking.
1908+
* Bits 60-61 (TT) indicate the table type: 0x01 for REGION3 and 0x00 for SEGMENT.
1909+
* Bit 52 (X) is unused.
1910+
*/
1911+
1912+
#define __SWP_OFFSET_MASK_RSTE ((1UL << 52) - 1)
1913+
#define __SWP_OFFSET_SHIFT_RSTE 12
1914+
#define __SWP_TYPE_MASK_RSTE ((1UL << 5) - 1)
1915+
#define __SWP_TYPE_SHIFT_RSTE 6
1916+
1917+
/*
1918+
* TT bits set to 0x00 == SEGMENT. For REGION3 entries, caller must add R3
1919+
* bits 0x01. See also __set_huge_pte_at().
1920+
*/
1921+
static inline unsigned long mk_swap_rste(unsigned long type, unsigned long offset)
1922+
{
1923+
unsigned long rste;
1924+
1925+
rste = _RST_ENTRY_INVALID | _RST_ENTRY_COMM;
1926+
rste |= (offset & __SWP_OFFSET_MASK_RSTE) << __SWP_OFFSET_SHIFT_RSTE;
1927+
rste |= (type & __SWP_TYPE_MASK_RSTE) << __SWP_TYPE_SHIFT_RSTE;
1928+
return rste;
1929+
}
1930+
1931+
static inline unsigned long __swp_type_rste(swp_entry_t entry)
1932+
{
1933+
return (entry.val >> __SWP_TYPE_SHIFT_RSTE) & __SWP_TYPE_MASK_RSTE;
1934+
}
1935+
1936+
static inline unsigned long __swp_offset_rste(swp_entry_t entry)
1937+
{
1938+
return (entry.val >> __SWP_OFFSET_SHIFT_RSTE) & __SWP_OFFSET_MASK_RSTE;
1939+
}
1940+
1941+
#define __rste_to_swp_entry(rste) ((swp_entry_t) { rste })
1942+
18701943
extern int vmem_add_mapping(unsigned long start, unsigned long size);
18711944
extern void vmem_remove_mapping(unsigned long start, unsigned long size);
18721945
extern int __vmem_map_4k_page(unsigned long addr, unsigned long phys, pgprot_t prot, bool alloc);

arch/s390/mm/fault.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,15 @@ static void do_fault_error(struct pt_regs *regs, vm_fault_t fault)
307307
do_no_context(regs);
308308
else
309309
do_sigsegv(regs, SEGV_MAPERR);
310-
} else if (fault & VM_FAULT_SIGBUS) {
310+
} else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON |
311+
VM_FAULT_HWPOISON_LARGE)) {
311312
/* Kernel mode? Handle exceptions or die */
312313
if (!user_mode(regs))
313314
do_no_context(regs);
314315
else
315316
do_sigbus(regs);
316317
} else {
318+
pr_emerg("Unexpected fault flags: %08x\n", fault);
317319
BUG();
318320
}
319321
break;

arch/s390/mm/gmap.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
616616
if (pmd_leaf(*pmd)) {
617617
*table = (pmd_val(*pmd) &
618618
_SEGMENT_ENTRY_HARDWARE_BITS_LARGE)
619-
| _SEGMENT_ENTRY_GMAP_UC;
619+
| _SEGMENT_ENTRY_GMAP_UC
620+
| _SEGMENT_ENTRY;
620621
} else
621622
*table = pmd_val(*pmd) &
622623
_SEGMENT_ENTRY_HARDWARE_BITS;
@@ -2345,7 +2346,8 @@ static void gmap_pmdp_clear(struct mm_struct *mm, unsigned long vmaddr,
23452346
gaddr = __gmap_segment_gaddr((unsigned long *)pmdp);
23462347
pmdp_notify_gmap(gmap, pmdp, gaddr);
23472348
WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
2348-
_SEGMENT_ENTRY_GMAP_UC));
2349+
_SEGMENT_ENTRY_GMAP_UC |
2350+
_SEGMENT_ENTRY));
23492351
if (purge)
23502352
__pmdp_csp(pmdp);
23512353
set_pmd(pmdp, __pmd(_SEGMENT_ENTRY_EMPTY));
@@ -2399,7 +2401,8 @@ void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr)
23992401
gaddr = __gmap_segment_gaddr(entry);
24002402
pmdp_notify_gmap(gmap, pmdp, gaddr);
24012403
WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
2402-
_SEGMENT_ENTRY_GMAP_UC));
2404+
_SEGMENT_ENTRY_GMAP_UC |
2405+
_SEGMENT_ENTRY));
24032406
if (MACHINE_HAS_TLB_GUEST)
24042407
__pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE,
24052408
gmap->asce, IDTE_LOCAL);
@@ -2434,7 +2437,8 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr)
24342437
gaddr = __gmap_segment_gaddr(entry);
24352438
pmdp_notify_gmap(gmap, pmdp, gaddr);
24362439
WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
2437-
_SEGMENT_ENTRY_GMAP_UC));
2440+
_SEGMENT_ENTRY_GMAP_UC |
2441+
_SEGMENT_ENTRY));
24382442
if (MACHINE_HAS_TLB_GUEST)
24392443
__pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE,
24402444
gmap->asce, IDTE_GLOBAL);

arch/s390/mm/hugetlbpage.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
static inline unsigned long __pte_to_rste(pte_t pte)
2626
{
27+
swp_entry_t arch_entry;
2728
unsigned long rste;
2829

2930
/*
@@ -48,6 +49,7 @@ static inline unsigned long __pte_to_rste(pte_t pte)
4849
*/
4950
if (pte_present(pte)) {
5051
rste = pte_val(pte) & PAGE_MASK;
52+
rste |= _SEGMENT_ENTRY_PRESENT;
5153
rste |= move_set_bit(pte_val(pte), _PAGE_READ,
5254
_SEGMENT_ENTRY_READ);
5355
rste |= move_set_bit(pte_val(pte), _PAGE_WRITE,
@@ -66,20 +68,29 @@ static inline unsigned long __pte_to_rste(pte_t pte)
6668
#endif
6769
rste |= move_set_bit(pte_val(pte), _PAGE_NOEXEC,
6870
_SEGMENT_ENTRY_NOEXEC);
71+
} else if (!pte_none(pte)) {
72+
/* swap pte */
73+
arch_entry = __pte_to_swp_entry(pte);
74+
rste = mk_swap_rste(__swp_type(arch_entry), __swp_offset(arch_entry));
6975
} else
7076
rste = _SEGMENT_ENTRY_EMPTY;
7177
return rste;
7278
}
7379

7480
static inline pte_t __rste_to_pte(unsigned long rste)
7581
{
82+
swp_entry_t arch_entry;
7683
unsigned long pteval;
77-
int present;
84+
int present, none;
85+
pte_t pte;
7886

79-
if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
87+
if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
8088
present = pud_present(__pud(rste));
81-
else
89+
none = pud_none(__pud(rste));
90+
} else {
8291
present = pmd_present(__pmd(rste));
92+
none = pmd_none(__pmd(rste));
93+
}
8394

8495
/*
8596
* Convert encoding pmd / pud bits pte bits
@@ -114,6 +125,11 @@ static inline pte_t __rste_to_pte(unsigned long rste)
114125
pteval |= move_set_bit(rste, _SEGMENT_ENTRY_SOFT_DIRTY, _PAGE_SOFT_DIRTY);
115126
#endif
116127
pteval |= move_set_bit(rste, _SEGMENT_ENTRY_NOEXEC, _PAGE_NOEXEC);
128+
} else if (!none) {
129+
/* swap rste */
130+
arch_entry = __rste_to_swp_entry(rste);
131+
pte = mk_swap_pte(__swp_type_rste(arch_entry), __swp_offset_rste(arch_entry));
132+
pteval = pte_val(pte);
117133
} else
118134
pteval = _PAGE_INVALID;
119135
return __pte(pteval);
@@ -148,8 +164,6 @@ void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
148164
unsigned long rste;
149165

150166
rste = __pte_to_rste(pte);
151-
if (!MACHINE_HAS_NX)
152-
rste &= ~_SEGMENT_ENTRY_NOEXEC;
153167

154168
/* Set correct table type for 2G hugepages */
155169
if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
@@ -223,11 +237,10 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
223237
p4dp = p4d_offset(pgdp, addr);
224238
if (p4d_present(*p4dp)) {
225239
pudp = pud_offset(p4dp, addr);
226-
if (pud_present(*pudp)) {
227-
if (pud_leaf(*pudp))
228-
return (pte_t *) pudp;
240+
if (sz == PUD_SIZE)
241+
return (pte_t *)pudp;
242+
if (pud_present(*pudp))
229243
pmdp = pmd_offset(pudp, addr);
230-
}
231244
}
232245
}
233246
return (pte_t *) pmdp;

0 commit comments

Comments
 (0)