Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 platform updates from Ingo Molnar:
 "The main changes in this cycle were:

   - Add "Jailhouse" hypervisor support (Jan Kiszka)

   - Update DeviceTree support (Ivan Gorinov)

   - Improve DMI date handling (Andy Shevchenko)"

* 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/PCI: Fix a potential regression when using dmi_get_bios_year()
  firmware/dmi_scan: Uninline dmi_get_bios_year() helper
  x86/devicetree: Use CPU description from Device Tree
  of/Documentation: Specify local APIC ID in "reg"
  MAINTAINERS: Add entry for Jailhouse
  x86/jailhouse: Allow to use PCI_MMCONFIG without ACPI
  x86: Consolidate PCI_MMCONFIG configs
  x86: Align x86_64 PCI_MMCONFIG with 32-bit variant
  x86/jailhouse: Enable PCI mmconfig access in inmates
  PCI: Scan all functions when running over Jailhouse
  jailhouse: Provide detection for non-x86 systems
  x86/devicetree: Fix device IRQ settings in DT
  x86/devicetree: Initialize device tree before using it
  pci: Simplify code by using the new dmi_get_bios_year() helper
  ACPI/sleep: Simplify code by using the new dmi_get_bios_year() helper
  x86/pci: Simplify code by using the new dmi_get_bios_year() helper
  dmi: Introduce the dmi_get_bios_year() helper function
  x86/platform/quark: Re-use DEFINE_SHOW_ATTRIBUTE() macro
  x86/platform/atom: Re-use DEFINE_SHOW_ATTRIBUTE() macro
This commit is contained in:
Linus Torvalds 2018-04-02 16:15:32 -07:00
commit cea061e455
22 changed files with 186 additions and 104 deletions

View File

@ -0,0 +1,8 @@
Jailhouse non-root cell device tree bindings
--------------------------------------------
When running in a non-root Jailhouse cell (partition), the device tree of this
platform shall have a top-level "hypervisor" node with the following
properties:
- compatible = "jailhouse,cell"

View File

@ -7,17 +7,36 @@ Many of the "generic" devices like HPET or IO APIC have the ce4100
name in their compatible property because they first appeared in this
SoC.
The CPU node
------------
cpu@0 {
device_type = "cpu";
compatible = "intel,ce4100";
reg = <0>;
lapic = <&lapic0>;
The CPU nodes
-------------
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "intel,ce4100";
reg = <0x00>;
};
cpu@2 {
device_type = "cpu";
compatible = "intel,ce4100";
reg = <0x02>;
};
};
The reg property describes the CPU number. The lapic property points to
the local APIC timer.
A "cpu" node describes one logical processor (hardware thread).
Required properties:
- device_type
Device type, must be "cpu".
- reg
Local APIC ID, the unique number assigned to each processor by
system hardware.
The SoC node
------------

View File

@ -7534,6 +7534,13 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/
S: Maintained
F: drivers/media/dvb-frontends/ix2505v*
JAILHOUSE HYPERVISOR INTERFACE
M: Jan Kiszka <jan.kiszka@siemens.com>
L: jailhouse-dev@googlegroups.com
S: Maintained
F: arch/x86/kernel/jailhouse.c
F: arch/x86/include/asm/jailhouse_para.h
JC42.4 TEMPERATURE SENSOR DRIVER
M: Guenter Roeck <linux@roeck-us.net>
L: linux-hwmon@vger.kernel.org

View File

@ -2626,8 +2626,10 @@ config PCI_DIRECT
depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC || PCI_GOMMCONFIG))
config PCI_MMCONFIG
def_bool y
depends on X86_32 && PCI && (ACPI || SFI) && (PCI_GOMMCONFIG || PCI_GOANY)
bool "Support mmconfig PCI config space access" if X86_64
default y
depends on PCI && (ACPI || SFI || JAILHOUSE_GUEST)
depends on X86_64 || (PCI_GOANY || PCI_GOMMCONFIG)
config PCI_OLPC
def_bool y
@ -2642,9 +2644,9 @@ config PCI_DOMAINS
def_bool y
depends on PCI
config PCI_MMCONFIG
bool "Support mmconfig PCI config space access"
depends on X86_64 && PCI && ACPI
config MMCONF_FAM10H
def_bool y
depends on X86_64 && PCI_MMCONFIG && ACPI
config PCI_CNB20LE_QUIRK
bool "Read CNB20LE Host Bridge Windows" if EXPERT

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL2.0 */
/*
* Jailhouse paravirt_ops implementation
* Jailhouse paravirt detection
*
* Copyright (c) Siemens AG, 2015-2017
*

View File

@ -151,6 +151,8 @@ extern int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
phys_addr_t addr);
extern int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
extern struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start,
int end, u64 addr);
extern struct list_head pci_mmcfg_list;

View File

@ -146,6 +146,6 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_GART_IOMMU) += amd_gart_64.o aperture_64.o
obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
obj-$(CONFIG_MMCONF_FAM10H) += mmconf-fam10h_64.o
obj-y += vsmp_64.o
endif

View File

@ -716,7 +716,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c)
static void init_amd_gh(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_X86_64
#ifdef CONFIG_MMCONF_FAM10H
/* do this for boot cpu */
if (c == &boot_cpu_data)
check_enable_amd_mmconf_dmi();

