@@ -45,6 +45,34 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
45
45
return 0 ;
46
46
}
47
47
48
+ static int ident_p4d_init (struct x86_mapping_info * info , p4d_t * p4d_page ,
49
+ unsigned long addr , unsigned long end )
50
+ {
51
+ unsigned long next ;
52
+
53
+ for (; addr < end ; addr = next ) {
54
+ p4d_t * p4d = p4d_page + p4d_index (addr );
55
+ pud_t * pud ;
56
+
57
+ next = (addr & P4D_MASK ) + P4D_SIZE ;
58
+ if (next > end )
59
+ next = end ;
60
+
61
+ if (p4d_present (* p4d )) {
62
+ pud = pud_offset (p4d , 0 );
63
+ ident_pud_init (info , pud , addr , next );
64
+ continue ;
65
+ }
66
+ pud = (pud_t * )info -> alloc_pgt_page (info -> context );
67
+ if (!pud )
68
+ return - ENOMEM ;
69
+ ident_pud_init (info , pud , addr , next );
70
+ set_p4d (p4d , __p4d (__pa (pud ) | _KERNPG_TABLE ));
71
+ }
72
+
73
+ return 0 ;
74
+ }
75
+
48
76
int kernel_ident_mapping_init (struct x86_mapping_info * info , pgd_t * pgd_page ,
49
77
unsigned long pstart , unsigned long pend )
50
78
{
@@ -55,27 +83,36 @@ int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
55
83
56
84
for (; addr < end ; addr = next ) {
57
85
pgd_t * pgd = pgd_page + pgd_index (addr );
58
- pud_t * pud ;
86
+ p4d_t * p4d ;
59
87
60
88
next = (addr & PGDIR_MASK ) + PGDIR_SIZE ;
61
89
if (next > end )
62
90
next = end ;
63
91
64
92
if (pgd_present (* pgd )) {
65
- pud = pud_offset (pgd , 0 );
66
- result = ident_pud_init (info , pud , addr , next );
93
+ p4d = p4d_offset (pgd , 0 );
94
+ result = ident_p4d_init (info , p4d , addr , next );
67
95
if (result )
68
96
return result ;
69
97
continue ;
70
98
}
71
99
72
- pud = (pud_t * )info -> alloc_pgt_page (info -> context );
73
- if (!pud )
100
+ p4d = (p4d_t * )info -> alloc_pgt_page (info -> context );
101
+ if (!p4d )
74
102
return - ENOMEM ;
75
- result = ident_pud_init (info , pud , addr , next );
103
+ result = ident_p4d_init (info , p4d , addr , next );
76
104
if (result )
77
105
return result ;
78
- set_pgd (pgd , __pgd (__pa (pud ) | _KERNPG_TABLE ));
106
+ if (IS_ENABLED (CONFIG_X86_5LEVEL )) {
107
+ set_pgd (pgd , __pgd (__pa (p4d ) | _KERNPG_TABLE ));
108
+ } else {
109
+ /*
110
+ * With p4d folded, pgd is equal to p4d.
111
+ * The pgd entry has to point to the pud page table in this case.
112
+ */
113
+ pud_t * pud = pud_offset (p4d , 0 );
114
+ set_pgd (pgd , __pgd (__pa (pud ) | _KERNPG_TABLE ));
115
+ }
79
116
}
80
117
81
118
return 0 ;
0 commit comments