Initialize Tizen 2.3
[external/prelink.git] / src / arch-sparc.c
1 /* Copyright (C) 2001, 2002, 2004, 2009 Red Hat, Inc.
2    Written by Jakub Jelinek <jakub@redhat.com>, 2001.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #include <config.h>
19 #include <assert.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <locale.h>
25 #include <error.h>
26 #include <argp.h>
27 #include <stdlib.h>
28
29 #include "prelink.h"
30
31 static int
32 sparc_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
33                   GElf_Addr adjust)
34 {
35   if (dyn->d_tag == DT_PLTGOT)
36     {
37       int i;
38
39       for (i = 1; i < dso->ehdr.e_shnum; ++i)
40         if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
41                               dso->shdr[i].sh_name), ".got"))
42           {
43             Elf32_Addr data;
44
45             data = read_ube32 (dso, dso->shdr[i].sh_addr);
46             /* .got[0] points to _DYNAMIC, it needs to be adjusted.  */
47             if (data == dso->shdr[n].sh_addr && data >= start)
48               write_be32 (dso, dso->shdr[i].sh_addr, data + adjust);
49             break;
50           }
51     }
52
53   return 0;
54 }
55
56 static int
57 sparc_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
58                   GElf_Addr adjust)
59 {
60   error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename);
61   return 1;
62 }
63
64 static int
65 sparc_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
66                    GElf_Addr adjust)
67 {
68   if (GELF_R_TYPE (rela->r_info) == R_SPARC_RELATIVE)
69     {
70       if (rela->r_addend)
71         {
72           if ((Elf32_Addr) rela->r_addend >= start)
73             rela->r_addend += (Elf32_Sword) adjust;
74         }
75       else
76         {
77           GElf_Addr val = read_ube32 (dso, rela->r_offset);
78
79           if (val >= start)
80             write_be32 (dso, rela->r_offset, val + adjust);
81         }
82     }
83   return 0;
84 }
85
86 static int
87 sparc_prelink_rel (struct prelink_info *info, GElf_Rel *rel,
88                    GElf_Addr reladdr)
89 {
90   error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename);
91   return 1;
92 }
93
94 static void
95 sparc_fixup_plt (DSO *dso, GElf_Rela *rela, GElf_Addr value)
96 {
97   Elf32_Sword disp = value - rela->r_offset;
98
99   if (disp >= -0x800000 && disp < 0x800000)
100     {
101       /* b,a value
102           nop
103          nop  */
104       write_be32 (dso, rela->r_offset, 0x30800000 | ((disp >> 2) & 0x3fffff));
105       write_be32 (dso, rela->r_offset + 4, 0x01000000);
106       write_be32 (dso, rela->r_offset + 8, 0x01000000);
107     }
108   else
109     {
110       /* sethi %hi(value), %g1
111          jmpl %g1 + %lo(value), %g0
112           nop  */
113       write_be32 (dso, rela->r_offset, 0x03000000 | ((value >> 10) & 0x3fffff));
114       write_be32 (dso, rela->r_offset + 4, 0x81c06000 | (value & 0x3ff));
115       write_be32 (dso, rela->r_offset + 8, 0x01000000);
116     }
117 }
118
119 static int
120 sparc_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
121                     GElf_Addr relaaddr)
122 {
123   DSO *dso = info->dso;
124   GElf_Addr value;
125
126   if (GELF_R_TYPE (rela->r_info) == R_SPARC_NONE)
127     return 0;
128   else if (GELF_R_TYPE (rela->r_info) == R_SPARC_RELATIVE)
129     {
130       /* 32-bit SPARC handles RELATIVE relocs as
131          *(int *)rela->r_offset += l_addr + rela->r_addend.
132          RELATIVE relocs against .got traditionally used to have the
133          addend in memory pointed by r_offset and 0 r_addend,
134          other RELATIVE relocs and more recent .got RELATIVE relocs
135          too have 0 in memory and non-zero r_addend.  For prelinking,
136          we need the value in memory to be already relocated for
137          l_addr == 0 case, so we have to make sure r_addend will be 0.  */
138       if (rela->r_addend == 0)
139         return 0;
140       value = read_ube32 (dso, rela->r_offset);
141       value += rela->r_addend;
142       rela->r_addend = 0;
143       write_be32 (dso, rela->r_offset, value);
144       /* Tell prelink_rela routine it should update the relocation.  */
145       return 2;
146     }
147   value = info->resolve (info, GELF_R_SYM (rela->r_info),
148                          GELF_R_TYPE (rela->r_info));
149   value += rela->r_addend;
150   switch (GELF_R_TYPE (rela->r_info))
151     {
152     case R_SPARC_GLOB_DAT:
153     case R_SPARC_32:
154     case R_SPARC_UA32:
155       write_be32 (dso, rela->r_offset, value);
156       break;
157     case R_SPARC_JMP_SLOT:
158       sparc_fixup_plt (dso, rela, value);
159       break;
160     case R_SPARC_8:
161       write_8 (dso, rela->r_offset, value);
162       break;
163     case R_SPARC_16:
164     case R_SPARC_UA16:
165       write_be16 (dso, rela->r_offset, value);
166       break;
167     case R_SPARC_LO10:
168       write_be32 (dso, rela->r_offset,
169                   (value & 0x3ff) | (read_ube32 (dso, rela->r_offset) & ~0x3ff));
170       break;
171     case R_SPARC_HI22:
172       write_be32 (dso, rela->r_offset,
173                   ((value >> 10) & 0x3fffff)
174                   | (read_ube32 (dso, rela->r_offset) & 0xffc00000));
175       break;
176     case R_SPARC_DISP8:
177       write_8 (dso, rela->r_offset, value - rela->r_offset);
178       break;
179     case R_SPARC_DISP16:
180       write_be16 (dso, rela->r_offset, value - rela->r_offset);
181       break;
182     case R_SPARC_DISP32:
183       write_be32 (dso, rela->r_offset, value - rela->r_offset);
184       break;
185     case R_SPARC_WDISP30:
186       write_be32 (dso, rela->r_offset,
187                   (((value - rela->r_offset) >> 2) & 0x3fffffff)
188                   | (read_ube32 (dso, rela->r_offset) & 0xc0000000));
189       break;
190     case R_SPARC_TLS_DTPOFF32:
191       write_be32 (dso, rela->r_offset, value + rela->r_addend);
192       break;
193     /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries
194        unless prelink sets the rules.  */
195     case R_SPARC_TLS_DTPMOD32:
196       if (dso->ehdr.e_type == ET_EXEC)
197         {
198           error (0, 0, "%s: R_SPARC_TLS_DTPMOD32 reloc in executable?",
199                  dso->filename);
200           return 1;
201         }
202       break;
203     case R_SPARC_TLS_TPOFF32:
204       if (dso->ehdr.e_type == ET_EXEC && info->resolvetls)
205         write_be32 (dso, rela->r_offset,
206                     value + rela->r_addend - info->resolvetls->offset);
207       break;
208     case R_SPARC_TLS_LE_HIX22:
209       if (dso->ehdr.e_type == ET_EXEC && info->resolvetls)
210         write_be32 (dso, rela->r_offset,
211                     (read_ube32 (dso, rela->r_offset) & 0xffc00000)
212                     | (((~(value + rela->r_addend - info->resolvetls->offset))
213                         >> 10) & 0x3fffff));
214       break;
215     case R_SPARC_TLS_LE_LOX10:
216       if (dso->ehdr.e_type == ET_EXEC && info->resolvetls)
217         write_be32 (dso, rela->r_offset,
218                     (read_ube32 (dso, rela->r_offset) & 0xffffe000) | 0x1c00
219                     | ((value + rela->r_addend - info->resolvetls->offset)
220                        & 0x3ff));
221       break;
222     case R_SPARC_COPY:
223       if (dso->ehdr.e_type == ET_EXEC)
224         /* COPY relocs are handled specially in generic code.  */
225         return 0;
226       error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename);
227       return 1;
228     default:
229       error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename,
230              (int) GELF_R_TYPE (rela->r_info));
231       return 1;
232     }
233   return 0;
234 }
235
236 static int
237 sparc_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
238                            char *buf, GElf_Addr dest_addr)
239 {
240   switch (GELF_R_TYPE (rela->r_info))
241     {
242     case R_SPARC_32:
243     case R_SPARC_UA32:
244       buf_write_be32 (buf, rela->r_addend);
245       break;
246     case R_SPARC_16:
247     case R_SPARC_UA16:
248       buf_write_be16 (buf, rela->r_addend);
249       break;
250     case R_SPARC_8:
251       buf_write_8 (buf, rela->r_addend);
252       break;
253     default:
254       abort ();
255     }
256   return 0;
257 }
258
259 static int
260 sparc_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
261 {
262   error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename);
263   return 1;
264 }
265
266 static int
267 sparc_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
268 {
269   GElf_Addr value;
270
271   value = info->resolve (info, GELF_R_SYM (rela->r_info),
272                          GELF_R_TYPE (rela->r_info));
273   value += rela->r_addend;
274   switch (GELF_R_TYPE (rela->r_info))
275     {
276     case R_SPARC_NONE:
277       break;
278     case R_SPARC_DISP32:
279       value -= rela->r_offset;
280     case R_SPARC_GLOB_DAT:
281     case R_SPARC_32:
282     case R_SPARC_UA32:
283       buf_write_be32 (buf, value);
284       break;
285     case R_SPARC_DISP16:
286       value -= rela->r_offset;
287     case R_SPARC_16:
288     case R_SPARC_UA16:
289       buf_write_be16 (buf, value);
290       break;
291     case R_SPARC_DISP8:
292       value -= rela->r_offset;
293     case R_SPARC_8:
294       buf_write_8 (buf, value);
295       break;
296     case R_SPARC_LO10:
297       buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) | (value & 0x3ff));
298       break;
299     case R_SPARC_HI22:
300       buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000)
301                            | ((value >> 10) & 0x3fffff));
302       break;
303     case R_SPARC_WDISP30:
304       buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xc0000000)
305                            | (((value - rela->r_offset) >> 2) & 0x3fffffff));
306       break;
307     case R_SPARC_RELATIVE:
308       error (0, 0, "%s: R_SPARC_RELATIVE in ET_EXEC object?",
309              info->dso->filename);
310       return 1;
311     default:
312       return 1;
313     }
314   return 0;
315 }
316
317 static int
318 sparc_prelink_conflict_rel (DSO *dso, struct prelink_info *info,
319                             GElf_Rel *rel, GElf_Addr reladdr)
320 {
321   error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename);
322   return 1;
323 }
324
325 static int
326 sparc_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
327                              GElf_Rela *rela, GElf_Addr relaaddr)
328 {
329   GElf_Addr value;
330   struct prelink_conflict *conflict;
331   struct prelink_tls *tls;
332   GElf_Rela *ret;
333   int r_type;
334
335   if (GELF_R_TYPE (rela->r_info) == R_SPARC_RELATIVE
336       || GELF_R_TYPE (rela->r_info) == R_SPARC_NONE
337       || info->dso == dso)
338     /* Fast path: nothing to do.  */
339     return 0;
340   conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info),
341                                GELF_R_TYPE (rela->r_info));
342   if (conflict == NULL)
343     {
344       if (info->curtls == NULL)
345         return 0;
346       switch (GELF_R_TYPE (rela->r_info))
347         {
348         /* Even local DTPMOD32 and TPOFF32 relocs need conflicts.  */
349         case R_SPARC_TLS_DTPMOD32:
350         case R_SPARC_TLS_TPOFF32:
351         case R_SPARC_TLS_LE_HIX22:
352         case R_SPARC_TLS_LE_LOX10:
353           break;
354         default:
355           return 0;
356         }
357       value = 0;
358     }
359   else if (conflict->ifunc)
360     {
361       error (0, 0, "%s: STT_GNU_IFUNC not handled on SPARC yet",
362              dso->filename);
363       return 1;
364     }
365   else
366     {
367       /* DTPOFF32 wants to see only real conflicts, not lookups
368          with reloc_class RTYPE_CLASS_TLS.  */
369       if (GELF_R_TYPE (rela->r_info) == R_SPARC_TLS_DTPOFF32
370           && conflict->lookup.tls == conflict->conflict.tls
371           && conflict->lookupval == conflict->conflictval)
372         return 0;
373
374       value = conflict_lookup_value (conflict);
375     }
376   ret = prelink_conflict_add_rela (info);
377   if (ret == NULL)
378     return 1;
379   ret->r_offset = rela->r_offset;
380   value += rela->r_addend;
381   r_type = GELF_R_TYPE (rela->r_info);
382   switch (r_type)
383     {
384     case R_SPARC_DISP32:
385       value -= rela->r_offset;
386     case R_SPARC_GLOB_DAT:
387     case R_SPARC_32:
388       r_type = R_SPARC_32;
389       break;
390     case R_SPARC_DISP16:
391       value -= rela->r_offset;
392     case R_SPARC_16:
393       r_type = R_SPARC_16;
394       break;
395     case R_SPARC_DISP8:
396       value -= rela->r_offset;
397     case R_SPARC_8:
398       r_type = R_SPARC_8;
399       break;
400     /* Attempt to transform all reloc which read-modify-write into
401        simple writes.  */
402     case R_SPARC_LO10:
403       value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) | (value & 0x3ff);
404       r_type = R_SPARC_32;
405       break;
406     case R_SPARC_HI22:
407       value = (read_ube32 (dso, rela->r_offset) & 0xffc00000)
408               | ((value >> 10) & 0x3fffff);
409       r_type = R_SPARC_32;
410       break;
411     case R_SPARC_WDISP30:
412       value = (read_ube32 (dso, rela->r_offset) & 0xc0000000)
413               | (((value - rela->r_offset) >> 2) & 0x3fffffff);
414       r_type = R_SPARC_32;
415       break;
416     case R_SPARC_UA16:
417     case R_SPARC_UA32:
418     case R_SPARC_JMP_SLOT:
419       break;
420     case R_SPARC_TLS_DTPMOD32:
421     case R_SPARC_TLS_DTPOFF32:
422     case R_SPARC_TLS_TPOFF32:
423     case R_SPARC_TLS_LE_HIX22:
424     case R_SPARC_TLS_LE_LOX10:
425       if (conflict != NULL
426           && (conflict->reloc_class != RTYPE_CLASS_TLS
427               || conflict->lookup.tls == NULL))
428         {
429           error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol",
430                  dso->filename);
431           return 1;
432         }
433       r_type = R_SPARC_32;
434       tls = conflict ? conflict->lookup.tls : info->curtls;
435       switch (GELF_R_TYPE (rela->r_info))
436         {
437         case R_SPARC_TLS_DTPMOD32:
438           value = tls->modid;
439           break;
440         case R_SPARC_TLS_DTPOFF32:
441           break;
442         case R_SPARC_TLS_TPOFF32:
443           value -= tls->offset;
444           break;
445         case R_SPARC_TLS_LE_HIX22:
446           value -= tls->offset;
447           value = (read_ube32 (dso, rela->r_offset) & 0xffc00000)
448                   | (((~value) >> 10) & 0x3fffff);
449           break;
450         case R_SPARC_TLS_LE_LOX10:
451           value -= tls->offset;
452           value = (read_ube32 (dso, rela->r_offset) & 0xffffe000) | 0x1c00
453                   | (value & 0x3ff);
454           break;
455         }
456       break;
457     default:
458       error (0, 0, "%s: Unknown Sparc relocation type %d", dso->filename,
459              r_type);
460       return 1;
461     }
462   ret->r_info = GELF_R_INFO (0, r_type);
463   ret->r_addend = (Elf32_Sword) value;
464   return 0;
465 }
466
467 static int
468 sparc_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
469 {
470   error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename);
471   return 1;
472 }
473
474 static int
475 sparc_need_rel_to_rela (DSO *dso, int first, int last)
476 {
477   return 0;
478 }
479
480 static int
481 sparc_arch_prelink (struct prelink_info *info)
482 {
483   return 0;
484 }
485
486 static int
487 sparc_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr)
488 {
489   int sec;
490
491   switch (GELF_R_TYPE (rela->r_info))
492     {
493     case R_SPARC_NONE:
494       return 0;
495     case R_SPARC_RELATIVE:
496       /* 32-bit SPARC handles RELATIVE relocs as
497          *(int *)rela->r_offset += l_addr + rela->r_addend.
498          RELATIVE relocs against .got traditionally used to have the
499          addend in memory pointed by r_offset and 0 r_addend,
500          other RELATIVE relocs and more recent RELATIVE relocs have 0
501          in memory and non-zero r_addend.
502          Always store 0 to memory when doing undo.  */
503       assert (rela->r_addend == 0);
504       rela->r_addend = (Elf32_Sword) read_ube32 (dso, rela->r_offset);
505       write_be32 (dso, rela->r_offset, 0);
506       /* Tell undo_prelink_rela routine it should update the
507          relocation.  */
508       return 2;
509     case R_SPARC_GLOB_DAT:
510     case R_SPARC_32:
511     case R_SPARC_UA32:
512     case R_SPARC_DISP32:
513     case R_SPARC_TLS_DTPMOD32:
514     case R_SPARC_TLS_DTPOFF32:
515     case R_SPARC_TLS_TPOFF32:
516       write_be32 (dso, rela->r_offset, 0);
517       break;
518     case R_SPARC_JMP_SLOT:
519       sec = addr_to_sec (dso, rela->r_offset);
520       if (sec != -1)
521         {
522           /* sethi .-.plt, %g1
523              b,a .plt+0  */
524           write_be32 (dso, rela->r_offset,
525                       0x03000000
526                       | ((rela->r_offset - dso->shdr[sec].sh_addr)
527                          & 0x3fffff));
528           write_be32 (dso, rela->r_offset + 4,
529                       0x30800000
530                       | (((dso->shdr[sec].sh_addr - rela->r_offset - 4) >> 2)
531                          & 0x3fffff));
532         }
533       break;
534     case R_SPARC_8:
535     case R_SPARC_DISP8:
536       write_8 (dso, rela->r_offset, 0);
537       break;
538     case R_SPARC_16:
539     case R_SPARC_UA16:
540     case R_SPARC_DISP16:
541       write_be16 (dso, rela->r_offset, 0);
542       break;
543     case R_SPARC_LO10:
544       write_be32 (dso, rela->r_offset,
545                   read_ube32 (dso, rela->r_offset) & ~0x3ff);
546       break;
547     case R_SPARC_TLS_LE_LOX10:
548       write_be32 (dso, rela->r_offset,
549                   read_ube32 (dso, rela->r_offset) & 0xffffe000);
550       break;
551     case R_SPARC_HI22:
552     case R_SPARC_TLS_LE_HIX22:
553       write_be32 (dso, rela->r_offset,
554                   read_ube32 (dso, rela->r_offset) & 0xffc00000);
555       break;
556     case R_SPARC_WDISP30:
557       write_be32 (dso, rela->r_offset,
558                   read_ube32 (dso, rela->r_offset) & 0xc0000000);
559       break;
560     case R_SPARC_COPY:
561       if (dso->ehdr.e_type == ET_EXEC)
562         /* COPY relocs are handled specially in generic code.  */
563         return 0;
564       error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename);
565       return 1;
566     default:
567       error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename,
568              (int) GELF_R_TYPE (rela->r_info));
569       return 1;
570     }
571   return 0;
572 }
573
574 static int
575 sparc_reloc_size (int reloc_type)
576 {
577   switch (reloc_type)
578     {
579     case R_SPARC_8:
580     case R_SPARC_DISP8:
581       return 1;
582     case R_SPARC_16:
583     case R_SPARC_DISP16:
584     case R_SPARC_UA16:
585       return 2;
586     default:
587       break;
588     }
589   return 4;
590 }
591
592 static int
593 sparc_reloc_class (int reloc_type)
594 {
595   switch (reloc_type)
596     {
597     case R_SPARC_COPY: return RTYPE_CLASS_COPY;
598     case R_SPARC_JMP_SLOT: return RTYPE_CLASS_PLT;
599     case R_SPARC_TLS_DTPMOD32:
600     case R_SPARC_TLS_DTPOFF32:
601     case R_SPARC_TLS_TPOFF32:
602     case R_SPARC_TLS_LE_HIX22:
603     case R_SPARC_TLS_LE_LOX10:
604       return RTYPE_CLASS_TLS;
605     default: return RTYPE_CLASS_VALID;
606     }
607 }
608
609 PL_ARCH = {
610   .name = "SPARC",
611   .class = ELFCLASS32,
612   .machine = EM_SPARC,
613   .alternate_machine = { EM_SPARC32PLUS },
614   .R_JMP_SLOT = R_SPARC_JMP_SLOT,
615   .R_COPY = R_SPARC_COPY,
616   .R_RELATIVE = R_SPARC_RELATIVE,
617   .rtype_class_valid = RTYPE_CLASS_VALID,
618   .dynamic_linker = "/lib/ld-linux.so.2",
619   .adjust_dyn = sparc_adjust_dyn,
620   .adjust_rel = sparc_adjust_rel,
621   .adjust_rela = sparc_adjust_rela,
622   .prelink_rel = sparc_prelink_rel,
623   .prelink_rela = sparc_prelink_rela,
624   .prelink_conflict_rel = sparc_prelink_conflict_rel,
625   .prelink_conflict_rela = sparc_prelink_conflict_rela,
626   .apply_conflict_rela = sparc_apply_conflict_rela,
627   .apply_rel = sparc_apply_rel,
628   .apply_rela = sparc_apply_rela,
629   .rel_to_rela = sparc_rel_to_rela,
630   .need_rel_to_rela = sparc_need_rel_to_rela,
631   .reloc_size = sparc_reloc_size,
632   .reloc_class = sparc_reloc_class,
633   .max_reloc_size = 4,
634   .arch_prelink = sparc_arch_prelink,
635   .undo_prelink_rela = sparc_undo_prelink_rela,
636   /* Although TASK_UNMAPPED_BASE is 0x70000000, we leave some
637      area so that mmap of /etc/ld.so.cache and ld.so's malloc
638      does not take some library's VA slot.
639      Also, if this guard area isn't too small, typically
640      even dlopened libraries will get the slots they desire.  */
641   .mmap_base = 0x71000000LL,
642   .mmap_end =  0x80000000LL,
643   .max_page_size = 0x10000,
644   .page_size = 0x1000
645 };