/* * hal_arch.c - Implementation of generic Inter-Processor-Interrupt API for TSAR-MIPS32 * * Authors Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH.is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH.is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH.; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////////////////////// // This global varible define the TSAR architecture specific XCU device decriptor, // that is replicated in all clusters. ///////////////////////////////////////////////////////////////////////////////////////////// static void cpu_default_irq_handler(struct irq_action_s *action) { unsigned int irq_num = (unsigned int) action->data; isr_dmsg(WARNING, "WARNING: No registered handler fo IRQ %d on CPU %d\n", irq_num, cpu_get_id()); cpu_disable_single_irq(irq_num, NULL); isr_dmsg(WARNING, "WARNING: IRQ %d on CPU %d has been masked\n", irq_num, cpu_get_id()); } ////////////////////////////////////// error_t arch_cpu_init( core_t * core ) { register int i; register struct irq_action_s *action_ptr; kmem_req_t req; req.type = KMEM_GENERIC; req.size = sizeof(*action_ptr); req.flags = AF_BOOT | AF_ZERO; for(i=1; i < CPU_IRQ_NR; i++) { if((action_ptr = kmem_alloc(&req)) == NULL) return ENOMEM; action_ptr->irq_handler = &cpu_default_irq_handler; action_ptr->data = (void *) i; arch_cpu_set_irq_entry(cpu, i, action_ptr); } return 0; } //////////////////////////////////////////////// error_t arch_cpu_set_irq_entry( core_t * core, uint32_t irq_nr, struct irq_action_s *action ) { core->arch.irq_vector[irq_nr] = action; return 0; } //////////////////////////////////////////////// error_t arch_cpu_get_irq_entry( core_t * core, uint32_t irq_nr, struct irq_action_s **action) { *action = cpu->arch.irq_vector[irq_nr]; return 0; } //////////////////////////////////////////// error_t arch_set_power_state( core_t * core, arch_power_state_t state) { switch(state) { case ARCH_PWR_IDLE: cpu_power_idle(); return 0; case ARCH_PWR_SLEEP: case ARCH_PWR_SHUTDOWN: printk(WARNING, "WARNING: Unexpected power state (%d) has been asked for CPU %d, of Cluster %d\n", state, cpu->lid, cpu->cluster->id); return 0; default: printk(ERROR, "ERROR: Unknown power state (%d) has been asked for CPU %d, of Cluster %d\n", state, cpu->lid, cpu->cluster->id); return EINVAL; } } ///////////////////////// sint_t arch_barrier_init(struct cluster_s *cluster, struct event_s *event, uint_t count) { return soclib_xicu_barrier_init(get_arch_entry(cluster->id)->xicu, event, count); } ////////////////////////// sint_t arch_barrier_wait(struct cluster_s *cluster, uint_t barrier_id) { return soclib_xicu_barrier_wait(get_arch_entry(cluster->id)->xicu, barrier_id); } ///////////////////////////// error_t arch_barrier_destroy(struct cluster_s *cluster, uint_t barrier_id) { return soclib_xicu_barrier_destroy(get_arch_entry(cluster->id)->xicu, barrier_id); } /////////////////////////////////// error_t hal_send_ipi( cxy_t cxy, lid_t lid, uint32_t val ) { // check arguments // get local pointer on target XCU device device_t * ptr = xcu_device return soclib_xicu_ipi_send(get_arch_entry(cid)->xicu, lid, val); }