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 | Date: October 2014 | 220 | Date: October 2014 |
| 221 | Contact: linuxppc-dev@lists.ozlabs.org | 221 | Contact: linuxppc-dev@lists.ozlabs.org |
| 222 | Description: write only | 222 | Description: write only |
| 223 | Writing 1 will issue a PERST to card which may cause the card | 223 | Writing 1 will issue a PERST to card provided there are no |
| 224 | to reload the FPGA depending on load_image_on_perst. | 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 | Users: https://github.com/ibm-capi/libcxl | 228 | Users: https://github.com/ibm-capi/libcxl |
| 226 | 229 | ||
| 227 | What: /sys/class/cxl/<card>/perst_reloads_same_image (not in a guest) | 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 | void *addr = 0; | 32 | void *addr = 0; |
| 33 | struct elf_info ei; | 33 | struct elf_info ei; |
| 34 | long len; | 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 | elfheader, sizeof(elfheader), 0); | 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 | if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei)) | 46 | if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei)) |
| 40 | fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); | 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 | "device tree\n\r"); | 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 | /* Finally, decompress the kernel */ | 84 | /* Finally, decompress the kernel */ |
| 71 | printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr, | 85 | printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr, |
| 72 | vmlinuz_addr, vmlinuz_addr+vmlinuz_size); | 86 | vmlinuz_addr, vmlinuz_addr+vmlinuz_size); |
| @@ -82,7 +96,7 @@ static struct addr_range prep_kernel(void) · 9 unmodified lines | |||
| 82 | len, ei.loadsize); | 96 | len, ei.loadsize); |
| 83 | 97 | ||
| 84 | printf("Done! Decompressed 0x%lx bytes\n\r", len); | 98 | printf("Done! Decompressed 0x%lx bytes\n\r", len); |
| 85 | 99 | out: | |
| 86 | flush_cache(addr, ei.loadsize); | 100 | flush_cache(addr, ei.loadsize); |
| 87 | 101 | ||
| 88 | return (struct addr_range){addr, ei.memsize}; | 102 | return (struct addr_range){addr, ei.memsize}; |
| @@ -16,6 +16,10 @@ · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | #define __NR__exit __NR_exit | 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 | #ifndef __ASSEMBLY__ | 23 | #ifndef __ASSEMBLY__ |
| 20 | 24 | ||
| 21 | #include <linux/types.h> | 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 | switch (REGION_ID(ea)) { | 106 | switch (REGION_ID(ea)) { |
| 107 | case USER_REGION_ID: | 107 | case USER_REGION_ID: |
| 108 | pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea); | 108 | pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea); |
| 109 | if (mm == NULL) | ||
| 110 | return 1; | ||
| 109 | psize = get_slice_psize(mm, ea); | 111 | psize = get_slice_psize(mm, ea); |
| 110 | ssize = user_segment_size(ea); | 112 | ssize = user_segment_size(ea); |
| 111 | vsid = get_vsid(mm->context.id, ea, ssize); | 113 | vsid = get_vsid(mm->context.id, ea, ssize); |
| @@ -845,7 +845,7 @@ void __init dump_numa_cpu_topology(void) · 844 unmodified lines | |||
| 845 | return; | 845 | return; |
| 846 | 846 | ||
| 847 | for_each_online_node(node) { | 847 | for_each_online_node(node) { |
| 848 | printk(KERN_DEBUG "Node %d CPUs:", node); | 848 | pr_info("Node %d CPUs:", node); |
| 849 | 849 | ||
| 850 | count = 0; | 850 | count = 0; |
| 851 | /* | 851 | /* |
| @@ -856,52 +856,18 @@ void __init dump_numa_cpu_topology(void) · 4 unmodified lines | |||
| 856 | if (cpumask_test_cpu(cpu, | 856 | if (cpumask_test_cpu(cpu, |
| 857 | node_to_cpumask_map[node])) { | 857 | node_to_cpumask_map[node])) { |
| 858 | if (count == 0) | 858 | if (count == 0) |
| 859 | printk(" %u", cpu); | 859 | pr_cont(" %u", cpu); |
| 860 | ++count; | 860 | ++count; |
| 861 | } else { | 861 | } else { |
| 862 | if (count > 1) | 862 | if (count > 1) |
| 863 | printk("-%u", cpu - 1); | 863 | pr_cont("-%u", cpu - 1); |
| 864 | count = 0; | 864 | count = 0; |
| 865 | } | 865 | } |
| 866 | } | 866 | } |
| 867 | 867 | ||
| 868 | if (count > 1) | 868 | if (count > 1) |
| 869 | printk("-%u", nr_cpu_ids - 1); | 869 | pr_cont("-%u", nr_cpu_ids - 1); |
| 870 | printk("\n"); | 870 | pr_cont("\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"); | ||
| 905 | } | 871 | } |
| 906 | } | 872 | } |
| 907 | 873 | ||
| @@ -947,8 +913,6 @@ void __init initmem_init(void) · 39 unmodified lines | |||
| 947 | 913 | ||
| 948 | if (parse_numa_properties()) | 914 | if (parse_numa_properties()) |
| 949 | setup_nonnuma(); | 915 | setup_nonnuma(); |
| 950 | else | ||
| 951 | dump_numa_memory_topology(); | ||
| 952 | 916 | ||
| 953 | memblock_dump_all(); | 917 | memblock_dump_all(); |
| 954 | 918 | ||
| @@ -229,6 +229,14 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, · 228 unmodified lines | |||
| 229 | if (ctx->status == STARTED) | 229 | if (ctx->status == STARTED) |
| 230 | goto out; /* already started */ | 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 | if (task) { | 240 | if (task) { |
| 233 | ctx->pid = get_task_pid(task, PIDTYPE_PID); | 241 | ctx->pid = get_task_pid(task, PIDTYPE_PID); |
| 234 | ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID); | 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 | if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { | 249 | if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { |
| 242 | put_pid(ctx->pid); | 250 | put_pid(ctx->pid); |
| 251 | cxl_adapter_context_put(ctx->afu->adapter); | ||
| 243 | cxl_ctx_put(); | 252 | cxl_ctx_put(); |
| 244 | goto out; | 253 | goto out; |
| 245 | } | 254 | } |
| @@ -238,6 +238,9 @@ int __detach_context(struct cxl_context *ctx) · 237 unmodified lines | |||
| 238 | put_pid(ctx->glpid); | 238 | put_pid(ctx->glpid); |
| 239 | 239 | ||
| 240 | cxl_ctx_put(); | 240 | cxl_ctx_put(); |
| 241 | |||
| 242 | /* Decrease the attached context count on the adapter */ | ||
| 243 | cxl_adapter_context_put(ctx->afu->adapter); | ||
| 241 | return 0; | 244 | return 0; |
| 242 | } | 245 | } |
| 243 | 246 | ||
| @@ -618,6 +618,14 @@ struct cxl { · 617 unmodified lines | |||
| 618 | bool perst_select_user; | 618 | bool perst_select_user; |
| 619 | bool perst_same_image; | 619 | bool perst_same_image; |
| 620 | bool psl_timebase_synced; | 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 | int cxl_pci_alloc_one_irq(struct cxl *adapter); | 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 | /* decode AFU error bits in the PSL register PSL_SERR_An */ | 953 | /* decode AFU error bits in the PSL register PSL_SERR_An */ |
| 946 | void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr); | 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 | #endif | 971 | #endif |
| @@ -205,11 +205,22 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, · 204 unmodified lines | |||
| 205 | ctx->pid = get_task_pid(current, PIDTYPE_PID); | 205 | ctx->pid = get_task_pid(current, PIDTYPE_PID); |
| 206 | ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID); | 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 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); | 218 | trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); |
| 209 | 219 | ||
| 210 | if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, | 220 | if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, |
| 211 | amr))) { | 221 | amr))) { |
| 212 | afu_release_irqs(ctx, ctx); | 222 | afu_release_irqs(ctx, ctx); |
| 223 | cxl_adapter_context_put(ctx->afu->adapter); | ||
| 213 | goto out; | 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 | if ((rc = cxl_sysfs_adapter_add(adapter))) | 1152 | if ((rc = cxl_sysfs_adapter_add(adapter))) |
| 1153 | goto err_put1; | 1153 | goto err_put1; |
| 1154 | 1154 | ||
| 1155 | /* release the context lock as the adapter is configured */ | ||
| 1156 | cxl_adapter_context_unlock(adapter); | ||
| 1157 | |||
| 1155 | return adapter; | 1158 | return adapter; |
| 1156 | 1159 | ||
| 1157 | err_put1: | 1160 | err_put1: |
| @@ -243,8 +243,10 @@ struct cxl *cxl_alloc_adapter(void) · 242 unmodified lines | |||
| 243 | if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num)) | 243 | if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num)) |
| 244 | goto err2; | 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 | err2: | 250 | err2: |
| 249 | cxl_remove_adapter_nr(adapter); | 251 | cxl_remove_adapter_nr(adapter); |
| 250 | err1: | 252 | err1: |
| @@ -286,6 +288,44 @@ int cxl_afu_select_best_mode(struct cxl_afu *afu) · 35 unmodified lines | |||
| 286 | return 0; | 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 | static int __init init_cxl(void) | 329 | static int __init init_cxl(void) |
| 290 | { | 330 | { |
| 291 | int rc = 0; | 331 | int rc = 0; |
| @@ -1487,6 +1487,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) · 1486 unmodified lines | |||
| 1487 | if ((rc = cxl_native_register_psl_err_irq(adapter))) | 1487 | if ((rc = cxl_native_register_psl_err_irq(adapter))) |
| 1488 | goto err; | 1488 | goto err; |
| 1489 | 1489 | ||
| 1490 | /* Release the context lock as adapter is configured */ | ||
| 1491 | cxl_adapter_context_unlock(adapter); | ||
| 1490 | return 0; | 1492 | return 0; |
| 1491 | 1493 | ||
| 1492 | err: | 1494 | err: |
| @@ -75,12 +75,31 @@ static ssize_t reset_adapter_store(struct device *device, · 74 unmodified lines | |||
| 75 | int val; | 75 | int val; |
| 76 | 76 | ||
| 77 | rc = sscanf(buf, "%i", &val); | 77 | rc = sscanf(buf, "%i", &val); |
| 78 | if ((rc != 1) || (val != 1)) | 78 | if ((rc != 1) || (val != 1 && val != -1)) |
| 79 | return -EINVAL; | 79 | return -EINVAL; |
| 80 | 80 | ||
| 81 | if ((rc = cxl_ops->adapter_reset(adapter))) | 81 | /* |
| 82 | return rc; | 82 | * See if we can lock the context mapping that's only allowed |
| 83 | return count; | 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 | static ssize_t load_image_on_perst_show(struct device *device, | 105 | static ssize_t load_image_on_perst_show(struct device *device, |