cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vsmp_64.c (3372B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * vSMPowered(tm) systems specific initialization
      4 * Copyright (C) 2005 ScaleMP Inc.
      5 *
      6 * Ravikiran Thirumalai <kiran@scalemp.com>,
      7 * Shai Fultheim <shai@scalemp.com>
      8 * Paravirt ops integration: Glauber de Oliveira Costa <gcosta@redhat.com>,
      9 *			     Ravikiran Thirumalai <kiran@scalemp.com>
     10 */
     11
     12#include <linux/init.h>
     13#include <linux/pci_ids.h>
     14#include <linux/pci_regs.h>
     15#include <linux/smp.h>
     16#include <linux/irq.h>
     17
     18#include <asm/apic.h>
     19#include <asm/pci-direct.h>
     20#include <asm/io.h>
     21#include <asm/paravirt.h>
     22#include <asm/setup.h>
     23
     24#define TOPOLOGY_REGISTER_OFFSET 0x10
     25
     26#ifdef CONFIG_PCI
     27static void __init set_vsmp_ctl(void)
     28{
     29	void __iomem *address;
     30	unsigned int cap, ctl, cfg;
     31
     32	/* set vSMP magic bits to indicate vSMP capable kernel */
     33	cfg = read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0);
     34	address = early_ioremap(cfg, 8);
     35	cap = readl(address);
     36	ctl = readl(address + 4);
     37	printk(KERN_INFO "vSMP CTL: capabilities:0x%08x  control:0x%08x\n",
     38	       cap, ctl);
     39
     40	/* If possible, let the vSMP foundation route the interrupt optimally */
     41#ifdef CONFIG_SMP
     42	if (cap & ctl & BIT(8)) {
     43		ctl &= ~BIT(8);
     44
     45#ifdef CONFIG_PROC_FS
     46		/* Don't let users change irq affinity via procfs */
     47		no_irq_affinity = 1;
     48#endif
     49	}
     50#endif
     51
     52	writel(ctl, address + 4);
     53	ctl = readl(address + 4);
     54	pr_info("vSMP CTL: control set to:0x%08x\n", ctl);
     55
     56	early_iounmap(address, 8);
     57}
     58static int is_vsmp = -1;
     59
     60static void __init detect_vsmp_box(void)
     61{
     62	is_vsmp = 0;
     63
     64	if (!early_pci_allowed())
     65		return;
     66
     67	/* Check if we are running on a ScaleMP vSMPowered box */
     68	if (read_pci_config(0, 0x1f, 0, PCI_VENDOR_ID) ==
     69	     (PCI_VENDOR_ID_SCALEMP | (PCI_DEVICE_ID_SCALEMP_VSMP_CTL << 16)))
     70		is_vsmp = 1;
     71}
     72
     73static int is_vsmp_box(void)
     74{
     75	if (is_vsmp != -1)
     76		return is_vsmp;
     77	else {
     78		WARN_ON_ONCE(1);
     79		return 0;
     80	}
     81}
     82
     83#else
     84static void __init detect_vsmp_box(void)
     85{
     86}
     87static int is_vsmp_box(void)
     88{
     89	return 0;
     90}
     91static void __init set_vsmp_ctl(void)
     92{
     93}
     94#endif
     95
     96static void __init vsmp_cap_cpus(void)
     97{
     98#if !defined(CONFIG_X86_VSMP) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
     99	void __iomem *address;
    100	unsigned int cfg, topology, node_shift, maxcpus;
    101
    102	/*
    103	 * CONFIG_X86_VSMP is not configured, so limit the number CPUs to the
    104	 * ones present in the first board, unless explicitly overridden by
    105	 * setup_max_cpus
    106	 */
    107	if (setup_max_cpus != NR_CPUS)
    108		return;
    109
    110	/* Read the vSMP Foundation topology register */
    111	cfg = read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0);
    112	address = early_ioremap(cfg + TOPOLOGY_REGISTER_OFFSET, 4);
    113	if (WARN_ON(!address))
    114		return;
    115
    116	topology = readl(address);
    117	node_shift = (topology >> 16) & 0x7;
    118	if (!node_shift)
    119		/* The value 0 should be decoded as 8 */
    120		node_shift = 8;
    121	maxcpus = (topology & ((1 << node_shift) - 1)) + 1;
    122
    123	pr_info("vSMP CTL: Capping CPUs to %d (CONFIG_X86_VSMP is unset)\n",
    124		maxcpus);
    125	setup_max_cpus = maxcpus;
    126	early_iounmap(address, 4);
    127#endif
    128}
    129
    130static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
    131{
    132	return hard_smp_processor_id() >> index_msb;
    133}
    134
    135static void vsmp_apic_post_init(void)
    136{
    137	/* need to update phys_pkg_id */
    138	apic->phys_pkg_id = apicid_phys_pkg_id;
    139}
    140
    141void __init vsmp_init(void)
    142{
    143	detect_vsmp_box();
    144	if (!is_vsmp_box())
    145		return;
    146
    147	x86_platform.apic_post_init = vsmp_apic_post_init;
    148
    149	vsmp_cap_cpus();
    150
    151	set_vsmp_ctl();
    152	return;
    153}