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

probe_32.c (5037B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Default generic APIC driver. This handles up to 8 CPUs.
      4 *
      5 * Copyright 2003 Andi Kleen, SuSE Labs.
      6 *
      7 * Generic x86 APIC driver probe layer.
      8 */
      9#include <linux/export.h>
     10#include <linux/errno.h>
     11#include <linux/smp.h>
     12
     13#include <asm/io_apic.h>
     14#include <asm/apic.h>
     15#include <asm/acpi.h>
     16
     17#include "local.h"
     18
     19static int default_x86_32_early_logical_apicid(int cpu)
     20{
     21	return 1 << cpu;
     22}
     23
     24static void setup_apic_flat_routing(void)
     25{
     26#ifdef CONFIG_X86_IO_APIC
     27	printk(KERN_INFO
     28		"Enabling APIC mode:  Flat.  Using %d I/O APICs\n",
     29		nr_ioapics);
     30#endif
     31}
     32
     33static int default_apic_id_registered(void)
     34{
     35	return physid_isset(read_apic_id(), phys_cpu_present_map);
     36}
     37
     38/*
     39 * Set up the logical destination ID.  Intel recommends to set DFR, LDR and
     40 * TPR before enabling an APIC.  See e.g. "AP-388 82489DX User's Manual"
     41 * (Intel document number 292116).
     42 */
     43static void default_init_apic_ldr(void)
     44{
     45	unsigned long val;
     46
     47	apic_write(APIC_DFR, APIC_DFR_VALUE);
     48	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
     49	val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
     50	apic_write(APIC_LDR, val);
     51}
     52
     53static int default_phys_pkg_id(int cpuid_apic, int index_msb)
     54{
     55	return cpuid_apic >> index_msb;
     56}
     57
     58/* should be called last. */
     59static int probe_default(void)
     60{
     61	return 1;
     62}
     63
     64static struct apic apic_default __ro_after_init = {
     65
     66	.name				= "default",
     67	.probe				= probe_default,
     68	.acpi_madt_oem_check		= NULL,
     69	.apic_id_valid			= default_apic_id_valid,
     70	.apic_id_registered		= default_apic_id_registered,
     71
     72	.delivery_mode			= APIC_DELIVERY_MODE_FIXED,
     73	.dest_mode_logical		= true,
     74
     75	.disable_esr			= 0,
     76
     77	.check_apicid_used		= default_check_apicid_used,
     78	.init_apic_ldr			= default_init_apic_ldr,
     79	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
     80	.setup_apic_routing		= setup_apic_flat_routing,
     81	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
     82	.apicid_to_cpu_present		= physid_set_mask_of_physid,
     83	.check_phys_apicid_present	= default_check_phys_apicid_present,
     84	.phys_pkg_id			= default_phys_pkg_id,
     85
     86	.get_apic_id			= default_get_apic_id,
     87	.set_apic_id			= NULL,
     88
     89	.calc_dest_apicid		= apic_flat_calc_apicid,
     90
     91	.send_IPI			= default_send_IPI_single,
     92	.send_IPI_mask			= default_send_IPI_mask_logical,
     93	.send_IPI_mask_allbutself	= default_send_IPI_mask_allbutself_logical,
     94	.send_IPI_allbutself		= default_send_IPI_allbutself,
     95	.send_IPI_all			= default_send_IPI_all,
     96	.send_IPI_self			= default_send_IPI_self,
     97
     98	.inquire_remote_apic		= default_inquire_remote_apic,
     99
    100	.read				= native_apic_mem_read,
    101	.write				= native_apic_mem_write,
    102	.eoi_write			= native_apic_mem_write,
    103	.icr_read			= native_apic_icr_read,
    104	.icr_write			= native_apic_icr_write,
    105	.wait_icr_idle			= native_apic_wait_icr_idle,
    106	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
    107
    108	.x86_32_early_logical_apicid	= default_x86_32_early_logical_apicid,
    109};
    110
    111apic_driver(apic_default);
    112
    113struct apic *apic __ro_after_init = &apic_default;
    114EXPORT_SYMBOL_GPL(apic);
    115
    116static int cmdline_apic __initdata;
    117static int __init parse_apic(char *arg)
    118{
    119	struct apic **drv;
    120
    121	if (!arg)
    122		return -EINVAL;
    123
    124	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
    125		if (!strcmp((*drv)->name, arg)) {
    126			apic = *drv;
    127			cmdline_apic = 1;
    128			return 0;
    129		}
    130	}
    131
    132	/* Parsed again by __setup for debug/verbose */
    133	return 0;
    134}
    135early_param("apic", parse_apic);
    136
    137void __init default_setup_apic_routing(void)
    138{
    139	int version = boot_cpu_apic_version;
    140
    141	if (num_possible_cpus() > 8) {
    142		switch (boot_cpu_data.x86_vendor) {
    143		case X86_VENDOR_INTEL:
    144			if (!APIC_XAPIC(version)) {
    145				def_to_bigsmp = 0;
    146				break;
    147			}
    148			/* P4 and above */
    149			fallthrough;
    150		case X86_VENDOR_HYGON:
    151		case X86_VENDOR_AMD:
    152			def_to_bigsmp = 1;
    153		}
    154	}
    155
    156#ifdef CONFIG_X86_BIGSMP
    157	/*
    158	 * This is used to switch to bigsmp mode when
    159	 * - There is no apic= option specified by the user
    160	 * - generic_apic_probe() has chosen apic_default as the sub_arch
    161	 * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
    162	 */
    163
    164	if (!cmdline_apic && apic == &apic_default)
    165		generic_bigsmp_probe();
    166#endif
    167
    168	if (apic->setup_apic_routing)
    169		apic->setup_apic_routing();
    170}
    171
    172void __init generic_apic_probe(void)
    173{
    174	if (!cmdline_apic) {
    175		struct apic **drv;
    176
    177		for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
    178			if ((*drv)->probe()) {
    179				apic = *drv;
    180				break;
    181			}
    182		}
    183		/* Not visible without early console */
    184		if (drv == __apicdrivers_end)
    185			panic("Didn't find an APIC driver");
    186	}
    187	printk(KERN_INFO "Using APIC driver %s\n", apic->name);
    188}
    189
    190/* This function can switch the APIC even after the initial ->probe() */
    191int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
    192{
    193	struct apic **drv;
    194
    195	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
    196		if (!(*drv)->acpi_madt_oem_check)
    197			continue;
    198		if (!(*drv)->acpi_madt_oem_check(oem_id, oem_table_id))
    199			continue;
    200
    201		if (!cmdline_apic) {
    202			apic = *drv;
    203			printk(KERN_INFO "Switched to APIC driver `%s'.\n",
    204			       apic->name);
    205		}
    206		return 1;
    207	}
    208	return 0;
    209}