18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_APIC_H
38c2ecf20Sopenharmony_ci#define _ASM_X86_APIC_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/cpumask.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <asm/alternative.h>
88c2ecf20Sopenharmony_ci#include <asm/cpufeature.h>
98c2ecf20Sopenharmony_ci#include <asm/apicdef.h>
108c2ecf20Sopenharmony_ci#include <linux/atomic.h>
118c2ecf20Sopenharmony_ci#include <asm/fixmap.h>
128c2ecf20Sopenharmony_ci#include <asm/mpspec.h>
138c2ecf20Sopenharmony_ci#include <asm/msr.h>
148c2ecf20Sopenharmony_ci#include <asm/hardirq.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define ARCH_APICTIMER_STOPS_ON_C3	1
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/*
198c2ecf20Sopenharmony_ci * Debugging macros
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci#define APIC_QUIET   0
228c2ecf20Sopenharmony_ci#define APIC_VERBOSE 1
238c2ecf20Sopenharmony_ci#define APIC_DEBUG   2
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/* Macros for apic_extnmi which controls external NMI masking */
268c2ecf20Sopenharmony_ci#define APIC_EXTNMI_BSP		0 /* Default */
278c2ecf20Sopenharmony_ci#define APIC_EXTNMI_ALL		1
288c2ecf20Sopenharmony_ci#define APIC_EXTNMI_NONE	2
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/*
318c2ecf20Sopenharmony_ci * Define the default level of output to be very little
328c2ecf20Sopenharmony_ci * This can be turned up by using apic=verbose for more
338c2ecf20Sopenharmony_ci * information and apic=debug for _lots_ of information.
348c2ecf20Sopenharmony_ci * apic_verbosity is defined in apic.c
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ci#define apic_printk(v, s, a...) do {       \
378c2ecf20Sopenharmony_ci		if ((v) <= apic_verbosity) \
388c2ecf20Sopenharmony_ci			printk(s, ##a);    \
398c2ecf20Sopenharmony_ci	} while (0)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
438c2ecf20Sopenharmony_ciextern void generic_apic_probe(void);
448c2ecf20Sopenharmony_ci#else
458c2ecf20Sopenharmony_cistatic inline void generic_apic_probe(void)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci#endif
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_LOCAL_APIC
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ciextern int apic_verbosity;
538c2ecf20Sopenharmony_ciextern int local_apic_timer_c2_ok;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciextern int disable_apic;
568c2ecf20Sopenharmony_ciextern unsigned int lapic_timer_period;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ciextern enum apic_intr_mode_id apic_intr_mode;
598c2ecf20Sopenharmony_cienum apic_intr_mode_id {
608c2ecf20Sopenharmony_ci	APIC_PIC,
618c2ecf20Sopenharmony_ci	APIC_VIRTUAL_WIRE,
628c2ecf20Sopenharmony_ci	APIC_VIRTUAL_WIRE_NO_CONFIG,
638c2ecf20Sopenharmony_ci	APIC_SYMMETRIC_IO,
648c2ecf20Sopenharmony_ci	APIC_SYMMETRIC_IO_NO_ROUTING
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
688c2ecf20Sopenharmony_ciextern void __inquire_remote_apic(int apicid);
698c2ecf20Sopenharmony_ci#else /* CONFIG_SMP */
708c2ecf20Sopenharmony_cistatic inline void __inquire_remote_apic(int apicid)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic inline void default_inquire_remote_apic(int apicid)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	if (apic_verbosity >= APIC_DEBUG)
788c2ecf20Sopenharmony_ci		__inquire_remote_apic(apicid);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/*
828c2ecf20Sopenharmony_ci * With 82489DX we can't rely on apic feature bit
838c2ecf20Sopenharmony_ci * retrieved via cpuid but still have to deal with
848c2ecf20Sopenharmony_ci * such an apic chip so we assume that SMP configuration
858c2ecf20Sopenharmony_ci * is found from MP table (64bit case uses ACPI mostly
868c2ecf20Sopenharmony_ci * which set smp presence flag as well so we are safe
878c2ecf20Sopenharmony_ci * to use this helper too).
888c2ecf20Sopenharmony_ci */
898c2ecf20Sopenharmony_cistatic inline bool apic_from_smp_config(void)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	return smp_found_config && !disable_apic;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/*
958c2ecf20Sopenharmony_ci * Basic functions accessing APICs.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_ci#ifdef CONFIG_PARAVIRT
988c2ecf20Sopenharmony_ci#include <asm/paravirt.h>
998c2ecf20Sopenharmony_ci#endif
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciextern int setup_profiling_timer(unsigned int);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic inline void native_apic_mem_write(u32 reg, u32 v)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	alternative_io("movl %0, %P1", "xchgl %0, %P1", X86_BUG_11AP,
1088c2ecf20Sopenharmony_ci		       ASM_OUTPUT2("=r" (v), "=m" (*addr)),
1098c2ecf20Sopenharmony_ci		       ASM_OUTPUT2("0" (v), "m" (*addr)));
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic inline u32 native_apic_mem_read(u32 reg)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	return *((volatile u32 *)(APIC_BASE + reg));
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ciextern void native_apic_wait_icr_idle(void);
1188c2ecf20Sopenharmony_ciextern u32 native_safe_apic_wait_icr_idle(void);
1198c2ecf20Sopenharmony_ciextern void native_apic_icr_write(u32 low, u32 id);
1208c2ecf20Sopenharmony_ciextern u64 native_apic_icr_read(void);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic inline bool apic_is_x2apic_enabled(void)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	u64 msr;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (rdmsrl_safe(MSR_IA32_APICBASE, &msr))
1278c2ecf20Sopenharmony_ci		return false;
1288c2ecf20Sopenharmony_ci	return msr & X2APIC_ENABLE;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ciextern void enable_IR_x2apic(void);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ciextern int get_physical_broadcast(void);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ciextern int lapic_get_maxlvt(void);
1368c2ecf20Sopenharmony_ciextern void clear_local_APIC(void);
1378c2ecf20Sopenharmony_ciextern void disconnect_bsp_APIC(int virt_wire_setup);
1388c2ecf20Sopenharmony_ciextern void disable_local_APIC(void);
1398c2ecf20Sopenharmony_ciextern void apic_soft_disable(void);
1408c2ecf20Sopenharmony_ciextern void lapic_shutdown(void);
1418c2ecf20Sopenharmony_ciextern void sync_Arb_IDs(void);
1428c2ecf20Sopenharmony_ciextern void init_bsp_APIC(void);
1438c2ecf20Sopenharmony_ciextern void apic_intr_mode_select(void);
1448c2ecf20Sopenharmony_ciextern void apic_intr_mode_init(void);
1458c2ecf20Sopenharmony_ciextern void init_apic_mappings(void);
1468c2ecf20Sopenharmony_civoid register_lapic_address(unsigned long address);
1478c2ecf20Sopenharmony_ciextern void setup_boot_APIC_clock(void);
1488c2ecf20Sopenharmony_ciextern void setup_secondary_APIC_clock(void);
1498c2ecf20Sopenharmony_ciextern void lapic_update_tsc_freq(void);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
1528c2ecf20Sopenharmony_cistatic inline int apic_force_enable(unsigned long addr)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	return -1;
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci#else
1578c2ecf20Sopenharmony_ciextern int apic_force_enable(unsigned long addr);
1588c2ecf20Sopenharmony_ci#endif
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ciextern void apic_ap_setup(void);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/*
1638c2ecf20Sopenharmony_ci * On 32bit this is mach-xxx local
1648c2ecf20Sopenharmony_ci */
1658c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
1668c2ecf20Sopenharmony_ciextern int apic_is_clustered_box(void);
1678c2ecf20Sopenharmony_ci#else
1688c2ecf20Sopenharmony_cistatic inline int apic_is_clustered_box(void)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	return 0;
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci#endif
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ciextern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
1758c2ecf20Sopenharmony_ciextern void lapic_assign_system_vectors(void);
1768c2ecf20Sopenharmony_ciextern void lapic_assign_legacy_vector(unsigned int isairq, bool replace);
1778c2ecf20Sopenharmony_ciextern void lapic_update_legacy_vectors(void);
1788c2ecf20Sopenharmony_ciextern void lapic_online(void);
1798c2ecf20Sopenharmony_ciextern void lapic_offline(void);
1808c2ecf20Sopenharmony_ciextern bool apic_needs_pit(void);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ciextern void apic_send_IPI_allbutself(unsigned int vector);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci#else /* !CONFIG_X86_LOCAL_APIC */
1858c2ecf20Sopenharmony_cistatic inline void lapic_shutdown(void) { }
1868c2ecf20Sopenharmony_ci#define local_apic_timer_c2_ok		1
1878c2ecf20Sopenharmony_cistatic inline void init_apic_mappings(void) { }
1888c2ecf20Sopenharmony_cistatic inline void disable_local_APIC(void) { }
1898c2ecf20Sopenharmony_ci# define setup_boot_APIC_clock x86_init_noop
1908c2ecf20Sopenharmony_ci# define setup_secondary_APIC_clock x86_init_noop
1918c2ecf20Sopenharmony_cistatic inline void lapic_update_tsc_freq(void) { }
1928c2ecf20Sopenharmony_cistatic inline void init_bsp_APIC(void) { }
1938c2ecf20Sopenharmony_cistatic inline void apic_intr_mode_select(void) { }
1948c2ecf20Sopenharmony_cistatic inline void apic_intr_mode_init(void) { }
1958c2ecf20Sopenharmony_cistatic inline void lapic_assign_system_vectors(void) { }
1968c2ecf20Sopenharmony_cistatic inline void lapic_assign_legacy_vector(unsigned int i, bool r) { }
1978c2ecf20Sopenharmony_cistatic inline bool apic_needs_pit(void) { return true; }
1988c2ecf20Sopenharmony_ci#endif /* !CONFIG_X86_LOCAL_APIC */
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X2APIC
2018c2ecf20Sopenharmony_cistatic inline void native_apic_msr_write(u32 reg, u32 v)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
2048c2ecf20Sopenharmony_ci	    reg == APIC_LVR)
2058c2ecf20Sopenharmony_ci		return;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic inline void native_apic_msr_eoi_write(u32 reg, u32 v)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	__wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic inline u32 native_apic_msr_read(u32 reg)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	u64 msr;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (reg == APIC_DFR)
2208c2ecf20Sopenharmony_ci		return -1;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	rdmsrl(APIC_BASE_MSR + (reg >> 4), msr);
2238c2ecf20Sopenharmony_ci	return (u32)msr;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic inline void native_x2apic_wait_icr_idle(void)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	/* no need to wait for icr idle in x2apic */
2298c2ecf20Sopenharmony_ci	return;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic inline u32 native_safe_x2apic_wait_icr_idle(void)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	/* no need to wait for icr idle in x2apic */
2358c2ecf20Sopenharmony_ci	return 0;
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic inline void native_x2apic_icr_write(u32 low, u32 id)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic inline u64 native_x2apic_icr_read(void)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	unsigned long val;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
2488c2ecf20Sopenharmony_ci	return val;
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ciextern int x2apic_mode;
2528c2ecf20Sopenharmony_ciextern int x2apic_phys;
2538c2ecf20Sopenharmony_ciextern void __init x2apic_set_max_apicid(u32 apicid);
2548c2ecf20Sopenharmony_ciextern void __init check_x2apic(void);
2558c2ecf20Sopenharmony_ciextern void x2apic_setup(void);
2568c2ecf20Sopenharmony_cistatic inline int x2apic_enabled(void)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	return boot_cpu_has(X86_FEATURE_X2APIC) && apic_is_x2apic_enabled();
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci#define x2apic_supported()	(boot_cpu_has(X86_FEATURE_X2APIC))
2628c2ecf20Sopenharmony_ci#else /* !CONFIG_X86_X2APIC */
2638c2ecf20Sopenharmony_cistatic inline void check_x2apic(void) { }
2648c2ecf20Sopenharmony_cistatic inline void x2apic_setup(void) { }
2658c2ecf20Sopenharmony_cistatic inline int x2apic_enabled(void) { return 0; }
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci#define x2apic_mode		(0)
2688c2ecf20Sopenharmony_ci#define	x2apic_supported()	(0)
2698c2ecf20Sopenharmony_ci#endif /* !CONFIG_X86_X2APIC */
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistruct irq_data;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci/*
2748c2ecf20Sopenharmony_ci * Copyright 2004 James Cleverdon, IBM.
2758c2ecf20Sopenharmony_ci *
2768c2ecf20Sopenharmony_ci * Generic APIC sub-arch data struct.
2778c2ecf20Sopenharmony_ci *
2788c2ecf20Sopenharmony_ci * Hacked for x86-64 by James Cleverdon from i386 architecture code by
2798c2ecf20Sopenharmony_ci * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
2808c2ecf20Sopenharmony_ci * James Cleverdon.
2818c2ecf20Sopenharmony_ci */
2828c2ecf20Sopenharmony_cistruct apic {
2838c2ecf20Sopenharmony_ci	/* Hotpath functions first */
2848c2ecf20Sopenharmony_ci	void	(*eoi_write)(u32 reg, u32 v);
2858c2ecf20Sopenharmony_ci	void	(*native_eoi_write)(u32 reg, u32 v);
2868c2ecf20Sopenharmony_ci	void	(*write)(u32 reg, u32 v);
2878c2ecf20Sopenharmony_ci	u32	(*read)(u32 reg);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	/* IPI related functions */
2908c2ecf20Sopenharmony_ci	void	(*wait_icr_idle)(void);
2918c2ecf20Sopenharmony_ci	u32	(*safe_wait_icr_idle)(void);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	void	(*send_IPI)(int cpu, int vector);
2948c2ecf20Sopenharmony_ci	void	(*send_IPI_mask)(const struct cpumask *mask, int vector);
2958c2ecf20Sopenharmony_ci	void	(*send_IPI_mask_allbutself)(const struct cpumask *msk, int vec);
2968c2ecf20Sopenharmony_ci	void	(*send_IPI_allbutself)(int vector);
2978c2ecf20Sopenharmony_ci	void	(*send_IPI_all)(int vector);
2988c2ecf20Sopenharmony_ci	void	(*send_IPI_self)(int vector);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/* dest_logical is used by the IPI functions */
3018c2ecf20Sopenharmony_ci	u32	dest_logical;
3028c2ecf20Sopenharmony_ci	u32	disable_esr;
3038c2ecf20Sopenharmony_ci	u32	irq_delivery_mode;
3048c2ecf20Sopenharmony_ci	u32	irq_dest_mode;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	u32	(*calc_dest_apicid)(unsigned int cpu);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	/* ICR related functions */
3098c2ecf20Sopenharmony_ci	u64	(*icr_read)(void);
3108c2ecf20Sopenharmony_ci	void	(*icr_write)(u32 low, u32 high);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* Probe, setup and smpboot functions */
3138c2ecf20Sopenharmony_ci	int	(*probe)(void);
3148c2ecf20Sopenharmony_ci	int	(*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
3158c2ecf20Sopenharmony_ci	int	(*apic_id_valid)(u32 apicid);
3168c2ecf20Sopenharmony_ci	int	(*apic_id_registered)(void);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	bool	(*check_apicid_used)(physid_mask_t *map, int apicid);
3198c2ecf20Sopenharmony_ci	void	(*init_apic_ldr)(void);
3208c2ecf20Sopenharmony_ci	void	(*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
3218c2ecf20Sopenharmony_ci	void	(*setup_apic_routing)(void);
3228c2ecf20Sopenharmony_ci	int	(*cpu_present_to_apicid)(int mps_cpu);
3238c2ecf20Sopenharmony_ci	void	(*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
3248c2ecf20Sopenharmony_ci	int	(*check_phys_apicid_present)(int phys_apicid);
3258c2ecf20Sopenharmony_ci	int	(*phys_pkg_id)(int cpuid_apic, int index_msb);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	u32	(*get_apic_id)(unsigned long x);
3288c2ecf20Sopenharmony_ci	u32	(*set_apic_id)(unsigned int id);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	/* wakeup_secondary_cpu */
3318c2ecf20Sopenharmony_ci	int	(*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	void	(*inquire_remote_apic)(int apicid);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_32
3368c2ecf20Sopenharmony_ci	/*
3378c2ecf20Sopenharmony_ci	 * Called very early during boot from get_smp_config().  It should
3388c2ecf20Sopenharmony_ci	 * return the logical apicid.  x86_[bios]_cpu_to_apicid is
3398c2ecf20Sopenharmony_ci	 * initialized before this function is called.
3408c2ecf20Sopenharmony_ci	 *
3418c2ecf20Sopenharmony_ci	 * If logical apicid can't be determined that early, the function
3428c2ecf20Sopenharmony_ci	 * may return BAD_APICID.  Logical apicid will be configured after
3438c2ecf20Sopenharmony_ci	 * init_apic_ldr() while bringing up CPUs.  Note that NUMA affinity
3448c2ecf20Sopenharmony_ci	 * won't be applied properly during early boot in this case.
3458c2ecf20Sopenharmony_ci	 */
3468c2ecf20Sopenharmony_ci	int (*x86_32_early_logical_apicid)(int cpu);
3478c2ecf20Sopenharmony_ci#endif
3488c2ecf20Sopenharmony_ci	char	*name;
3498c2ecf20Sopenharmony_ci};
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci/*
3528c2ecf20Sopenharmony_ci * Pointer to the local APIC driver in use on this system (there's
3538c2ecf20Sopenharmony_ci * always just one such driver in use - the kernel decides via an
3548c2ecf20Sopenharmony_ci * early probing process which one it picks - and then sticks to it):
3558c2ecf20Sopenharmony_ci */
3568c2ecf20Sopenharmony_ciextern struct apic *apic;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci/*
3598c2ecf20Sopenharmony_ci * APIC drivers are probed based on how they are listed in the .apicdrivers
3608c2ecf20Sopenharmony_ci * section. So the order is important and enforced by the ordering
3618c2ecf20Sopenharmony_ci * of different apic driver files in the Makefile.
3628c2ecf20Sopenharmony_ci *
3638c2ecf20Sopenharmony_ci * For the files having two apic drivers, we use apic_drivers()
3648c2ecf20Sopenharmony_ci * to enforce the order with in them.
3658c2ecf20Sopenharmony_ci */
3668c2ecf20Sopenharmony_ci#define apic_driver(sym)					\
3678c2ecf20Sopenharmony_ci	static const struct apic *__apicdrivers_##sym __used		\
3688c2ecf20Sopenharmony_ci	__aligned(sizeof(struct apic *))			\
3698c2ecf20Sopenharmony_ci	__section(".apicdrivers") = { &sym }
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci#define apic_drivers(sym1, sym2)					\
3728c2ecf20Sopenharmony_ci	static struct apic *__apicdrivers_##sym1##sym2[2] __used	\
3738c2ecf20Sopenharmony_ci	__aligned(sizeof(struct apic *))				\
3748c2ecf20Sopenharmony_ci	__section(".apicdrivers") = { &sym1, &sym2 }
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ciextern struct apic *__apicdrivers[], *__apicdrivers_end[];
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci/*
3798c2ecf20Sopenharmony_ci * APIC functionality to boot other CPUs - only used on SMP:
3808c2ecf20Sopenharmony_ci */
3818c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
3828c2ecf20Sopenharmony_ciextern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip);
3838c2ecf20Sopenharmony_ciextern int lapic_can_unplug_cpu(void);
3848c2ecf20Sopenharmony_ci#endif
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_LOCAL_APIC
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cistatic inline u32 apic_read(u32 reg)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	return apic->read(reg);
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic inline void apic_write(u32 reg, u32 val)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	apic->write(reg, val);
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic inline void apic_eoi(void)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	apic->eoi_write(APIC_EOI, APIC_EOI_ACK);
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistatic inline u64 apic_icr_read(void)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	return apic->icr_read();
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic inline void apic_icr_write(u32 low, u32 high)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	apic->icr_write(low, high);
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic inline void apic_wait_icr_idle(void)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	apic->wait_icr_idle();
4168c2ecf20Sopenharmony_ci}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_cistatic inline u32 safe_apic_wait_icr_idle(void)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	return apic->safe_wait_icr_idle();
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ciextern void __init apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v));
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci#else /* CONFIG_X86_LOCAL_APIC */
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_cistatic inline u32 apic_read(u32 reg) { return 0; }
4288c2ecf20Sopenharmony_cistatic inline void apic_write(u32 reg, u32 val) { }
4298c2ecf20Sopenharmony_cistatic inline void apic_eoi(void) { }
4308c2ecf20Sopenharmony_cistatic inline u64 apic_icr_read(void) { return 0; }
4318c2ecf20Sopenharmony_cistatic inline void apic_icr_write(u32 low, u32 high) { }
4328c2ecf20Sopenharmony_cistatic inline void apic_wait_icr_idle(void) { }
4338c2ecf20Sopenharmony_cistatic inline u32 safe_apic_wait_icr_idle(void) { return 0; }
4348c2ecf20Sopenharmony_cistatic inline void apic_set_eoi_write(void (*eoi_write)(u32 reg, u32 v)) {}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_LOCAL_APIC */
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ciextern void apic_ack_irq(struct irq_data *data);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_cistatic inline void ack_APIC_irq(void)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	/*
4438c2ecf20Sopenharmony_ci	 * ack_APIC_irq() actually gets compiled as a single instruction
4448c2ecf20Sopenharmony_ci	 * ... yummie.
4458c2ecf20Sopenharmony_ci	 */
4468c2ecf20Sopenharmony_ci	apic_eoi();
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic inline bool lapic_vector_set_in_irr(unsigned int vector)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	u32 irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return !!(irr & (1U << (vector % 32)));
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic inline unsigned default_get_apic_id(unsigned long x)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	if (APIC_XAPIC(ver) || boot_cpu_has(X86_FEATURE_EXTD_APICID))
4628c2ecf20Sopenharmony_ci		return (x >> 24) & 0xFF;
4638c2ecf20Sopenharmony_ci	else
4648c2ecf20Sopenharmony_ci		return (x >> 24) & 0x0F;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci/*
4688c2ecf20Sopenharmony_ci * Warm reset vector position:
4698c2ecf20Sopenharmony_ci */
4708c2ecf20Sopenharmony_ci#define TRAMPOLINE_PHYS_LOW		0x467
4718c2ecf20Sopenharmony_ci#define TRAMPOLINE_PHYS_HIGH		0x469
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ciextern void generic_bigsmp_probe(void);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_LOCAL_APIC
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci#include <asm/smp.h>
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci#define APIC_DFR_VALUE	(APIC_DFR_FLAT)
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ciDECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ciextern struct apic apic_noop;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic inline unsigned int read_apic_id(void)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	unsigned int reg = apic_read(APIC_ID);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	return apic->get_apic_id(reg);
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ciextern int default_apic_id_valid(u32 apicid);
4938c2ecf20Sopenharmony_ciextern int default_acpi_madt_oem_check(char *, char *);
4948c2ecf20Sopenharmony_ciextern void default_setup_apic_routing(void);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ciextern u32 apic_default_calc_apicid(unsigned int cpu);
4978c2ecf20Sopenharmony_ciextern u32 apic_flat_calc_apicid(unsigned int cpu);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ciextern bool default_check_apicid_used(physid_mask_t *map, int apicid);
5008c2ecf20Sopenharmony_ciextern void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap);
5018c2ecf20Sopenharmony_ciextern int default_cpu_present_to_apicid(int mps_cpu);
5028c2ecf20Sopenharmony_ciextern int default_check_phys_apicid_present(int phys_apicid);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_LOCAL_APIC */
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
5078c2ecf20Sopenharmony_cibool apic_id_is_primary_thread(unsigned int id);
5088c2ecf20Sopenharmony_civoid apic_smt_update(void);
5098c2ecf20Sopenharmony_ci#else
5108c2ecf20Sopenharmony_cistatic inline bool apic_id_is_primary_thread(unsigned int id) { return false; }
5118c2ecf20Sopenharmony_cistatic inline void apic_smt_update(void) { }
5128c2ecf20Sopenharmony_ci#endif
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_cistruct msi_msg;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_MSI
5178c2ecf20Sopenharmony_civoid x86_vector_msi_compose_msg(struct irq_data *data, struct msi_msg *msg);
5188c2ecf20Sopenharmony_ci#else
5198c2ecf20Sopenharmony_ci# define x86_vector_msi_compose_msg NULL
5208c2ecf20Sopenharmony_ci#endif
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ciextern void ioapic_zap_locks(void);
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci#endif /* _ASM_X86_APIC_H */
525