1efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/* 2efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * sfi.c - x86 architecture SFI support. 3efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 4efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * Copyright (c) 2009, Intel Corporation. 5efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 6efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * This program is free software; you can redistribute it and/or modify it 7efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * under the terms and conditions of the GNU General Public License, 8efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * version 2, as published by the Free Software Foundation. 9efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 10efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * This program is distributed in the hope it will be useful, but WITHOUT 11efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * more details. 14efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 15efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * You should have received a copy of the GNU General Public License along with 16efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * this program; if not, write to the Free Software Foundation, Inc., 17efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * 19efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang */ 20efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 21efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#define KMSG_COMPONENT "SFI" 22efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 23efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 24efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/acpi.h> 25efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/init.h> 26efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/sfi.h> 27efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <linux/io.h> 28efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 29efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/io_apic.h> 30efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/mpspec.h> 31efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/setup.h> 32efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#include <asm/apic.h> 33efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 34efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_LOCAL_APIC 35efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; 36efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 37efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/* All CPUs enumerated by SFI must be present and enabled */ 38940b3c7b193ec54141976a8642c00582f423690cThomas Gleixnerstatic void __cpuinit mp_sfi_register_lapic(u8 id) 39efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 40cb2ded37fd2e1039f96c8c892da024a8f033add5Yinghai Lu if (MAX_LOCAL_APIC - id <= 0) { 41efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pr_warning("Processor #%d invalid (max %d)\n", 42cb2ded37fd2e1039f96c8c892da024a8f033add5Yinghai Lu id, MAX_LOCAL_APIC); 43efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return; 44efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang } 45efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 46efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pr_info("registering lapic[%d]\n", id); 47efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 48efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR))); 49efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 50efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 51efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic int __init sfi_parse_cpus(struct sfi_table_header *table) 52efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 53efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_table_simple *sb; 54efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_cpu_table_entry *pentry; 55efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang int i; 56efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang int cpu_num; 57efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 58efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sb = (struct sfi_table_simple *)table; 59efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry); 60efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry = (struct sfi_cpu_table_entry *)sb->pentry; 61efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 62efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang for (i = 0; i < cpu_num; i++) { 63efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang mp_sfi_register_lapic(pentry->apic_id); 64efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry++; 65efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang } 66efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 67efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang smp_found_config = 1; 68efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return 0; 69efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 70efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif /* CONFIG_X86_LOCAL_APIC */ 71efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 72efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_IO_APIC 73efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 74efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangstatic int __init sfi_parse_ioapic(struct sfi_table_header *table) 75efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 76efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_table_simple *sb; 77efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang struct sfi_apic_table_entry *pentry; 78efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang int i, num; 79efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 80efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sb = (struct sfi_table_simple *)table; 81efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry); 82efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry = (struct sfi_apic_table_entry *)sb->pentry; 83efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 84efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang for (i = 0; i < num; i++) { 85a4384df3e24579d6292a1b3b41d500349948f30bEric W. Biederman mp_register_ioapic(i, pentry->phys_addr, gsi_top); 86efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pentry++; 87efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang } 88efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 89efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang WARN(pic_mode, KERN_WARNING 90efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang "SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n"); 91efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang pic_mode = 0; 92efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return 0; 93efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 94efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif /* CONFIG_X86_IO_APIC */ 95efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang 96efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang/* 97efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang * sfi_platform_init(): register lapics & io-apics 98efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang */ 99efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tangint __init sfi_platform_init(void) 100efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang{ 101efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_LOCAL_APIC 10253301f36f316a6519c464b0ef2a155386c20be19Yinghai Lu register_lapic_address(sfi_lapic_addr); 103efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); 104efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif 105efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#ifdef CONFIG_X86_IO_APIC 106efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic); 107efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang#endif 108efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang return 0; 109efafc8b213e67ed148a5b53ade29ee7b48af907dFeng Tang} 110