1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <cpu/x86/pae.h>
6 #define memset_pae(a, b, c, d, e) 0
7 #define PAE_PGTL_ALIGN 0
8 #define PAE_PGTL_SIZE 0
9 #define PAE_VMEM_ALIGN 0
10 #define PAE_VMEM_SIZE 0
15 #include <bootstate.h>
17 #include <console/console.h>
18 #include <arch/memory_clear.h>
20 #include <security/memory/memory.h>
22 #include <acpi/acpi.h>
23 #include <drivers/efi/capsules.h>
25 /* Helper to find free space for memset_pae. */
26 static uintptr_t get_free_memory_range(struct memranges
*mem
,
27 const resource_t align
,
28 const resource_t size
)
30 const struct range_entry
*r
;
32 /* Find a spot for virtual memory address */
33 memranges_each_entry(r
, mem
) {
34 if (range_entry_tag(r
) != BM_MEM_RAM
)
37 if (ALIGN_UP(range_entry_base(r
) + size
, align
) + size
>
41 return ALIGN_UP(range_entry_base(r
) + size
, align
);
43 printk(BIOS_ERR
, "%s: Couldn't find free memory range\n", __func__
);
49 * Clears all memory regions marked as BM_MEM_RAM.
50 * Uses memset_pae if the memory region can't be accessed by memset and
51 * architecture is x86.
53 * @return 0 on success, 1 on error
55 static void clear_memory(void *unused
)
57 const struct range_entry
*r
;
59 uintptr_t pgtbl
, vmem_addr
;
61 if (acpi_is_wakeup_s3())
64 /* Process capsules before clearing memory and only if not waking up from S3. */
67 if (!security_clear_dram_request())
70 /* FSP1.0 is marked as MMIO and won't appear here */
72 memranges_init(&mem
, IORESOURCE_MEM
| IORESOURCE_FIXED
|
73 IORESOURCE_STORED
| IORESOURCE_ASSIGNED
|
75 IORESOURCE_MEM
| IORESOURCE_FIXED
|
76 IORESOURCE_STORED
| IORESOURCE_ASSIGNED
|
80 /* Add reserved entries */
84 /* Only skip CBMEM, stage program, stack and heap are included there. */
86 if (cbmem_get_region(&baseptr
, &size
))
87 die("Could not find cbmem region");
88 memranges_insert(&mem
, (uintptr_t)baseptr
, size
, BM_MEM_TABLE
);
91 /* Find space for PAE enabled memset */
92 pgtbl
= get_free_memory_range(&mem
, PAE_PGTL_ALIGN
, PAE_PGTL_SIZE
);
94 /* Don't touch page tables while clearing */
95 memranges_insert(&mem
, pgtbl
, PAE_PGTL_SIZE
, BM_MEM_TABLE
);
97 vmem_addr
= get_free_memory_range(&mem
, PAE_VMEM_ALIGN
, PAE_VMEM_SIZE
);
99 printk(BIOS_SPEW
, "%s: pgtbl at %p, virt memory at %p\n",
100 __func__
, (void *)pgtbl
, (void *)vmem_addr
);
103 /* Now clear all usable DRAM */
104 memranges_each_entry(r
, &mem
) {
105 if (range_entry_tag(r
) != BM_MEM_RAM
)
107 printk(BIOS_DEBUG
, "%s: Clearing DRAM %016llx-%016llx\n",
108 __func__
, range_entry_base(r
), range_entry_end(r
));
110 /* Does regular memset work? */
111 if (sizeof(resource_t
) == sizeof(void *) ||
112 !(range_entry_end(r
) >> (sizeof(void *) * 8))) {
114 memset((void *)(uintptr_t)range_entry_base(r
), 0,
115 range_entry_size(r
));
117 /* Use PAE if available */
119 if (memset_pae(range_entry_base(r
), 0,
120 range_entry_size(r
), (void *)pgtbl
,
122 printk(BIOS_ERR
, "%s: Failed to memset "
123 "memory\n", __func__
);
125 printk(BIOS_ERR
, "%s: Failed to memset memory\n",
131 /* Clear previously skipped memory reserved for pagetables */
132 printk(BIOS_DEBUG
, "%s: Clearing DRAM %016lx-%016lx\n",
133 __func__
, pgtbl
, pgtbl
+ PAE_PGTL_SIZE
);
135 memset((void *)pgtbl
, 0, PAE_PGTL_SIZE
);
138 memranges_teardown(&mem
);
141 /* After DEV_INIT as MTRRs needs to be configured on x86 */
142 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT
, BS_ON_EXIT
, clear_memory
, NULL
);