View File

@ -11,6 +11,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
#include <linux/libfdt.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/of_pci.h>
@ -130,34 +131,52 @@ static void __init dtb_setup_hpet(void)
#endif
}
#ifdef CONFIG_X86_LOCAL_APIC
static void __init dtb_cpu_setup(void)
{
struct device_node *dn;
u32 apic_id, version;
int ret;
version = GET_APIC_VERSION(apic_read(APIC_LVR));
for_each_node_by_type(dn, "cpu") {
ret = of_property_read_u32(dn, "reg", &apic_id);
if (ret < 0) {
pr_warn("%pOF: missing local APIC ID\n", dn);
continue;
}
generic_processor_info(apic_id, version);
}
}
static void __init dtb_lapic_setup(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
struct device_node *dn;
struct resource r;
unsigned long lapic_addr = APIC_DEFAULT_PHYS_BASE;
int ret;
dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
if (!dn)
return;
ret = of_address_to_resource(dn, 0, &r);
if (WARN_ON(ret))
return;
if (dn) {
ret = of_address_to_resource(dn, 0, &r);
if (WARN_ON(ret))
return;
lapic_addr = r.start;
}
/* Did the boot loader setup the local APIC ? */
if (!boot_cpu_has(X86_FEATURE_APIC)) {
if (apic_force_enable(r.start))
if (apic_force_enable(lapic_addr))
return;
}
smp_found_config = 1;
pic_mode = 1;
register_lapic_address(r.start);
generic_processor_info(boot_cpu_physical_apicid,
GET_APIC_VERSION(apic_read(APIC_LVR)));
#endif
register_lapic_address(lapic_addr);
}
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
static unsigned int ioapic_id;
@ -194,19 +213,22 @@ static struct of_ioapic_type of_ioapic_type[] =
static int dt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *arg)
{
struct of_phandle_args *irq_data = (void *)arg;
struct irq_fwspec *fwspec = (struct irq_fwspec *)arg;
struct of_ioapic_type *it;
struct irq_alloc_info tmp;
int type_index;
if (WARN_ON(irq_data->args_count < 2))
return -EINVAL;
if (irq_data->args[1] >= ARRAY_SIZE(of_ioapic_type))
if (WARN_ON(fwspec->param_count < 2))
return -EINVAL;
it = &of_ioapic_type[irq_data->args[1]];
type_index = fwspec->param[1];
if (type_index >= ARRAY_SIZE(of_ioapic_type))
return -EINVAL;
it = &of_ioapic_type[type_index];
ioapic_set_alloc_attr(&tmp, NUMA_NO_NODE, it->trigger, it->polarity);
tmp.ioapic_id = mpc_ioapic_id(mp_irqdomain_ioapic_idx(domain));
tmp.ioapic_pin = irq_data->args[0];
tmp.ioapic_pin = fwspec->param[0];
return mp_irqdomain_alloc(domain, virq, nr_irqs, &tmp);
}
@ -255,7 +277,10 @@ static void __init dtb_ioapic_setup(void) {}
static void __init dtb_apic_setup(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
dtb_lapic_setup();
dtb_cpu_setup();
#endif
dtb_ioapic_setup();
}
@ -270,14 +295,15 @@ static void __init x86_flattree_get_config(void)
map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
initial_boot_params = dt = early_memremap(initial_dtb, map_len);
size = of_get_flat_dt_size();
dt = early_memremap(initial_dtb, map_len);
size = fdt_totalsize(dt);
if (map_len < size) {
early_memunmap(dt, map_len);
initial_boot_params = dt = early_memremap(initial_dtb, size);
dt = early_memremap(initial_dtb, size);
map_len = size;
}
early_init_dt_verify(dt);
unflatten_and_copy_device_tree();
early_memunmap(dt, map_len);
}

View File

