1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/romstage.h>
5 #include <console/console.h>
6 #include <commonlib/helpers.h>
8 #include <cpu/x86/msr.h>
9 #include <cpu/x86/mtrr.h>
10 #include <northbridge/amd/agesa/agesa_helper.h>
11 #include <romstage_handoff.h>
13 static void set_range_uc(u32 base
, u32 size
)
17 max_var_mtrrs
= get_var_mtrr_count();
19 for (i
= 0; i
< max_var_mtrrs
; i
++) {
20 msr
= rdmsr(MTRR_PHYS_MASK(i
));
21 if (!(msr
.lo
& MTRR_PHYS_MASK_VALID
))
24 if (i
== max_var_mtrrs
)
25 die("Run out of unused MTRRs\n");
28 msr
.lo
= base
| MTRR_TYPE_UNCACHEABLE
;
29 wrmsr(MTRR_PHYS_BASE(i
), msr
);
31 msr
.hi
= (1 << (cpu_phys_address_size() - 32)) - 1;
32 msr
.lo
= ~(size
- 1) | MTRR_PHYS_MASK_VALID
;
33 wrmsr(MTRR_PHYS_MASK(i
), msr
);
36 void fixup_cbmem_to_UC(int s3resume
)
41 /* For normal path, INIT_POST has returned with all
42 * memory set WB cacheable. But we need CBMEM as UC
43 * to make CAR teardown with invalidation without
47 uintptr_t top_of_ram
= (uintptr_t)cbmem_top();
48 top_of_ram
= ALIGN_UP(top_of_ram
, 4 * MiB
);
50 set_range_uc(top_of_ram
- 4 * MiB
, 4 * MiB
);
51 set_range_uc(top_of_ram
- 8 * MiB
, 4 * MiB
);
54 static void recover_postcar_frame(struct postcar_frame
*pcf
)
58 int s3resume
= romstage_handoff_is_resume();
60 /* Replicate non-UC MTRRs as left behind by AGESA.
62 for (i
= 0; i
< pcf
->mtrr
->max_var_mtrrs
; i
++) {
63 mask
= rdmsr(MTRR_PHYS_MASK(i
));
64 base
= rdmsr(MTRR_PHYS_BASE(i
));
65 u32 size
= ~(mask
.lo
& ~0xfff) + 1;
66 u8 type
= base
.lo
& 0x7;
69 if (!(mask
.lo
& MTRR_PHYS_MASK_VALID
) ||
70 (type
== MTRR_TYPE_UNCACHEABLE
))
73 postcar_frame_add_mtrr(pcf
, base
.lo
, size
, type
);
76 /* For S3 resume path, INIT_RESUME does not return with
77 * memory covering CBMEM set as WB cacheable. For better
78 * speed make them WB after CAR teardown.
81 uintptr_t top_of_ram
= (uintptr_t)cbmem_top();
82 top_of_ram
= ALIGN_DOWN(top_of_ram
, 4 * MiB
);
84 postcar_frame_add_mtrr(pcf
, top_of_ram
- 4 * MiB
, 4 * MiB
,
86 postcar_frame_add_mtrr(pcf
, top_of_ram
- 8 * MiB
, 4 * MiB
,
91 void fill_postcar_frame(struct postcar_frame
*pcf
)
93 pcf
->skip_common_mtrr
= 1;
94 recover_postcar_frame(pcf
);