/** * Copyright (C) ARM Limited 2013-2014. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */ #if GATOR_IKS_SUPPORT #include #include #include #include static bool map_cpuids; static int mpidr_cpuids[NR_CPUS]; static const struct gator_cpu * mpidr_cpus[NR_CPUS]; static int __lcpu_to_pcpu[NR_CPUS]; static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name) { int i; for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) { return gator_cpu; } } return NULL; } static void calc_first_cluster_size(void) { int len; const u32 *val; const char *compatible; struct device_node *cn = NULL; int mpidr_cpuids_count = 0; // Zero is a valid cpuid, so initialize the array to 0xff's memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids)); memset(&mpidr_cpus, 0, sizeof(mpidr_cpus)); while ((cn = of_find_node_by_type(cn, "cpu"))) { BUG_ON(mpidr_cpuids_count >= NR_CPUS); val = of_get_property(cn, "reg", &len); if (!val || len != 4) { pr_err("%s missing reg property\n", cn->full_name); continue; } compatible = of_get_property(cn, "compatible", NULL); if (compatible == NULL) { pr_err("%s missing compatible property\n", cn->full_name); continue; } mpidr_cpuids[mpidr_cpuids_count] = be32_to_cpup(val); mpidr_cpus[mpidr_cpuids_count] = gator_find_cpu_by_dt_name(compatible); ++mpidr_cpuids_count; } map_cpuids = (mpidr_cpuids_count == nr_cpu_ids); } static int linearize_mpidr(int mpidr) { int i; for (i = 0; i < nr_cpu_ids; ++i) { if (mpidr_cpuids[i] == mpidr) { return i; } } BUG(); } int lcpu_to_pcpu(const int lcpu) { int pcpu; if (!map_cpuids) return lcpu; BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0); pcpu = __lcpu_to_pcpu[lcpu]; BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0); return pcpu; } int pcpu_to_lcpu(const int pcpu) { int lcpu; if (!map_cpuids) return pcpu; BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0); for (lcpu = 0; lcpu < nr_cpu_ids; ++lcpu) { if (__lcpu_to_pcpu[lcpu] == pcpu) { BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0); return lcpu; } } BUG(); } static void gator_update_cpu_mapping(u32 cpu_hwid) { int lcpu = smp_processor_id(); int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK); BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0); BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0); __lcpu_to_pcpu[lcpu] = pcpu; } GATOR_DEFINE_PROBE(cpu_migrate_begin, TP_PROTO(u64 timestamp, u32 cpu_hwid)) { const int cpu = get_physical_cpu(); gator_timer_offline((void *)1); gator_timer_offline_dispatch(cpu, true); } GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid)) { int cpu; gator_update_cpu_mapping(cpu_hwid); // get_physical_cpu must be called after gator_update_cpu_mapping cpu = get_physical_cpu(); gator_timer_online_dispatch(cpu, true); gator_timer_online((void *)1); } GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid)) { gator_update_cpu_mapping(cpu_hwid); } static void gator_send_iks_core_names(void) { int cpu; // Send the cpu names preempt_disable(); for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { if (mpidr_cpus[cpu] != NULL) { gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]); } } preempt_enable(); } static int gator_migrate_start(void) { int retval = 0; if (!map_cpuids) return retval; if (retval == 0) retval = GATOR_REGISTER_TRACE(cpu_migrate_begin); if (retval == 0) retval = GATOR_REGISTER_TRACE(cpu_migrate_finish); if (retval == 0) retval = GATOR_REGISTER_TRACE(cpu_migrate_current); if (retval == 0) { // Initialize the logical to physical cpu mapping memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu)); bL_switcher_trace_trigger(); } return retval; } static void gator_migrate_stop(void) { if (!map_cpuids) return; GATOR_UNREGISTER_TRACE(cpu_migrate_current); GATOR_UNREGISTER_TRACE(cpu_migrate_finish); GATOR_UNREGISTER_TRACE(cpu_migrate_begin); } #else #define calc_first_cluster_size() #define gator_send_iks_core_names() #define gator_migrate_start() 0 #define gator_migrate_stop() #endif