15
15
#include <linux/module.h>
16
16
#include <linux/of.h>
17
17
#include <linux/of_fdt.h>
18
+ #include <linux/sizes.h>
18
19
#include <linux/string.h>
19
20
#include <linux/errno.h>
20
21
#include <linux/slab.h>
@@ -439,6 +440,118 @@ struct boot_param_header *initial_boot_params;
439
440
440
441
#ifdef CONFIG_OF_EARLY_FLATTREE
441
442
443
+ /**
444
+ * res_mem_reserve_reg() - reserve all memory described in 'reg' property
445
+ */
446
+ static int __init __reserved_mem_reserve_reg (unsigned long node ,
447
+ const char * uname )
448
+ {
449
+ int t_len = (dt_root_addr_cells + dt_root_size_cells ) * sizeof (__be32 );
450
+ phys_addr_t base , size ;
451
+ unsigned long len ;
452
+ __be32 * prop ;
453
+ int nomap ;
454
+
455
+ prop = of_get_flat_dt_prop (node , "reg" , & len );
456
+ if (!prop )
457
+ return - ENOENT ;
458
+
459
+ if (len && len % t_len != 0 ) {
460
+ pr_err ("Reserved memory: invalid reg property in '%s', skipping node.\n" ,
461
+ uname );
462
+ return - EINVAL ;
463
+ }
464
+
465
+ nomap = of_get_flat_dt_prop (node , "no-map" , NULL ) != NULL ;
466
+
467
+ while (len >= t_len ) {
468
+ base = dt_mem_next_cell (dt_root_addr_cells , & prop );
469
+ size = dt_mem_next_cell (dt_root_size_cells , & prop );
470
+
471
+ if (base && size &&
472
+ early_init_dt_reserve_memory_arch (base , size , nomap ) == 0 )
473
+ pr_debug ("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n" ,
474
+ uname , & base , (unsigned long )size / SZ_1M );
475
+ else
476
+ pr_info ("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n" ,
477
+ uname , & base , (unsigned long )size / SZ_1M );
478
+
479
+ len -= t_len ;
480
+ }
481
+ return 0 ;
482
+ }
483
+
484
+ /**
485
+ * __reserved_mem_check_root() - check if #size-cells, #address-cells provided
486
+ * in /reserved-memory matches the values supported by the current implementation,
487
+ * also check if ranges property has been provided
488
+ */
489
+ static int __reserved_mem_check_root (unsigned long node )
490
+ {
491
+ __be32 * prop ;
492
+
493
+ prop = of_get_flat_dt_prop (node , "#size-cells" , NULL );
494
+ if (!prop || be32_to_cpup (prop ) != dt_root_size_cells )
495
+ return - EINVAL ;
496
+
497
+ prop = of_get_flat_dt_prop (node , "#address-cells" , NULL );
498
+ if (!prop || be32_to_cpup (prop ) != dt_root_addr_cells )
499
+ return - EINVAL ;
500
+
501
+ prop = of_get_flat_dt_prop (node , "ranges" , NULL );
502
+ if (!prop )
503
+ return - EINVAL ;
504
+ return 0 ;
505
+ }
506
+
507
+ /**
508
+ * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
509
+ */
510
+ static int __init __fdt_scan_reserved_mem (unsigned long node , const char * uname ,
511
+ int depth , void * data )
512
+ {
513
+ static int found ;
514
+ const char * status ;
515
+
516
+ if (!found && depth == 1 && strcmp (uname , "reserved-memory" ) == 0 ) {
517
+ if (__reserved_mem_check_root (node ) != 0 ) {
518
+ pr_err ("Reserved memory: unsupported node format, ignoring\n" );
519
+ /* break scan */
520
+ return 1 ;
521
+ }
522
+ found = 1 ;
523
+ /* scan next node */
524
+ return 0 ;
525
+ } else if (!found ) {
526
+ /* scan next node */
527
+ return 0 ;
528
+ } else if (found && depth < 2 ) {
529
+ /* scanning of /reserved-memory has been finished */
530
+ return 1 ;
531
+ }
532
+
533
+ status = of_get_flat_dt_prop (node , "status" , NULL );
534
+ if (status && strcmp (status , "okay" ) != 0 && strcmp (status , "ok" ) != 0 )
535
+ return 0 ;
536
+
537
+ __reserved_mem_reserve_reg (node , uname );
538
+
539
+ /* scan next node */
540
+ return 0 ;
541
+ }
542
+
543
+ /**
544
+ * early_init_fdt_scan_reserved_mem() - create reserved memory regions
545
+ *
546
+ * This function grabs memory from early allocator for device exclusive use
547
+ * defined in device tree structures. It should be called by arch specific code
548
+ * once the early allocator (i.e. memblock) has been fully activated.
549
+ */
550
+ void __init early_init_fdt_scan_reserved_mem (void )
551
+ {
552
+ of_scan_flat_dt (__fdt_scan_reserved_mem , NULL );
553
+ }
554
+
442
555
/**
443
556
* of_scan_flat_dt - scan flattened tree blob and call callback on each.
444
557
* @it: callback function
@@ -856,6 +969,16 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
856
969
memblock_add (base , size );
857
970
}
858
971
972
+ int __init __weak early_init_dt_reserve_memory_arch (phys_addr_t base ,
973
+ phys_addr_t size , bool nomap )
974
+ {
975
+ if (memblock_is_region_reserved (base , size ))
976
+ return - EBUSY ;
977
+ if (nomap )
978
+ return memblock_remove (base , size );
979
+ return memblock_reserve (base , size );
980
+ }
981
+
859
982
/*
860
983
* called from unflatten_device_tree() to bootstrap devicetree itself
861
984
* Architectures can override this definition if memblock isn't used
@@ -864,6 +987,14 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
864
987
{
865
988
return __va (memblock_alloc (size , align ));
866
989
}
990
+ #else
991
+ int __init __weak early_init_dt_reserve_memory_arch (phys_addr_t base ,
992
+ phys_addr_t size , bool nomap )
993
+ {
994
+ pr_err ("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n" ,
995
+ base , size , nomap ? " (nomap)" : "" );
996
+ return - ENOSYS ;
997
+ }
867
998
#endif
868
999
869
1000
bool __init early_init_dt_scan (void * params )
0 commit comments