Pull powerpc fixes from Michael Ellerman: "Fixes marked for stable: - Prevent unlikely crash in copro_calculate_slb() (Frederic Barrat) - cxl: Prevent adapter reset if an active context exists (Vaibhav Jain) Fixes for code merged this cycle: - Fix boot on systems with uncompressed kernel image (Heiner Kallweit) - Drop dump_numa_memory_topology() (Michael Ellerman) - Fix numa topology console print (Aneesh Kumar K.V) - Ignore the pkey system calls for now (Stephen Rothwell)" * tag 'powerpc-4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc: Ignore the pkey system calls for now powerpc: Fix numa topology console print powerpc/mm: Drop dump_numa_memory_topology() cxl: Prevent adapter reset if an active context exists powerpc/boot: Fix boot on systems with uncompressed kernel image powerpc/mm: Prevent unlikely crash in copro_calculate_slb()
Unified · Split
| @@ -220,8 +220,11 @@ What: /sys/class/cxl/<card>/reset · 219 unmodified lines | ||
| 220 | 220 | Date: October 2014 |
| 221 | 221 | Contact: linuxppc-dev@lists.ozlabs.org |
| 222 | 222 | Description: write only |
| 223 | − Writing 1 will issue a PERST to card which may cause the card | |
| 224 | − to reload the FPGA depending on load_image_on_perst. | |
| 223 | + Writing 1 will issue a PERST to card provided there are no | |
| 224 | + contexts active on any one of the card AFUs. This may cause | |
| 225 | + the card to reload the FPGA depending on load_image_on_perst. | |
| 226 | + Writing -1 will do a force PERST irrespective of any active | |
| 227 | + contexts on the card AFUs. | |
| 225 | 228 | Users: https://github.com/ibm-capi/libcxl |
| 226 | 229 | |
| 227 | 230 | What: /sys/class/cxl/<card>/perst_reloads_same_image (not in a guest) |
| @@ -32,9 +32,16 @@ static struct addr_range prep_kernel(void) · 31 unmodified lines | ||
| 32 | 32 | void *addr = 0; |
| 33 | 33 | struct elf_info ei; |
| 34 | 34 | long len; |
| 35 | + int uncompressed_image = 0; | |
| 35 | 36 | |
| 36 | − partial_decompress(vmlinuz_addr, vmlinuz_size, | |
| 37 | + len = partial_decompress(vmlinuz_addr, vmlinuz_size, | |
| 37 | 38 | elfheader, sizeof(elfheader), 0); |
| 39 | + /* assume uncompressed data if -1 is returned */ | |
| 40 | + if (len == -1) { | |
| 41 | + uncompressed_image = 1; | |
| 42 | + memcpy(elfheader, vmlinuz_addr, sizeof(elfheader)); | |
| 43 | + printf("No valid compressed data found, assume uncompressed data\n\r"); | |
| 44 | + } | |
| 38 | 45 | |
| 39 | 46 | if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei)) |
| 40 | 47 | fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); |
| @@ -67,6 +74,13 @@ static struct addr_range prep_kernel(void) · 26 unmodified lines | ||
| 67 | 74 | "device tree\n\r"); |
| 68 | 75 | } |
| 69 | 76 | |
| 77 | + if (uncompressed_image) { | |
| 78 | + memcpy(addr, vmlinuz_addr + ei.elfoffset, ei.loadsize); | |
| 79 | + printf("0x%lx bytes of uncompressed data copied\n\r", | |
| 80 | + ei.loadsize); | |
| 81 | + goto out; | |
| 82 | + } | |
| 83 | + | |
| 70 | 84 | /* Finally, decompress the kernel */ |
| 71 | 85 | printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr, |
| 72 | 86 | vmlinuz_addr, vmlinuz_addr+vmlinuz_size); |
| @@ -82,7 +96,7 @@ static struct addr_range prep_kernel(void) · 9 unmodified lines | ||
| 82 | 96 | len, ei.loadsize); |
| 83 | 97 | |
| 84 | 98 | printf("Done! Decompressed 0x%lx bytes\n\r", len); |
| 85 | − | |
| 99 | +out: | |
| 86 | 100 | flush_cache(addr, ei.loadsize); |
| 87 | 101 | |
| 88 | 102 | return (struct addr_range){addr, ei.memsize}; |
| @@ -16,6 +16,10 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #define __NR__exit __NR_exit |
| 18 | 18 | |
| 19 | +#define __IGNORE_pkey_mprotect | |
| 20 | +#define __IGNORE_pkey_alloc | |
| 21 | +#define __IGNORE_pkey_free | |
| 22 | + | |
| 19 | 23 | #ifndef __ASSEMBLY__ |
| 20 | 24 | |
| 21 | 25 | #include <linux/types.h> |
| @@ -106,6 +106,8 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb) · 105 unmodified lines | ||
| 106 | 106 | switch (REGION_ID(ea)) { |
| 107 | 107 | case USER_REGION_ID: |
| 108 | 108 | pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea); |
| 109 | + if (mm == NULL) | |
| 110 | + return 1; | |
| 109 | 111 | psize = get_slice_psize(mm, ea); |
| 110 | 112 | ssize = user_segment_size(ea); |
| 111 | 113 | vsid = get_vsid(mm->context.id, ea, ssize); |
| @@ -845,7 +845,7 @@ void __init dump_numa_cpu_topology(void) · 844 unmodified lines | ||
| 845 | 845 | return; |
| 846 | 846 | |
| 847 | 847 | for_each_online_node(node) { |
| 848 | − printk(KERN_DEBUG "Node %d CPUs:", node); | |
| 848 | + pr_info("Node %d CPUs:", node); | |
| 849 | 849 | |
| 850 | 850 | count = 0; |
| 851 | 851 | /* |
| @@ -856,52 +856,18 @@ void __init dump_numa_cpu_topology(void) · 4 unmodified lines | ||
| 856 | 856 | if (cpumask_test_cpu(cpu, |
| 857 | 857 | node_to_cpumask_map[node])) { |
| 858 | 858 | if (count == 0) |
| 859 | − printk(" %u", cpu); | |
| 859 | + pr_cont(" %u", cpu); | |
| 860 | 860 | ++count; |
| 861 | 861 | } else { |
| 862 | 862 | if (count > 1) |
| 863 | − printk("-%u", cpu - 1); | |
| 863 | + pr_cont("-%u", cpu - 1); | |
| 864 | 864 | count = 0; |
| 865 | 865 | } |
| 866 | 866 | } |
| 867 | 867 | |
| 868 | 868 | if (count > 1) |
| 869 | − printk("-%u", nr_cpu_ids - 1); | |
| 870 | − printk("\n"); | |
| 871 | − } | |
| 872 | −} | |
| 873 | − | |
| 874 | −static void __init dump_numa_memory_topology(void) | |
| 875 | −{ | |
| 876 | − unsigned int node; | |
| 877 | − unsigned int count; | |
| 878 | − | |
| 879 | − if (min_common_depth == -1 || !numa_enabled) | |
| 880 | − return; | |
| 881 | − | |
| 882 | − for_each_online_node(node) { | |
| 883 | − unsigned long i; | |
| 884 | − | |
| 885 | − printk(KERN_DEBUG "Node %d Memory:", node); | |
| 886 | − | |
| 887 | − count = 0; | |
| 888 | − | |
| 889 | − for (i = 0; i < memblock_end_of_DRAM(); | |
| 890 | − i += (1 << SECTION_SIZE_BITS)) { | |
| 891 | − if (early_pfn_to_nid(i >> PAGE_SHIFT) == node) { | |
| 892 | − if (count == 0) | |
| 893 | − printk(" 0x%lx", i); | |
| 894 | − ++count; | |
| 895 | − } else { | |
| 896 | − if (count > 0) | |
| 897 | − printk("-0x%lx", i); | |
| 898 | − count = 0; | |
| 899 | − } | |
| 900 | − } | |
| 901 | − | |
| 902 | − if (count > 0) | |
| 903 | − printk("-0x%lx", i); | |
| 904 | − printk("\n"); | |
| 869 | + pr_cont("-%u", nr_cpu_ids - 1); | |
| 870 | + pr_cont("\n"); | |
| 905 | 871 | } |
| 906 | 872 | } |
| 907 | 873 | |
| @@ -947,8 +913,6 @@ void __init initmem_init(void) · 39 unmodified lines | ||
| 947 | 913 | |
| 948 | 914 | if (parse_numa_properties()) |
| 949 | 915 | setup_nonnuma(); |
| 950 | − else | |
| 951 | − dump_numa_memory_topology(); | |
| 952 | 916 | |
| 953 | 917 | memblock_dump_all(); |
| 954 | 918 | |
| @@ -229,6 +229,14 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, · 228 unmodified lines | ||
| 229 | 229 | if (ctx->status == STARTED) |
| 230 | 230 | goto out; /* already started */ |
| 231 | 231 | |
| 232 | + /* | |
| 233 | + * Increment the mapped context count for adapter. This also checks | |
| 234 | + * if adapter_context_lock is taken. | |
| 235 | + */ | |
| 236 | + rc = cxl_adapter_context_get(ctx->afu->adapter); | |
| 237 | + if (rc) | |
| 238 | + goto out; | |
| 239 | + | |
| 232 | 240 | if (task) { |
| 233 | 241 | ctx->pid = get_task_pid(task, PIDTYPE_PID); |
| 234 | 242 | ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID); |
| @@ -240,6 +248,7 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, · 5 unmodified lines | ||
| 240 | 248 | |
| 241 | 249 | if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { |
| 242 | 250 | put_pid(ctx->pid); |
| 251 | + cxl_adapter_context_put(ctx->afu->adapter); | |
| 243 | 252 | cxl_ctx_put(); |
| 244 | 253 | goto out; |
| 245 | 254 | } |
| @@ -238,6 +238,9 @@ int __detach_context(struct cxl_context *ctx) · 237 unmodified lines | ||
| 238 | 238 | put_pid(ctx->glpid); |
| 239 | 239 | |
| 240 | 240 | cxl_ctx_put(); |
| 241 | + | |
| 242 | + /* Decrease the attached context count on the adapter */ | |
| 243 | + cxl_adapter_context_put(ctx->afu->adapter); | |
| 241 | 244 | return 0; |
| 242 | 245 | } |
| 243 | 246 | |
| @@ -618,6 +618,14 @@ struct cxl { · 617 unmodified lines | ||
| 618 | 618 | bool perst_select_user; |
| 619 | 619 | bool perst_same_image; |
| 620 | 620 | bool psl_timebase_synced; |
| 621 | + | |
| 622 | + /* | |
| 623 | + * number of contexts mapped on to this card. Possible values are: | |
| 624 | + * >0: Number of contexts mapped and new one can be mapped. | |
| 625 | + * 0: No active contexts and new ones can be mapped. | |
| 626 | + * -1: No contexts mapped and new ones cannot be mapped. | |
| 627 | + */ | |
| 628 | + atomic_t contexts_num; | |
| 621 | 629 | }; |
| 622 | 630 | |
| 623 | 631 | int cxl_pci_alloc_one_irq(struct cxl *adapter); |
| @@ -944,4 +952,20 @@ bool cxl_pci_is_vphb_device(struct pci_dev *dev); · 320 unmodified lines | ||
| 944 | 952 | |
| 945 | 953 | /* decode AFU error bits in the PSL register PSL_SERR_An */ |
| 946 | 954 | void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr); |
| 955 | + | |
| 956 | +/* | |
| 957 | + * Increments the number of attached contexts on an adapter. | |
| 958 | + * In case an adapter_context_lock is taken the return -EBUSY. | |
| 959 | + */ | |
| 960 | +int cxl_adapter_context_get(struct cxl *adapter); | |
| 961 | + | |
| 962 | +/* Decrements the number of attached contexts on an adapter */ | |
| 963 | +void cxl_adapter_context_put(struct cxl *adapter); | |
| 964 | + | |
| 965 | +/* If no active contexts then prevents contexts from being attached */ | |
| 966 | +int cxl_adapter_context_lock(struct cxl *adapter); | |
| 967 | + | |
| 968 | +/* Unlock the contexts-lock if taken. Warn and force unlock otherwise */ | |
| 969 | +void cxl_adapter_context_unlock(struct cxl *adapter); | |
| 970 | + | |
| 947 | 971 | #endif |
| @@ -205,11 +205,22 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, · 204 unmodified lines | ||
| 205 | 205 | ctx->pid = get_task_pid(current, PIDTYPE_PID); |
| 206 | 206 | ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID); |
| 207 | 207 | |
| 208 | + /* | |
| 209 | + * Increment the mapped context count for adapter. This also checks | |
| 210 | + * if adapter_context_lock is taken. | |
| 211 | + */ | |
| 212 | + rc = cxl_adapter_context_get(ctx->afu->adapter); | |
| 213 | + if (rc) { | |
| 214 | + afu_release_irqs(ctx, ctx); | |
| 215 | + goto out; | |
| 216 | + } | |
| 217 | + | |
| 208 | 218 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); |
| 209 | 219 | |
| 210 | 220 | if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, |
| 211 | 221 | amr))) { |
| 212 | 222 | afu_release_irqs(ctx, ctx); |
| 223 | + cxl_adapter_context_put(ctx->afu->adapter); | |
| 213 | 224 | goto out; |
| 214 | 225 | } |
| 215 | 226 | |
| @@ -1152,6 +1152,9 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic · 1151 unmodified lines | ||
| 1152 | 1152 | if ((rc = cxl_sysfs_adapter_add(adapter))) |
| 1153 | 1153 | goto err_put1; |
| 1154 | 1154 | |
| 1155 | + /* release the context lock as the adapter is configured */ | |
| 1156 | + cxl_adapter_context_unlock(adapter); | |
| 1157 | + | |
| 1155 | 1158 | return adapter; |
| 1156 | 1159 | |
| 1157 | 1160 | err_put1: |
| @@ -243,8 +243,10 @@ struct cxl *cxl_alloc_adapter(void) · 242 unmodified lines | ||
| 243 | 243 | if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num)) |
| 244 | 244 | goto err2; |
| 245 | 245 | |
| 246 | − return adapter; | |
| 246 | + /* start with context lock taken */ | |
| 247 | + atomic_set(&adapter->contexts_num, -1); | |
| 247 | 248 | |
| 249 | + return adapter; | |
| 248 | 250 | err2: |
| 249 | 251 | cxl_remove_adapter_nr(adapter); |
| 250 | 252 | err1: |
| @@ -286,6 +288,44 @@ int cxl_afu_select_best_mode(struct cxl_afu *afu) · 35 unmodified lines | ||
| 286 | 288 | return 0; |
| 287 | 289 | } |
| 288 | 290 | |
| 291 | +int cxl_adapter_context_get(struct cxl *adapter) | |
| 292 | +{ | |
| 293 | + int rc; | |
| 294 | + | |
| 295 | + rc = atomic_inc_unless_negative(&adapter->contexts_num); | |
| 296 | + return rc >= 0 ? 0 : -EBUSY; | |
| 297 | +} | |
| 298 | + | |
| 299 | +void cxl_adapter_context_put(struct cxl *adapter) | |
| 300 | +{ | |
| 301 | + atomic_dec_if_positive(&adapter->contexts_num); | |
| 302 | +} | |
| 303 | + | |
| 304 | +int cxl_adapter_context_lock(struct cxl *adapter) | |
| 305 | +{ | |
| 306 | + int rc; | |
| 307 | + /* no active contexts -> contexts_num == 0 */ | |
| 308 | + rc = atomic_cmpxchg(&adapter->contexts_num, 0, -1); | |
| 309 | + return rc ? -EBUSY : 0; | |
| 310 | +} | |
| 311 | + | |
| 312 | +void cxl_adapter_context_unlock(struct cxl *adapter) | |
| 313 | +{ | |
| 314 | + int val = atomic_cmpxchg(&adapter->contexts_num, -1, 0); | |
| 315 | + | |
| 316 | + /* | |
| 317 | + * contexts lock taken -> contexts_num == -1 | |
| 318 | + * If not true then show a warning and force reset the lock. | |
| 319 | + * This will happen when context_unlock was requested without | |
| 320 | + * doing a context_lock. | |
| 321 | + */ | |
| 322 | + if (val != -1) { | |
| 323 | + atomic_set(&adapter->contexts_num, 0); | |
| 324 | + WARN(1, "Adapter context unlocked with %d active contexts", | |
| 325 | + val); | |
| 326 | + } | |
| 327 | +} | |
| 328 | + | |
| 289 | 329 | static int __init init_cxl(void) |
| 290 | 330 | { |
| 291 | 331 | int rc = 0; |
| @@ -1487,6 +1487,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) · 1486 unmodified lines | ||
| 1487 | 1487 | if ((rc = cxl_native_register_psl_err_irq(adapter))) |
| 1488 | 1488 | goto err; |
| 1489 | 1489 | |
| 1490 | + /* Release the context lock as adapter is configured */ | |
| 1491 | + cxl_adapter_context_unlock(adapter); | |
| 1490 | 1492 | return 0; |
| 1491 | 1493 | |
| 1492 | 1494 | err: |
| @@ -75,12 +75,31 @@ static ssize_t reset_adapter_store(struct device *device, · 74 unmodified lines | ||
| 75 | 75 | int val; |
| 76 | 76 | |
| 77 | 77 | rc = sscanf(buf, "%i", &val); |
| 78 | − if ((rc != 1) || (val != 1)) | |
| 78 | + if ((rc != 1) || (val != 1 && val != -1)) | |
| 79 | 79 | return -EINVAL; |
| 80 | 80 | |
| 81 | − if ((rc = cxl_ops->adapter_reset(adapter))) | |
| 82 | − return rc; | |
| 83 | − return count; | |
| 81 | + /* | |
| 82 | + * See if we can lock the context mapping that's only allowed | |
| 83 | + * when there are no contexts attached to the adapter. Once | |
| 84 | + * taken this will also prevent any context from getting activated. | |
| 85 | + */ | |
| 86 | + if (val == 1) { | |
| 87 | + rc = cxl_adapter_context_lock(adapter); | |
| 88 | + if (rc) | |
| 89 | + goto out; | |
| 90 | + | |
| 91 | + rc = cxl_ops->adapter_reset(adapter); | |
| 92 | + /* In case reset failed release context lock */ | |
| 93 | + if (rc) | |
| 94 | + cxl_adapter_context_unlock(adapter); | |
| 95 | + | |
| 96 | + } else if (val == -1) { | |
| 97 | + /* Perform a forced adapter reset */ | |
| 98 | + rc = cxl_ops->adapter_reset(adapter); | |
| 99 | + } | |
| 100 | + | |
| 101 | +out: | |
| 102 | + return rc ? rc : count; | |
| 84 | 103 | } |
| 85 | 104 | |
| 86 | 105 | static ssize_t load_image_on_perst_show(struct device *device, |