coreboot-kgpe-d16/src/soc/intel/braswell/northcluster.c
Harry Pan 43dcbfd855 soc/braswell: fix ACPI table by recollecting TOLM
cherry-pick from Chromium, commit 8fbe1e7

On Braswell and Baytrail devices, by userland 'perf top',
observed demanding clocks on __vdso_clock_gettime() since
chromeos_3.18 kernel; besides, evaluated massive calling of
clock_gettime() cost, up to 700 ns in average.

It turns out that Linux kernel of map_vdso() first call of
remap_pfn_range() does not fall into reserve_pfn_range()
due to size parameter, instead it relies on lookup_memtype()
and potentially be failed to be identified as eligible RAM
resource because the function of pat_pagerange_is_ram() actually
walks through root's sibling.

Meanwhile, on current BSW (and BYT) firmware implementation
makes System RAM resources located on child leaf, combining all
of these factors makes the kernel treat the vvar page of vdso
as a uncached-minus one leading slow access in result.

This patch recollects TOLM accessing; as Aaron recalled some
core_msr_script turns off access to TOLM register, he suggests
to store tolm to avoid getting back a zero while setting acpi
nvs space.

Original-Change-Id: Iad4ffa542b22073cb087100a95169e2d2a52efcd
Original-Signed-off-by: Harry Pan <harry.pan@intel.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/368585
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>

Change-Id: Idc9765ec5c0920dc98baeb9267a89bec5cadd5a0
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/20060
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
2017-06-09 17:04:33 +02:00

165 lines
4.7 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright (C) 2013 Google Inc.
* Copyright (C) 2015 Intel Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <arch/acpi.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <fsp/memmap.h>
#include <fsp/util.h>
#include <soc/iomap.h>
#include <soc/iosf.h>
#include <soc/pci_devs.h>
#include <soc/ramstage.h>
#include <soc/smm.h>
#include <vendorcode/google/chromeos/chromeos.h>
#include <stddef.h>
/*
* Host Memory Map:
*
* +--------------------------+ BMBOUND_HI
* | Usable DRAM |
* +--------------------------+ 4GiB
* | PCI Address Space |
* +--------------------------+ BMBOUND
* | TPM |
* +--------------------------+ IMR2
* | TXE |
* +--------------------------+ IMR1
* | iGD |
* +--------------------------+
* | GTT |
* +--------------------------+ SMMRRH, IRM0
* | TSEG |
* +--------------------------+ SMMRRL
* | Usable DRAM |
* +--------------------------+ 0
*
* Note that there are really only a few regions that need to enumerated w.r.t.
* coreboot's resrouce model:
*
* +--------------------------+ BMBOUND_HI
* | Cacheable/Usable |
* +--------------------------+ 4GiB
*
* +--------------------------+ BMBOUND
* | Uncacheable/Reserved |
* +--------------------------+ SMMRRH
* | Cacheable/Reserved |
* +--------------------------+ SMMRRL
* | Cacheable/Usable |
* +--------------------------+ 0
*/
#define RES_IN_KIB(r) ((r) >> 10)
uint32_t nc_read_top_of_low_memory(void)
{
MAYBE_STATIC uint32_t tolm = 0;
if (tolm)
return tolm;
tolm = iosf_bunit_read(BUNIT_BMBOUND) & ~((1 << 27) - 1);
return tolm;
}
static void nc_read_resources(device_t dev)
{
unsigned long mmconf;
unsigned long bmbound_k;
unsigned long bmbound_hi;
void *smm_base;
size_t smm_size;
unsigned long tseg_base_k;
unsigned long tseg_top_k;
unsigned long fsp_res_base_k;
unsigned long base_k, size_k;
const unsigned long four_gig_kib = (4 << (30 - 10));
int index = 0;
/* Read standard PCI resources. */
pci_dev_read_resources(dev);
/* Determine TSEG data */
smm_region(&smm_base, &smm_size);
tseg_base_k = RES_IN_KIB((unsigned long) smm_base);
tseg_top_k = tseg_base_k + RES_IN_KIB(smm_size);
/* Determine the base of the FSP reserved memory */
fsp_res_base_k = RES_IN_KIB((unsigned long) cbmem_top());
/* PCIe memory-mapped config space access - 256 MiB. */
mmconf = iosf_bunit_read(BUNIT_MMCONF_REG) & ~((1 << 28) - 1);
mmio_resource(dev, BUNIT_MMCONF_REG, RES_IN_KIB(mmconf), 256 * 1024);
/* 0 -> 0xa0000 */
base_k = RES_IN_KIB(0);
size_k = RES_IN_KIB(0xa0000) - base_k;
ram_resource(dev, index++, base_k, size_k);
/* 0xc0000 -> fsp_res_base - cacheable and usable */
base_k = RES_IN_KIB(0xc0000);
size_k = fsp_res_base_k - base_k;
ram_resource(dev, index++, base_k, size_k);
/* fsp_res_base -> tseg_top - Reserved */
base_k = fsp_res_base_k;
size_k = tseg_top_k - base_k;
reserved_ram_resource(dev, index++, base_k, size_k);
/* TSEG TOP -> bmbound is memory backed mmio. */
bmbound_k = RES_IN_KIB(nc_read_top_of_low_memory());
mmio_resource(dev, index++, tseg_top_k, bmbound_k - tseg_top_k);
/*
* The BMBOUND_HI register matches register bits of 31:24 with address
* bits of 35:28. Therefore, shift register to align properly.
*/
bmbound_hi = iosf_bunit_read(BUNIT_BMBOUND_HI) & ~((1 << 24) - 1);
bmbound_hi = RES_IN_KIB(bmbound_hi) << 4;
if (bmbound_hi > four_gig_kib)
ram_resource(dev, index++, four_gig_kib,
bmbound_hi - four_gig_kib);
/*
* Reserve everything between A segment and 1MB:
*
* 0xa0000 - 0xbffff: legacy VGA
* 0xc0000 - 0xfffff: RAM
*/
mmio_resource(dev, index++, (0xa0000 >> 10), (0xc0000 - 0xa0000) >> 10);
reserved_ram_resource(dev, index++, (0xc0000 >> 10),
(0x100000 - 0xc0000) >> 10);
chromeos_reserve_ram_oops(dev, index++);
}
static struct device_operations nc_ops = {
.acpi_fill_ssdt_generator = generate_cpu_entries,
.read_resources = nc_read_resources,
.ops_pci = &soc_pci_ops,
};
static const struct pci_driver nc_driver __pci_driver = {
.ops = &nc_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.device = SOC_DEVID,
};