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

apic_flat_64.c (6433B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2004 James Cleverdon, IBM.
      4 *
      5 * Flat APIC subarch code.
      6 *
      7 * Hacked for x86-64 by James Cleverdon from i386 architecture code by
      8 * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
      9 * James Cleverdon.
     10 */
     11#include <linux/cpumask.h>
     12#include <linux/export.h>
     13#include <linux/acpi.h>
     14
     15#include <asm/jailhouse_para.h>
     16#include <asm/apic.h>
     17
     18#include "local.h"
     19
     20static struct apic apic_physflat;
     21static struct apic apic_flat;
     22
     23struct apic *apic __ro_after_init = &apic_flat;
     24EXPORT_SYMBOL_GPL(apic);
     25
     26static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
     27{
     28	return 1;
     29}
     30
     31/*
     32 * Set up the logical destination ID.
     33 *
     34 * Intel recommends to set DFR, LDR and TPR before enabling
     35 * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
     36 * document number 292116).  So here it goes...
     37 */
     38void flat_init_apic_ldr(void)
     39{
     40	unsigned long val;
     41	unsigned long num, id;
     42
     43	num = smp_processor_id();
     44	id = 1UL << num;
     45	apic_write(APIC_DFR, APIC_DFR_FLAT);
     46	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
     47	val |= SET_APIC_LOGICAL_ID(id);
     48	apic_write(APIC_LDR, val);
     49}
     50
     51static void _flat_send_IPI_mask(unsigned long mask, int vector)
     52{
     53	unsigned long flags;
     54
     55	local_irq_save(flags);
     56	__default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
     57	local_irq_restore(flags);
     58}
     59
     60static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
     61{
     62	unsigned long mask = cpumask_bits(cpumask)[0];
     63
     64	_flat_send_IPI_mask(mask, vector);
     65}
     66
     67static void
     68flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
     69{
     70	unsigned long mask = cpumask_bits(cpumask)[0];
     71	int cpu = smp_processor_id();
     72
     73	if (cpu < BITS_PER_LONG)
     74		__clear_bit(cpu, &mask);
     75
     76	_flat_send_IPI_mask(mask, vector);
     77}
     78
     79static unsigned int flat_get_apic_id(unsigned long x)
     80{
     81	return (x >> 24) & 0xFF;
     82}
     83
     84static u32 set_apic_id(unsigned int id)
     85{
     86	return (id & 0xFF) << 24;
     87}
     88
     89static unsigned int read_xapic_id(void)
     90{
     91	return flat_get_apic_id(apic_read(APIC_ID));
     92}
     93
     94static int flat_apic_id_registered(void)
     95{
     96	return physid_isset(read_xapic_id(), phys_cpu_present_map);
     97}
     98
     99static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
    100{
    101	return initial_apic_id >> index_msb;
    102}
    103
    104static int flat_probe(void)
    105{
    106	return 1;
    107}
    108
    109static struct apic apic_flat __ro_after_init = {
    110	.name				= "flat",
    111	.probe				= flat_probe,
    112	.acpi_madt_oem_check		= flat_acpi_madt_oem_check,
    113	.apic_id_valid			= default_apic_id_valid,
    114	.apic_id_registered		= flat_apic_id_registered,
    115
    116	.delivery_mode			= APIC_DELIVERY_MODE_FIXED,
    117	.dest_mode_logical		= true,
    118
    119	.disable_esr			= 0,
    120
    121	.check_apicid_used		= NULL,
    122	.init_apic_ldr			= flat_init_apic_ldr,
    123	.ioapic_phys_id_map		= NULL,
    124	.setup_apic_routing		= NULL,
    125	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
    126	.apicid_to_cpu_present		= NULL,
    127	.check_phys_apicid_present	= default_check_phys_apicid_present,
    128	.phys_pkg_id			= flat_phys_pkg_id,
    129
    130	.get_apic_id			= flat_get_apic_id,
    131	.set_apic_id			= set_apic_id,
    132
    133	.calc_dest_apicid		= apic_flat_calc_apicid,
    134
    135	.send_IPI			= default_send_IPI_single,
    136	.send_IPI_mask			= flat_send_IPI_mask,
    137	.send_IPI_mask_allbutself	= flat_send_IPI_mask_allbutself,
    138	.send_IPI_allbutself		= default_send_IPI_allbutself,
    139	.send_IPI_all			= default_send_IPI_all,
    140	.send_IPI_self			= default_send_IPI_self,
    141
    142	.inquire_remote_apic		= default_inquire_remote_apic,
    143
    144	.read				= native_apic_mem_read,
    145	.write				= native_apic_mem_write,
    146	.eoi_write			= native_apic_mem_write,
    147	.icr_read			= native_apic_icr_read,
    148	.icr_write			= native_apic_icr_write,
    149	.wait_icr_idle			= native_apic_wait_icr_idle,
    150	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
    151};
    152
    153/*
    154 * Physflat mode is used when there are more than 8 CPUs on a system.
    155 * We cannot use logical delivery in this case because the mask
    156 * overflows, so use physical mode.
    157 */
    158static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
    159{
    160#ifdef CONFIG_ACPI
    161	/*
    162	 * Quirk: some x86_64 machines can only use physical APIC mode
    163	 * regardless of how many processors are present (x86_64 ES7000
    164	 * is an example).
    165	 */
    166	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
    167		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
    168		printk(KERN_DEBUG "system APIC only can use physical flat");
    169		return 1;
    170	}
    171
    172	if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
    173		printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
    174		return 1;
    175	}
    176#endif
    177
    178	return 0;
    179}
    180
    181static void physflat_init_apic_ldr(void)
    182{
    183	/*
    184	 * LDR and DFR are not involved in physflat mode, rather:
    185	 * "In physical destination mode, the destination processor is
    186	 * specified by its local APIC ID [...]." (Intel SDM, 10.6.2.1)
    187	 */
    188}
    189
    190static int physflat_probe(void)
    191{
    192	if (apic == &apic_physflat || num_possible_cpus() > 8 ||
    193	    jailhouse_paravirt())
    194		return 1;
    195
    196	return 0;
    197}
    198
    199static struct apic apic_physflat __ro_after_init = {
    200
    201	.name				= "physical flat",
    202	.probe				= physflat_probe,
    203	.acpi_madt_oem_check		= physflat_acpi_madt_oem_check,
    204	.apic_id_valid			= default_apic_id_valid,
    205	.apic_id_registered		= flat_apic_id_registered,
    206
    207	.delivery_mode			= APIC_DELIVERY_MODE_FIXED,
    208	.dest_mode_logical		= false,
    209
    210	.disable_esr			= 0,
    211
    212	.check_apicid_used		= NULL,
    213	.init_apic_ldr			= physflat_init_apic_ldr,
    214	.ioapic_phys_id_map		= NULL,
    215	.setup_apic_routing		= NULL,
    216	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
    217	.apicid_to_cpu_present		= NULL,
    218	.check_phys_apicid_present	= default_check_phys_apicid_present,
    219	.phys_pkg_id			= flat_phys_pkg_id,
    220
    221	.get_apic_id			= flat_get_apic_id,
    222	.set_apic_id			= set_apic_id,
    223
    224	.calc_dest_apicid		= apic_default_calc_apicid,
    225
    226	.send_IPI			= default_send_IPI_single_phys,
    227	.send_IPI_mask			= default_send_IPI_mask_sequence_phys,
    228	.send_IPI_mask_allbutself	= default_send_IPI_mask_allbutself_phys,
    229	.send_IPI_allbutself		= default_send_IPI_allbutself,
    230	.send_IPI_all			= default_send_IPI_all,
    231	.send_IPI_self			= default_send_IPI_self,
    232
    233	.inquire_remote_apic		= default_inquire_remote_apic,
    234
    235	.read				= native_apic_mem_read,
    236	.write				= native_apic_mem_write,
    237	.eoi_write			= native_apic_mem_write,
    238	.icr_read			= native_apic_icr_read,
    239	.icr_write			= native_apic_icr_write,
    240	.wait_icr_idle			= native_apic_wait_icr_idle,
    241	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
    242};
    243
    244/*
    245 * We need to check for physflat first, so this order is important.
    246 */
    247apic_drivers(apic_physflat, apic_flat);