1 #ifndef __ASM_SMPBOOT_H
2 #define __ASM_SMPBOOT_H
3 
4 /*emum for clustered_apic_mode values*/
5 enum{
6 	CLUSTERED_APIC_NONE = 0,
7 	CLUSTERED_APIC_XAPIC,
8 	CLUSTERED_APIC_NUMAQ
9 };
10 
11 #ifdef CONFIG_X86_CLUSTERED_APIC
12 extern unsigned int apic_broadcast_id;
13 extern unsigned char clustered_apic_mode;
14 extern unsigned char esr_disable;
15 extern unsigned char int_delivery_mode;
16 extern unsigned int int_dest_addr_mode;
17 extern int cyclone_setup(char*);
18 
detect_clustered_apic(char * oem,char * prod)19 static inline void detect_clustered_apic(char* oem, char* prod)
20 {
21 	/*
22 	 * Can't recognize Summit xAPICs at present, so use the OEM ID.
23 	 */
24 	if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "VIGIL SMP", 9)){
25 		clustered_apic_mode = CLUSTERED_APIC_XAPIC;
26 		apic_broadcast_id = APIC_BROADCAST_ID_XAPIC;
27 		int_dest_addr_mode = APIC_DEST_PHYSICAL;
28 		int_delivery_mode = dest_Fixed;
29 		esr_disable = 1;
30 		/*Start cyclone clock*/
31 		cyclone_setup(0);
32 	/* check for ACPI tables */
33 	} else if (!strncmp(oem, "IBM", 3) &&
34 	    (!strncmp(prod, "SERVIGIL", 8) ||
35 	     !strncmp(prod, "EXA", 3) ||
36 	     !strncmp(prod, "RUTHLESS", 8))){
37 		clustered_apic_mode = CLUSTERED_APIC_XAPIC;
38 		apic_broadcast_id = APIC_BROADCAST_ID_XAPIC;
39 		int_dest_addr_mode = APIC_DEST_PHYSICAL;
40 		int_delivery_mode = dest_Fixed;
41 		esr_disable = 1;
42 		/*Start cyclone clock*/
43 		cyclone_setup(0);
44 	} else if (!strncmp(oem, "IBM NUMA", 8)){
45 		clustered_apic_mode = CLUSTERED_APIC_NUMAQ;
46 		apic_broadcast_id = APIC_BROADCAST_ID_APIC;
47 		int_dest_addr_mode = APIC_DEST_LOGICAL;
48 		int_delivery_mode = dest_LowestPrio;
49 		esr_disable = 1;
50 	}
51 }
52 #define	INT_DEST_ADDR_MODE (int_dest_addr_mode)
53 #define	INT_DELIVERY_MODE (int_delivery_mode)
54 #else /* CONFIG_X86_CLUSTERED_APIC */
55 #define apic_broadcast_id (APIC_BROADCAST_ID_APIC)
56 #define clustered_apic_mode (CLUSTERED_APIC_NONE)
57 #define esr_disable (0)
58 #define detect_clustered_apic(x,y)
59 #define INT_DEST_ADDR_MODE (APIC_DEST_LOGICAL)	/* logical delivery */
60 #define INT_DELIVERY_MODE (dest_LowestPrio)
61 #endif /* CONFIG_X86_CLUSTERED_APIC */
62 #define BAD_APICID 0xFFu
63 
64 #define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467)
65 #define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469)
66 
67 #define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid)
68 
69 extern unsigned char raw_phys_apicid[NR_CPUS];
70 
71 /*
72  * How to map from the cpu_present_map
73  */
cpu_present_to_apicid(int mps_cpu)74 static inline int cpu_present_to_apicid(int mps_cpu)
75 {
76 	switch (clustered_apic_mode) {
77 		case CLUSTERED_APIC_XAPIC:
78 			if (mps_cpu >= NR_CPUS)
79 				return BAD_APICID;
80 			else
81 				return raw_phys_apicid[mps_cpu];
82 		case CLUSTERED_APIC_NUMAQ:
83 			return (mps_cpu & ~0x3) << 2 | 1 << (mps_cpu & 0x3);
84 		case CLUSTERED_APIC_NONE:
85 		default:
86 			return mps_cpu;
87 	}
88 }
89 
apicid_to_phys_cpu_present(int apicid)90 static inline unsigned long apicid_to_phys_cpu_present(int apicid)
91 {
92 	if(clustered_apic_mode)
93 		return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3));
94 	return 1UL << apicid;
95 }
96 
97 #define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) )
98 
99 /*
100  * Mappings between logical cpu number and logical / physical apicid
101  * The first four macros are trivial, but it keeps the abstraction consistent
102  */
103 extern volatile int logical_apicid_2_cpu[];
104 extern volatile int cpu_2_logical_apicid[];
105 extern volatile int physical_apicid_2_cpu[];
106 extern volatile int cpu_2_physical_apicid[];
107 
108 #define logical_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
109 #define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu]
110 #define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
111 #define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu]
112 #ifdef CONFIG_MULTIQUAD			/* use logical IDs to bootstrap */
113 #define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
114 #define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu]
115 #else /* !CONFIG_MULTIQUAD */		/* use physical IDs to bootstrap */
116 #define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
117 #define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu]
118 #endif /* CONFIG_MULTIQUAD */
119 
120 #ifdef CONFIG_X86_CLUSTERED_APIC
target_cpus(void)121 static inline int target_cpus(void)
122 {
123 	static int cpu;
124 	switch(clustered_apic_mode){
125 		case CLUSTERED_APIC_NUMAQ:
126 			/* Broadcast intrs to local quad only. */
127 			return APIC_BROADCAST_ID_APIC;
128 		case CLUSTERED_APIC_XAPIC:
129 			/*round robin the interrupts*/
130 			cpu = (cpu+1)%smp_num_cpus;
131 			return cpu_to_physical_apicid(cpu);
132 		default:
133 			return cpu_online_map;
134 	}
135 }
136 #else
137 #define target_cpus() (cpu_online_map)
138 #endif
139 #endif
140