@ -124,6 +124,14 @@ static int __init jailhouse_pci_arch_init(void)
if (pcibios_last_bus < 0)
pcibios_last_bus = 0xff;
#ifdef CONFIG_PCI_MMCONFIG
if (setup_data.pci_mmconfig_base) {
pci_mmconfig_add(0, 0, pcibios_last_bus,
setup_data.pci_mmconfig_base);
pci_mmcfg_arch_init();
}
#endif
return 0;
}

View File

@ -140,12 +140,10 @@ static const struct dmi_system_id pci_crs_quirks[] __initconst = {
void __init pci_acpi_crs_quirks(void)
{
int year;
int year = dmi_get_bios_year();
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) {
if (iomem_resource.end <= 0xffffffff)
pci_use_crs = false;
}
if (year >= 0 && year < 2008 && iomem_resource.end <= 0xffffffff)
pci_use_crs = false;
dmi_check_system(pci_crs_quirks);

View File

@ -195,14 +195,13 @@ static const struct pci_raw_ops pci_direct_conf2 = {
static int __init pci_sanity_check(const struct pci_raw_ops *o)
{
u32 x = 0;
int year, devfn;
int devfn;
if (pci_probe & PCI_NO_CHECKS)
return 1;
/* Assume Type 1 works for newer systems.
This handles machines that don't have anything on PCI Bus 0. */
dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL);
if (year >= 2001)
if (dmi_get_bios_year() >= 2001)
return 1;
for (devfn = 0; devfn < 0x100; devfn++) {

View File

@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/export.h>
#include <linux/pci.h>
#include <asm/jailhouse_para.h>
#include <asm/pci_x86.h>
/*
@ -34,13 +35,14 @@ int __init pci_legacy_init(void)
void pcibios_scan_specific_bus(int busn)
{
int stride = jailhouse_paravirt() ? 1 : 8;
int devfn;
u32 l;
if (pci_find_bus(0, busn))
return;
for (devfn = 0; devfn < 256; devfn += 8) {
for (devfn = 0; devfn < 256; devfn += stride) {
if (!raw_pci_read(0, busn, devfn, PCI_VENDOR_ID, 2, &l) &&
l != 0x0000 && l != 0xffff) {
DBG("Found device at %02x:%02x [%04x]\n", busn, devfn, l);

View File

@ -94,8 +94,8 @@ static struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start,
return new;
}
static struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start,
int end, u64 addr)
struct pci_mmcfg_region *__init pci_mmconfig_add(int segment, int start,
int end, u64 addr)
{
struct pci_mmcfg_region *new;
@ -547,19 +547,14 @@ static void __init pci_mmcfg_reject_broken(int early)
static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
struct acpi_mcfg_allocation *cfg)
{
int year;
if (cfg->address < 0xFFFFFFFF)
return 0;
if (!strncmp(mcfg->header.oem_id, "SGI", 3))
return 0;
if (mcfg->header.revision >= 1) {
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
year >= 2010)
return 0;
}
if ((mcfg->header.revision >= 1) && (dmi_get_bios_year() >= 2010))
return 0;
pr_err(PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx "
"is above 4GB, ignored\n", cfg->pci_segment,

View File

@ -109,18 +109,7 @@ static int punit_dev_state_show(struct seq_file *seq_file, void *unused)
return 0;
}
static int punit_dev_state_open(struct inode *inode, struct file *file)
{
return single_open(file, punit_dev_state_show, inode->i_private);
}
static const struct file_operations punit_dev_state_ops = {
.open = punit_dev_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(punit_dev_state);
static struct dentry *punit_dbg_file;
@ -132,9 +121,9 @@ static int punit_dbgfs_register(struct punit_device *punit_device)
if (!punit_dbg_file)
return -ENXIO;
dev_state = debugfs_create_file("dev_power_state", S_IFREG | S_IRUGO,
dev_state = debugfs_create_file("dev_power_state", 0444,
punit_dbg_file, punit_device,
&punit_dev_state_ops);
&punit_dev_state_fops);
if (!dev_state) {
pr_err("punit_dev_state register failed\n");
debugfs_remove(punit_dbg_file);

View File

@ -224,25 +224,7 @@ static int imr_dbgfs_state_show(struct seq_file *s, void *unused)
mutex_unlock(&idev->lock);
return ret;
}
/**
* imr_state_open - debugfs open callback.
*
* @inode: pointer to struct inode.
* @file: pointer to struct file.
* @return: result of single open.
*/
static int imr_state_open(struct inode *inode, struct file *file)
{
return single_open(file, imr_dbgfs_state_show, inode->i_private);
}
static const struct file_operations imr_state_ops = {
.open = imr_state_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(imr_dbgfs_state);
/**
* imr_debugfs_register - register debugfs hooks.
@ -252,8 +234,8 @@ static const struct file_operations imr_state_ops = {
*/
static int imr_debugfs_register(struct imr_device *idev)
{
idev->file = debugfs_create_file("imr_state", S_IFREG | S_IRUGO, NULL,
idev, &imr_state_ops);
idev->file = debugfs_create_file("imr_state", 0444, NULL, idev,
&imr_dbgfs_state_fops);
return PTR_ERR_OR_ZERO(idev->file);
}

View File

@ -376,12 +376,10 @@ void __init acpi_sleep_no_blacklist(void)
static void __init acpi_sleep_dmi_check(void)
{
int year;
if (ignore_blacklist)
return;
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012)
if (dmi_get_bios_year() >= 2012)
acpi_nvs_nosave_s3();
dmi_check_system(acpisleep_dmi_table);

View File

@ -1004,6 +1004,26 @@ out:
}
EXPORT_SYMBOL(dmi_get_date);
/**
* dmi_get_bios_year - get a year out of DMI_BIOS_DATE field
*
* Returns year on success, -ENXIO if DMI is not selected,
* or a different negative error code if DMI field is not present
* or not parseable.
*/
int dmi_get_bios_year(void)
{
bool exists;
int year;
exists = dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL);
if (!exists)
return -ENODATA;
return year ? year : -ERANGE;
}
EXPORT_SYMBOL(dmi_get_bios_year);
/**
* dmi_walk - Walk the DMI table and get called back for every record
* @decode: Callback function

View File

@ -2258,8 +2258,6 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev)
*/
bool pci_bridge_d3_possible(struct pci_dev *bridge)
{
unsigned int year;
if (!pci_is_pcie(bridge))
return false;
@ -2287,10 +2285,8 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
* It should be safe to put PCIe ports from 2015 or newer
* to D3.
*/
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
year >= 2015) {
if (dmi_get_bios_year() >= 2015)
return true;
}
break;
}

View File

@ -16,6 +16,7 @@
#include <linux/pci-aspm.h>
#include <linux/aer.h>
#include <linux/acpi.h>
#include <linux/hypervisor.h>
#include <linux/irqdomain.h>
#include <linux/pm_runtime.h>
#include "pci.h"
@ -2518,14 +2519,29 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
{
unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0;
unsigned int start = bus->busn_res.start;
unsigned int devfn, cmax, max = start;
unsigned int devfn, fn, cmax, max = start;
struct pci_dev *dev;
int nr_devs;
dev_dbg(&bus->dev, "scanning bus\n");
/* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8)
pci_scan_slot(bus, devfn);
for (devfn = 0; devfn < 256; devfn += 8) {
nr_devs = pci_scan_slot(bus, devfn);
/*
* The Jailhouse hypervisor may pass individual functions of a
* multi-function device to a guest without passing function 0.
* Look for them as well.
*/
if (jailhouse_paravirt() && nr_devs == 0) {
for (fn = 1; fn < 8; fn++) {
dev = pci_scan_single_device(bus, devfn + fn);
if (dev)
dev->multifunction = 1;
}
}
}
/* Reserve buses for SR-IOV capability */
used_buses = pci_iov_bus_range(bus);

View File

@ -106,6 +106,7 @@ extern void dmi_scan_machine(void);
extern void dmi_memdev_walk(void);
extern void dmi_set_dump_stack_arch_desc(void);
extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp);
extern int dmi_get_bios_year(void);
extern int dmi_name_in_vendors(const char *str);
extern int dmi_name_in_serial(const char *str);
extern int dmi_available;
@ -133,6 +134,7 @@ static inline bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
*dayp = 0;
return false;
}
static inline int dmi_get_bios_year(void) { return -ENXIO; }
static inline int dmi_name_in_vendors(const char *s) { return 0; }
static inline int dmi_name_in_serial(const char *s) { return 0; }
#define dmi_available 0

View File

@ -8,15 +8,28 @@
*/
#ifdef CONFIG_X86
#include <asm/jailhouse_para.h>
#include <asm/x86_init.h>
static inline void hypervisor_pin_vcpu(int cpu)
{
x86_platform.hyper.pin_vcpu(cpu);
}
#else
#else /* !CONFIG_X86 */
#include <linux/of.h>
static inline void hypervisor_pin_vcpu(int cpu)
{
}
#endif
static inline bool jailhouse_paravirt(void)
{
return of_find_compatible_node(NULL, NULL, "jailhouse,cell");
}
#endif /* !CONFIG_X86 */
#endif /* __LINUX_HYPEVISOR_H */