blob: 5f0493a5109943258fa8c3f73e4e5eb15f52a2d5 [file] [log] [blame]
Aaron Durbinc34713d2014-02-25 20:36:56 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Aaron Durbinc34713d2014-02-25 20:36:56 -060014 */
15
16#include <stdint.h>
17#include <stdlib.h>
18#include <string.h>
19#include <console/console.h>
20#include <bootmem.h>
Aaron Durbin04654a22015-03-17 11:43:44 -050021#include <program_loading.h>
Aaron Durbinc34713d2014-02-25 20:36:56 -060022
Aaron Durbin5957bd72015-05-19 16:32:54 -050023void mirror_payload(struct prog *payload)
Aaron Durbinc34713d2014-02-25 20:36:56 -060024{
25 char *buffer;
26 size_t size;
27 char *src;
28 uintptr_t alignment_diff;
29 const unsigned long cacheline_size = 64;
30 const uintptr_t intra_cacheline_mask = cacheline_size - 1;
31 const uintptr_t cacheline_mask = ~intra_cacheline_mask;
32
Aaron Durbin5957bd72015-05-19 16:32:54 -050033 src = prog_start(payload);
34 size = prog_size(payload);
Aaron Durbinc34713d2014-02-25 20:36:56 -060035
36 /*
37 * Adjust size so that the start and end points are aligned to a
38 * cacheline. The SPI hardware controllers on Intel machines should
39 * cache full length cachelines as well as prefetch data. Once the
40 * data is mirrored in memory all accesses should hit the CPU's cache.
41 */
42 alignment_diff = (intra_cacheline_mask & (uintptr_t)src);
43 size += alignment_diff;
44
45 size = ALIGN(size, cacheline_size);
46
47 printk(BIOS_DEBUG, "Payload aligned size: 0x%zx\n", size);
48
49 buffer = bootmem_allocate_buffer(size);
50
51 if (buffer == NULL) {
52 printk(BIOS_DEBUG, "No buffer for mirroring payload.\n");
53 return;
54 }
55
56 src = (void *)(cacheline_mask & (uintptr_t)src);
57
58 /*
59 * Note that if mempcy is not using 32-bit moves the performance will
60 * degrade because the SPI hardware prefetchers look for
61 * cacheline-aligned 32-bit accesses to kick in.
62 */
63 memcpy(buffer, src, size);
64
65 /* Update the payload's backing store. */
Aaron Durbin5957bd72015-05-19 16:32:54 -050066 prog_set_area(payload, &buffer[alignment_diff], prog_size(payload));
Aaron Durbinc34713d2014-02-25 20:36:56 -060067}