···9797 * boot up and this data does not change there after. Hence this9898 * operation should be safe. No locking required.9999 */100100- addr = __pa(per_cpu_ptr(crash_notes, cpunum));100100+ addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));101101 rc = sprintf(buf, "%Lx\n", addr);102102 return rc;103103}
···1563156315641564#ifdef CONFIG_FAIR_GROUP_SCHED1565156515661566-struct update_shares_data {15671567- unsigned long rq_weight[NR_CPUS];15681568-};15691569-15701570-static DEFINE_PER_CPU(struct update_shares_data, update_shares_data);15661566+static __read_mostly unsigned long *update_shares_data;1571156715721568static void __set_se_shares(struct sched_entity *se, unsigned long shares);15731569···15731577static void update_group_shares_cpu(struct task_group *tg, int cpu,15741578 unsigned long sd_shares,15751579 unsigned long sd_rq_weight,15761576- struct update_shares_data *usd)15801580+ unsigned long *usd_rq_weight)15771581{15781582 unsigned long shares, rq_weight;15791583 int boost = 0;1580158415811581- rq_weight = usd->rq_weight[cpu];15851585+ rq_weight = usd_rq_weight[cpu];15821586 if (!rq_weight) {15831587 boost = 1;15841588 rq_weight = NICE_0_LOAD;···16131617static int tg_shares_up(struct task_group *tg, void *data)16141618{16151619 unsigned long weight, rq_weight = 0, shares = 0;16161616- struct update_shares_data *usd;16201620+ unsigned long *usd_rq_weight;16171621 struct sched_domain *sd = data;16181622 unsigned long flags;16191623 int i;···16221626 return 0;1623162716241628 local_irq_save(flags);16251625- usd = &__get_cpu_var(update_shares_data);16291629+ usd_rq_weight = per_cpu_ptr(update_shares_data, smp_processor_id());1626163016271631 for_each_cpu(i, sched_domain_span(sd)) {16281632 weight = tg->cfs_rq[i]->load.weight;16291629- usd->rq_weight[i] = weight;16331633+ usd_rq_weight[i] = weight;1630163416311635 /*16321636 * If there are currently no tasks on the cpu pretend there···16471651 shares = tg->shares;1648165216491653 for_each_cpu(i, sched_domain_span(sd))16501650- update_group_shares_cpu(tg, i, shares, rq_weight, usd);16541654+ update_group_shares_cpu(tg, i, shares, rq_weight, usd_rq_weight);1651165516521656 local_irq_restore(flags);16531657···94029406#endif /* CONFIG_USER_SCHED */94039407#endif /* CONFIG_GROUP_SCHED */9404940894099409+#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP94109410+ update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),94119411+ __alignof__(unsigned long));94129412+#endif94059413 for_each_possible_cpu(i) {94069414 struct rq *rq;94079415
+114-48
mm/percpu.c
···7272#include <asm/cacheflush.h>7373#include <asm/sections.h>7474#include <asm/tlbflush.h>7575+#include <asm/io.h>75767677#define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */7778#define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */···152151 *153152 * During allocation, pcpu_alloc_mutex is kept locked all the time and154153 * pcpu_lock is grabbed and released as necessary. All actual memory155155- * allocations are done using GFP_KERNEL with pcpu_lock released.154154+ * allocations are done using GFP_KERNEL with pcpu_lock released. In155155+ * general, percpu memory can't be allocated with irq off but156156+ * irqsave/restore are still used in alloc path so that it can be used157157+ * from early init path - sched_init() specifically.156158 *157159 * Free path accesses and alters only the index data structures, so it158160 * can be safely called from atomic context. When memory needs to be···354350}355351356352/**357357- * pcpu_extend_area_map - extend area map for allocation358358- * @chunk: target chunk353353+ * pcpu_need_to_extend - determine whether chunk area map needs to be extended354354+ * @chunk: chunk of interest359355 *360360- * Extend area map of @chunk so that it can accomodate an allocation.361361- * A single allocation can split an area into three areas, so this362362- * function makes sure that @chunk->map has at least two extra slots.356356+ * Determine whether area map of @chunk needs to be extended to357357+ * accomodate a new allocation.363358 *364359 * CONTEXT:365365- * pcpu_alloc_mutex, pcpu_lock. pcpu_lock is released and reacquired366366- * if area map is extended.360360+ * pcpu_lock.367361 *368362 * RETURNS:369369- * 0 if noop, 1 if successfully extended, -errno on failure.363363+ * New target map allocation length if extension is necessary, 0364364+ * otherwise.370365 */371371-static int pcpu_extend_area_map(struct pcpu_chunk *chunk)372372- __releases(lock) __acquires(lock)366366+static int pcpu_need_to_extend(struct pcpu_chunk *chunk)373367{374368 int new_alloc;375375- int *new;376376- size_t size;377369378378- /* has enough? */379370 if (chunk->map_alloc >= chunk->map_used + 2)380371 return 0;381381-382382- spin_unlock_irq(&pcpu_lock);383372384373 new_alloc = PCPU_DFL_MAP_ALLOC;385374 while (new_alloc < chunk->map_used + 2)386375 new_alloc *= 2;387376388388- new = pcpu_mem_alloc(new_alloc * sizeof(new[0]));389389- if (!new) {390390- spin_lock_irq(&pcpu_lock);377377+ return new_alloc;378378+}379379+380380+/**381381+ * pcpu_extend_area_map - extend area map of a chunk382382+ * @chunk: chunk of interest383383+ * @new_alloc: new target allocation length of the area map384384+ *385385+ * Extend area map of @chunk to have @new_alloc entries.386386+ *387387+ * CONTEXT:388388+ * Does GFP_KERNEL allocation. Grabs and releases pcpu_lock.389389+ *390390+ * RETURNS:391391+ * 0 on success, -errno on failure.392392+ */393393+static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc)394394+{395395+ int *old = NULL, *new = NULL;396396+ size_t old_size = 0, new_size = new_alloc * sizeof(new[0]);397397+ unsigned long flags;398398+399399+ new = pcpu_mem_alloc(new_size);400400+ if (!new)391401 return -ENOMEM;392392- }393402394394- /*395395- * Acquire pcpu_lock and switch to new area map. Only free396396- * could have happened inbetween, so map_used couldn't have397397- * grown.398398- */399399- spin_lock_irq(&pcpu_lock);400400- BUG_ON(new_alloc < chunk->map_used + 2);403403+ /* acquire pcpu_lock and switch to new area map */404404+ spin_lock_irqsave(&pcpu_lock, flags);401405402402- size = chunk->map_alloc * sizeof(chunk->map[0]);403403- memcpy(new, chunk->map, size);406406+ if (new_alloc <= chunk->map_alloc)407407+ goto out_unlock;408408+409409+ old_size = chunk->map_alloc * sizeof(chunk->map[0]);410410+ memcpy(new, chunk->map, old_size);404411405412 /*406413 * map_alloc < PCPU_DFL_MAP_ALLOC indicates that the chunk is407414 * one of the first chunks and still using static map.408415 */409416 if (chunk->map_alloc >= PCPU_DFL_MAP_ALLOC)410410- pcpu_mem_free(chunk->map, size);417417+ old = chunk->map;411418412419 chunk->map_alloc = new_alloc;413420 chunk->map = new;421421+ new = NULL;422422+423423+out_unlock:424424+ spin_unlock_irqrestore(&pcpu_lock, flags);425425+426426+ /*427427+ * pcpu_mem_free() might end up calling vfree() which uses428428+ * IRQ-unsafe lock and thus can't be called under pcpu_lock.429429+ */430430+ pcpu_mem_free(old, old_size);431431+ pcpu_mem_free(new, new_size);432432+414433 return 0;415434}416435···10721045 static int warn_limit = 10;10731046 struct pcpu_chunk *chunk;10741047 const char *err;10751075- int slot, off;10481048+ int slot, off, new_alloc;10491049+ unsigned long flags;1076105010771051 if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) {10781052 WARN(true, "illegal size (%zu) or align (%zu) for "···10821054 }1083105510841056 mutex_lock(&pcpu_alloc_mutex);10851085- spin_lock_irq(&pcpu_lock);10571057+ spin_lock_irqsave(&pcpu_lock, flags);1086105810871059 /* serve reserved allocations from the reserved chunk if available */10881060 if (reserved && pcpu_reserved_chunk) {10891061 chunk = pcpu_reserved_chunk;10901090- if (size > chunk->contig_hint ||10911091- pcpu_extend_area_map(chunk) < 0) {10921092- err = "failed to extend area map of reserved chunk";10621062+10631063+ if (size > chunk->contig_hint) {10641064+ err = "alloc from reserved chunk failed";10931065 goto fail_unlock;10941066 }10671067+10681068+ while ((new_alloc = pcpu_need_to_extend(chunk))) {10691069+ spin_unlock_irqrestore(&pcpu_lock, flags);10701070+ if (pcpu_extend_area_map(chunk, new_alloc) < 0) {10711071+ err = "failed to extend area map of reserved chunk";10721072+ goto fail_unlock_mutex;10731073+ }10741074+ spin_lock_irqsave(&pcpu_lock, flags);10751075+ }10761076+10951077 off = pcpu_alloc_area(chunk, size, align);10961078 if (off >= 0)10971079 goto area_found;10801080+10981081 err = "alloc from reserved chunk failed";10991082 goto fail_unlock;11001083 }···11171078 if (size > chunk->contig_hint)11181079 continue;1119108011201120- switch (pcpu_extend_area_map(chunk)) {11211121- case 0:11221122- break;11231123- case 1:11241124- goto restart; /* pcpu_lock dropped, restart */11251125- default:11261126- err = "failed to extend area map";11271127- goto fail_unlock;10811081+ new_alloc = pcpu_need_to_extend(chunk);10821082+ if (new_alloc) {10831083+ spin_unlock_irqrestore(&pcpu_lock, flags);10841084+ if (pcpu_extend_area_map(chunk,10851085+ new_alloc) < 0) {10861086+ err = "failed to extend area map";10871087+ goto fail_unlock_mutex;10881088+ }10891089+ spin_lock_irqsave(&pcpu_lock, flags);10901090+ /*10911091+ * pcpu_lock has been dropped, need to10921092+ * restart cpu_slot list walking.10931093+ */10941094+ goto restart;11281095 }1129109611301097 off = pcpu_alloc_area(chunk, size, align);···11401095 }1141109611421097 /* hmmm... no space left, create a new chunk */11431143- spin_unlock_irq(&pcpu_lock);10981098+ spin_unlock_irqrestore(&pcpu_lock, flags);1144109911451100 chunk = alloc_pcpu_chunk();11461101 if (!chunk) {···11481103 goto fail_unlock_mutex;11491104 }1150110511511151- spin_lock_irq(&pcpu_lock);11061106+ spin_lock_irqsave(&pcpu_lock, flags);11521107 pcpu_chunk_relocate(chunk, -1);11531108 goto restart;1154110911551110area_found:11561156- spin_unlock_irq(&pcpu_lock);11111111+ spin_unlock_irqrestore(&pcpu_lock, flags);1157111211581113 /* populate, map and clear the area */11591114 if (pcpu_populate_chunk(chunk, off, size)) {11601160- spin_lock_irq(&pcpu_lock);11151115+ spin_lock_irqsave(&pcpu_lock, flags);11611116 pcpu_free_area(chunk, off);11621117 err = "failed to populate";11631118 goto fail_unlock;···11691124 return __addr_to_pcpu_ptr(chunk->base_addr + off);1170112511711126fail_unlock:11721172- spin_unlock_irq(&pcpu_lock);11271127+ spin_unlock_irqrestore(&pcpu_lock, flags);11731128fail_unlock_mutex:11741129 mutex_unlock(&pcpu_alloc_mutex);11751130 if (warn_limit) {···13001255 spin_unlock_irqrestore(&pcpu_lock, flags);13011256}13021257EXPORT_SYMBOL_GPL(free_percpu);12581258+12591259+/**12601260+ * per_cpu_ptr_to_phys - convert translated percpu address to physical address12611261+ * @addr: the address to be converted to physical address12621262+ *12631263+ * Given @addr which is dereferenceable address obtained via one of12641264+ * percpu access macros, this function translates it into its physical12651265+ * address. The caller is responsible for ensuring @addr stays valid12661266+ * until this function finishes.12671267+ *12681268+ * RETURNS:12691269+ * The physical address for @addr.12701270+ */12711271+phys_addr_t per_cpu_ptr_to_phys(void *addr)12721272+{12731273+ if ((unsigned long)addr < VMALLOC_START ||12741274+ (unsigned long)addr >= VMALLOC_END)12751275+ return __pa(addr);12761276+ else12771277+ return page_to_phys(vmalloc_to_page(addr));12781278+}1303127913041280static inline size_t pcpu_calc_fc_sizes(size_t static_size,13051281 size_t reserved_size,