Pull s390 updates from Heiko Carstens: - Add support for function error injection. - Add support for custom exception handlers, as required by BPF_PROBE_MEM. - Add support for BPF_PROBE_MEM. - Add trace events for idle enter / exit for the s390 specific idle implementation. - Remove unused zcore memmmap device. - Remove unused "raw view" from s390 debug feature. - AP bus + zcrypt device driver code refactoring. - Provide cex4 cca sysfs attributes for cex3 for zcrypt device driver. - Expose only minimal interface to walk physmem for mm/memblock. This is a common code change and it has been agreed on with Mike Rapoport and Andrew Morton that this can go upstream via the s390 tree. - Rework of the s390 vmem/vmmemap code to allow for future memory hot remove. - Get rid of FORCE_MAX_ZONEORDER to finally allow for order-10 allocations again, instead of only order-8 allocations. - Various small improvements and fixes. * tag 's390-5.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (48 commits) s390/vmemmap: coding style updates s390/vmemmap: avoid memset(PAGE_UNUSED) when adding consecutive sections s390/vmemmap: remember unused sub-pmd ranges s390/vmemmap: fallback to PTEs if mapping large PMD fails s390/vmem: cleanup empty page tables s390/vmemmap: take the vmem_mutex when populating/freeing s390/vmemmap: cleanup when vmemmap_populate() fails s390/vmemmap: extend modify_pagetable() to handle vmemmap s390/vmem: consolidate vmem_add_range() and vmem_remove_range() s390/vmem: rename vmem_add_mem() to vmem_add_range() s390: enable HAVE_FUNCTION_ERROR_INJECTION s390/pci: clarify comment in s390_mmio_read/write s390/time: improve comparison for tod steering s390/time: select CLOCKSOURCE_VALIDATE_LAST_CYCLE s390/time: use CLOCKSOURCE_MASK s390/bpf: implement BPF_PROBE_MEM s390/kernel: expand exception table logic to allow new handling options s390/kernel: unify EX_TABLE* implementations s390/mm: allow order 10 allocations s390/mm: avoid trimming to MAX_ORDER ...
Unified · Split
| @@ -67,7 +67,7 @@ corresponding component. The debugfs normally should be mounted to · 66 unmodified lines | |||
| 67 | The content of the directories are files which represent different views | 67 | The content of the directories are files which represent different views |
| 68 | to the debug log. Each component can decide which views should be | 68 | to the debug log. Each component can decide which views should be |
| 69 | used through registering them with the function :c:func:`debug_register_view()`. | 69 | used through registering them with the function :c:func:`debug_register_view()`. |
| 70 | Predefined views for hex/ascii, sprintf and raw binary data are provided. | 70 | Predefined views for hex/ascii and sprintf data are provided. |
| 71 | It is also possible to define other views. The content of | 71 | It is also possible to define other views. The content of |
| 72 | a view can be inspected simply by reading the corresponding debugfs file. | 72 | a view can be inspected simply by reading the corresponding debugfs file. |
| 73 | 73 | ||
| @@ -119,8 +119,6 @@ Predefined views: · 45 unmodified lines | |||
| 119 | 119 | ||
| 120 | extern struct debug_view debug_hex_ascii_view; | 120 | extern struct debug_view debug_hex_ascii_view; |
| 121 | 121 | ||
| 122 | extern struct debug_view debug_raw_view; | ||
| 123 | |||
| 124 | extern struct debug_view debug_sprintf_view; | 122 | extern struct debug_view debug_sprintf_view; |
| 125 | 123 | ||
| 126 | Examples | 124 | Examples |
| @@ -129,7 +127,7 @@ Examples · 2 unmodified lines | |||
| 129 | .. code-block:: c | 127 | .. code-block:: c |
| 130 | 128 | ||
| 131 | /* | 129 | /* |
| 132 | * hex_ascii- + raw-view Example | 130 | * hex_ascii-view Example |
| 133 | */ | 131 | */ |
| 134 | 132 | ||
| 135 | #include <linux/init.h> | 133 | #include <linux/init.h> |
| @@ -143,7 +141,6 @@ Examples · 7 unmodified lines | |||
| 143 | 141 | ||
| 144 | debug_info = debug_register("test", 1, 4, 4 ); | 142 | debug_info = debug_register("test", 1, 4, 4 ); |
| 145 | debug_register_view(debug_info, &debug_hex_ascii_view); | 143 | debug_register_view(debug_info, &debug_hex_ascii_view); |
| 146 | debug_register_view(debug_info, &debug_raw_view); | ||
| 147 | 144 | ||
| 148 | debug_text_event(debug_info, 4 , "one "); | 145 | debug_text_event(debug_info, 4 , "one "); |
| 149 | debug_int_exception(debug_info, 4, 4711); | 146 | debug_int_exception(debug_info, 4, 4711); |
| @@ -201,7 +198,7 @@ debugfs-files: · 51 unmodified lines | |||
| 201 | Example:: | 198 | Example:: |
| 202 | 199 | ||
| 203 | > ls /sys/kernel/debug/s390dbf/dasd | 200 | > ls /sys/kernel/debug/s390dbf/dasd |
| 204 | flush hex_ascii level pages raw | 201 | flush hex_ascii level pages |
| 205 | > cat /sys/kernel/debug/s390dbf/dasd/hex_ascii | sort -k2,2 -s | 202 | > cat /sys/kernel/debug/s390dbf/dasd/hex_ascii | sort -k2,2 -s |
| 206 | 00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | .... | 203 | 00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | .... |
| 207 | 00 00974733272:682210 2 - 02 0006ade6 46 52 45 45 | FREE | 204 | 00 00974733272:682210 2 - 02 0006ade6 46 52 45 45 | FREE |
| @@ -298,10 +295,9 @@ order to see the debug entries well formatted. · 90 unmodified lines | |||
| 298 | Predefined Views | 295 | Predefined Views |
| 299 | ---------------- | 296 | ---------------- |
| 300 | 297 | ||
| 301 | There are three predefined views: hex_ascii, raw and sprintf. | 298 | There are two predefined views: hex_ascii and sprintf. |
| 302 | The hex_ascii view shows the data field in hex and ascii representation | 299 | The hex_ascii view shows the data field in hex and ascii representation |
| 303 | (e.g. ``45 43 4b 44 | ECKD``). | 300 | (e.g. ``45 43 4b 44 | ECKD``). |
| 304 | The raw view returns a bytestream as the debug areas are stored in memory. | ||
| 305 | 301 | ||
| 306 | The sprintf view formats the debug entries in the same way as the sprintf | 302 | The sprintf view formats the debug entries in the same way as the sprintf |
| 307 | function would do. The sprintf event/exception functions write to the | 303 | function would do. The sprintf event/exception functions write to the |
| @@ -334,11 +330,6 @@ The format of the hex_ascii and sprintf view is as follows: · 26 unmodified lines | |||
| 334 | - Return Address to caller | 330 | - Return Address to caller |
| 335 | - data field | 331 | - data field |
| 336 | 332 | ||
| 337 | The format of the raw view is: | ||
| 338 | |||
| 339 | - Header as described in debug.h | ||
| 340 | - datafield | ||
| 341 | |||
| 342 | A typical line of the hex_ascii view will look like the following (first line | 333 | A typical line of the hex_ascii view will look like the following (first line |
| 343 | is only for explanation and will not be displayed when 'cating' the view):: | 334 | is only for explanation and will not be displayed when 'cating' the view):: |
| 344 | 335 | ||
| @@ -102,7 +102,6 @@ config S390 · 101 unmodified lines | |||
| 102 | select ARCH_INLINE_WRITE_UNLOCK_BH | 102 | select ARCH_INLINE_WRITE_UNLOCK_BH |
| 103 | select ARCH_INLINE_WRITE_UNLOCK_IRQ | 103 | select ARCH_INLINE_WRITE_UNLOCK_IRQ |
| 104 | select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE | 104 | select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE |
| 105 | select ARCH_KEEP_MEMBLOCK | ||
| 106 | select ARCH_STACKWALK | 105 | select ARCH_STACKWALK |
| 107 | select ARCH_SUPPORTS_ATOMIC_RMW | 106 | select ARCH_SUPPORTS_ATOMIC_RMW |
| 108 | select ARCH_SUPPORTS_NUMA_BALANCING | 107 | select ARCH_SUPPORTS_NUMA_BALANCING |
| @@ -126,6 +125,7 @@ config S390 · 17 unmodified lines | |||
| 126 | select HAVE_ARCH_JUMP_LABEL_RELATIVE | 125 | select HAVE_ARCH_JUMP_LABEL_RELATIVE |
| 127 | select HAVE_ARCH_KASAN | 126 | select HAVE_ARCH_KASAN |
| 128 | select HAVE_ARCH_KASAN_VMALLOC | 127 | select HAVE_ARCH_KASAN_VMALLOC |
| 128 | select CLOCKSOURCE_VALIDATE_LAST_CYCLE | ||
| 129 | select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES | 129 | select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES |
| 130 | select HAVE_ARCH_SECCOMP_FILTER | 130 | select HAVE_ARCH_SECCOMP_FILTER |
| 131 | select HAVE_ARCH_SOFT_DIRTY | 131 | select HAVE_ARCH_SOFT_DIRTY |
| @@ -145,6 +145,7 @@ config S390 · 13 unmodified lines | |||
| 145 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | 145 | select HAVE_EFFICIENT_UNALIGNED_ACCESS |
| 146 | select HAVE_FENTRY | 146 | select HAVE_FENTRY |
| 147 | select HAVE_FTRACE_MCOUNT_RECORD | 147 | select HAVE_FTRACE_MCOUNT_RECORD |
| 148 | select HAVE_FUNCTION_ERROR_INJECTION | ||
| 148 | select HAVE_FUNCTION_GRAPH_TRACER | 149 | select HAVE_FUNCTION_GRAPH_TRACER |
| 149 | select HAVE_FUNCTION_TRACER | 150 | select HAVE_FUNCTION_TRACER |
| 150 | select HAVE_FUTEX_CMPXCHG if FUTEX | 151 | select HAVE_FUTEX_CMPXCHG if FUTEX |
| @@ -626,10 +627,6 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE · 475 unmodified lines | |||
| 626 | config ARCH_ENABLE_SPLIT_PMD_PTLOCK | 627 | config ARCH_ENABLE_SPLIT_PMD_PTLOCK |
| 627 | def_bool y | 628 | def_bool y |
| 628 | 629 | ||
| 629 | config FORCE_MAX_ZONEORDER | ||
| 630 | int | ||
| 631 | default "9" | ||
| 632 | |||
| 633 | config MAX_PHYSMEM_BITS | 630 | config MAX_PHYSMEM_BITS |
| 634 | int "Maximum size of supported physical memory in bits (42-53)" | 631 | int "Maximum size of supported physical memory in bits (42-53)" |
| 635 | range 42 53 | 632 | range 42 53 |
| @@ -129,8 +129,7 @@ static void appldata_get_os_data(void *data) · 128 unmodified lines | |||
| 129 | 129 | ||
| 130 | os_data->nr_cpus = j; | 130 | os_data->nr_cpus = j; |
| 131 | 131 | ||
| 132 | new_size = sizeof(struct appldata_os_data) + | 132 | new_size = struct_size(os_data, os_cpu, os_data->nr_cpus); |
| 133 | (os_data->nr_cpus * sizeof(struct appldata_os_per_cpu)); | ||
| 134 | if (ops.size != new_size) { | 133 | if (ops.size != new_size) { |
| 135 | if (ops.active) { | 134 | if (ops.active) { |
| 136 | rc = appldata_diag(APPLDATA_RECORD_OS_ID, | 135 | rc = appldata_diag(APPLDATA_RECORD_OS_ID, |
| @@ -165,8 +164,7 @@ static int __init appldata_os_init(void) · 28 unmodified lines | |||
| 165 | { | 164 | { |
| 166 | int rc, max_size; | 165 | int rc, max_size; |
| 167 | 166 | ||
| 168 | max_size = sizeof(struct appldata_os_data) + | 167 | max_size = struct_size(appldata_os_data, os_cpu, num_possible_cpus()); |
| 169 | (num_possible_cpus() * sizeof(struct appldata_os_per_cpu)); | ||
| 170 | if (max_size > APPLDATA_MAX_REC_SIZE) { | 168 | if (max_size > APPLDATA_MAX_REC_SIZE) { |
| 171 | pr_err("Maximum OS record size %i exceeds the maximum " | 169 | pr_err("Maximum OS record size %i exceeds the maximum " |
| 172 | "record size %i\n", max_size, APPLDATA_MAX_REC_SIZE); | 170 | "record size %i\n", max_size, APPLDATA_MAX_REC_SIZE); |
| @@ -0,0 +1,12 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _ASM_S390_ASM_CONST_H | ||
| 3 | #define _ASM_S390_ASM_CONST_H | ||
| 4 | |||
| 5 | #ifdef __ASSEMBLY__ | ||
| 6 | # define stringify_in_c(...) __VA_ARGS__ | ||
| 7 | #else | ||
| 8 | /* This version of stringify will deal with commas... */ | ||
| 9 | # define __stringify_in_c(...) #__VA_ARGS__ | ||
| 10 | # define stringify_in_c(...) __stringify_in_c(__VA_ARGS__) " " | ||
| 11 | #endif | ||
| 12 | #endif /* _ASM_S390_ASM_CONST_H */ | ||
| @@ -12,7 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/time.h> | 13 | #include <linux/time.h> |
| 14 | #include <linux/refcount.h> | 14 | #include <linux/refcount.h> |
| 15 | #include <uapi/asm/debug.h> | 15 | #include <linux/fs.h> |
| 16 | 16 | ||
| 17 | #define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */ | 17 | #define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */ |
| 18 | #define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */ | 18 | #define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */ |
| @@ -26,6 +26,21 @@ · 7 unmodified lines | |||
| 26 | #define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */ | 26 | #define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */ |
| 27 | /* the entry information */ | 27 | /* the entry information */ |
| 28 | 28 | ||
| 29 | #define __DEBUG_FEATURE_VERSION 2 /* version of debug feature */ | ||
| 30 | |||
| 31 | struct __debug_entry { | ||
| 32 | union { | ||
| 33 | struct { | ||
| 34 | unsigned long clock : 52; | ||
| 35 | unsigned long exception : 1; | ||
| 36 | unsigned long level : 3; | ||
| 37 | unsigned long cpuid : 8; | ||
| 38 | } fields; | ||
| 39 | unsigned long stck; | ||
| 40 | } id; | ||
| 41 | void *caller; | ||
| 42 | } __packed; | ||
| 43 | |||
| 29 | typedef struct __debug_entry debug_entry_t; | 44 | typedef struct __debug_entry debug_entry_t; |
| 30 | 45 | ||
| 31 | struct debug_view; | 46 | struct debug_view; |
| @@ -82,7 +97,6 @@ struct debug_view { · 50 unmodified lines | |||
| 82 | }; | 97 | }; |
| 83 | 98 | ||
| 84 | extern struct debug_view debug_hex_ascii_view; | 99 | extern struct debug_view debug_hex_ascii_view; |
| 85 | extern struct debug_view debug_raw_view; | ||
| 86 | extern struct debug_view debug_sprintf_view; | 100 | extern struct debug_view debug_sprintf_view; |
| 87 | 101 | ||
| 88 | /* do NOT use the _common functions */ | 102 | /* do NOT use the _common functions */ |
| @@ -1,12 +1,20 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | #ifndef __S390_EXTABLE_H | 2 | #ifndef __S390_EXTABLE_H |
| 3 | #define __S390_EXTABLE_H | 3 | #define __S390_EXTABLE_H |
| 4 | |||
| 5 | #include <asm/ptrace.h> | ||
| 6 | #include <linux/compiler.h> | ||
| 7 | |||
| 4 | /* | 8 | /* |
| 5 | * The exception table consists of pairs of addresses: the first is the | 9 | * The exception table consists of three addresses: |
| 6 | * address of an instruction that is allowed to fault, and the second is | 10 | * |
| 7 | * the address at which the program should continue. No registers are | 11 | * - Address of an instruction that is allowed to fault. |
| 8 | * modified, so it is entirely up to the continuation code to figure out | 12 | * - Address at which the program should continue. |
| 9 | * what to do. | 13 | * - Optional address of handler that takes pt_regs * argument and runs in |
| 14 | * interrupt context. | ||
| 15 | * | ||
| 16 | * No registers are modified, so it is entirely up to the continuation code | ||
| 17 | * to figure out what to do. | ||
| 10 | * | 18 | * |
| 11 | * All the routines below use bits of fixup code that are out of line | 19 | * All the routines below use bits of fixup code that are out of line |
| 12 | * with the main instruction path. This means when everything is well, | 20 | * with the main instruction path. This means when everything is well, |
| @@ -17,6 +25,7 @@ · 4 unmodified lines | |||
| 17 | struct exception_table_entry | 25 | struct exception_table_entry |
| 18 | { | 26 | { |
| 19 | int insn, fixup; | 27 | int insn, fixup; |
| 28 | long handler; | ||
| 20 | }; | 29 | }; |
| 21 | 30 | ||
| 22 | extern struct exception_table_entry *__start_dma_ex_table; | 31 | extern struct exception_table_entry *__start_dma_ex_table; |
| @@ -29,6 +38,39 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x) · 6 unmodified lines | |||
| 29 | return (unsigned long)&x->fixup + x->fixup; | 38 | return (unsigned long)&x->fixup + x->fixup; |
| 30 | } | 39 | } |
| 31 | 40 | ||
| 41 | typedef bool (*ex_handler_t)(const struct exception_table_entry *, | ||
| 42 | struct pt_regs *); | ||
| 43 | |||
| 44 | static inline ex_handler_t | ||
| 45 | ex_fixup_handler(const struct exception_table_entry *x) | ||
| 46 | { | ||
| 47 | if (likely(!x->handler)) | ||
| 48 | return NULL; | ||
| 49 | return (ex_handler_t)((unsigned long)&x->handler + x->handler); | ||
| 50 | } | ||
| 51 | |||
| 52 | static inline bool ex_handle(const struct exception_table_entry *x, | ||
| 53 | struct pt_regs *regs) | ||
| 54 | { | ||
| 55 | ex_handler_t handler = ex_fixup_handler(x); | ||
| 56 | |||
| 57 | if (unlikely(handler)) | ||
| 58 | return handler(x, regs); | ||
| 59 | regs->psw.addr = extable_fixup(x); | ||
| 60 | return true; | ||
| 61 | } | ||
| 62 | |||
| 32 | #define ARCH_HAS_RELATIVE_EXTABLE | 63 | #define ARCH_HAS_RELATIVE_EXTABLE |
| 33 | 64 | ||
| 65 | static inline void swap_ex_entry_fixup(struct exception_table_entry *a, | ||
| 66 | struct exception_table_entry *b, | ||
| 67 | struct exception_table_entry tmp, | ||
| 68 | int delta) | ||
| 69 | { | ||
| 70 | a->fixup = b->fixup + delta; | ||
| 71 | b->fixup = tmp.fixup - delta; | ||
| 72 | a->handler = b->handler + delta; | ||
| 73 | b->handler = tmp.handler - delta; | ||
| 74 | } | ||
| 75 | |||
| 34 | #endif | 76 | #endif |
| @@ -2,38 +2,27 @@ · 1 unmodified line | |||
| 2 | #ifndef __ASM_LINKAGE_H | 2 | #ifndef __ASM_LINKAGE_H |
| 3 | #define __ASM_LINKAGE_H | 3 | #define __ASM_LINKAGE_H |
| 4 | 4 | ||
| 5 | #include <asm/asm-const.h> | ||
| 5 | #include <linux/stringify.h> | 6 | #include <linux/stringify.h> |
| 6 | 7 | ||
| 7 | #define __ALIGN .align 4, 0x07 | 8 | #define __ALIGN .align 4, 0x07 |
| 8 | #define __ALIGN_STR __stringify(__ALIGN) | 9 | #define __ALIGN_STR __stringify(__ALIGN) |
| 9 | 10 | ||
| 10 | #ifndef __ASSEMBLY__ | ||
| 11 | |||
| 12 | /* | 11 | /* |
| 13 | * Helper macro for exception table entries | 12 | * Helper macro for exception table entries |
| 14 | */ | 13 | */ |
| 15 | #define EX_TABLE(_fault, _target) \ | ||
| 16 | ".section __ex_table,\"a\"\n" \ | ||
| 17 | ".align 4\n" \ | ||
| 18 | ".long (" #_fault ") - .\n" \ | ||
| 19 | ".long (" #_target ") - .\n" \ | ||
| 20 | ".previous\n" | ||
| 21 | |||
| 22 | #else /* __ASSEMBLY__ */ | ||
| 23 | 14 | ||
| 24 | #define EX_TABLE(_fault, _target) \ | 15 | #define __EX_TABLE(_section, _fault, _target) \ |
| 25 | .section __ex_table,"a" ; \ | 16 | stringify_in_c(.section _section,"a";) \ |
| 26 | .align 4 ; \ | 17 | stringify_in_c(.align 8;) \ |
| 27 | .long (_fault) - . ; \ | 18 | stringify_in_c(.long (_fault) - .;) \ |
| 28 | .long (_target) - . ; \ | 19 | stringify_in_c(.long (_target) - .;) \ |
| 29 | .previous | 20 | stringify_in_c(.quad 0;) \ |
| 21 | stringify_in_c(.previous) | ||
| 30 | 22 | ||
| 31 | #define EX_TABLE_DMA(_fault, _target) \ | 23 | #define EX_TABLE(_fault, _target) \ |
| 32 | .section .dma.ex_table, "a" ; \ | 24 | __EX_TABLE(__ex_table, _fault, _target) |
| 33 | .align 4 ; \ | 25 | #define EX_TABLE_DMA(_fault, _target) \ |
| 34 | .long (_fault) - . ; \ | 26 | __EX_TABLE(.dma.ex_table, _fault, _target) |
| 35 | .long (_target) - . ; \ | ||
| 36 | .previous | ||
| 37 | 27 | ||
| 38 | #endif /* __ASSEMBLY__ */ | ||
| 39 | #endif | 28 | #endif |
| @@ -131,12 +131,6 @@ static inline void validate_st_entry(unsigned long *entry) · 130 unmodified lines | |||
| 131 | *entry |= ZPCI_TABLE_VALID; | 131 | *entry |= ZPCI_TABLE_VALID; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static inline void invalidate_table_entry(unsigned long *entry) | ||
| 135 | { | ||
| 136 | *entry &= ~ZPCI_TABLE_VALID_MASK; | ||
| 137 | *entry |= ZPCI_TABLE_INVALID; | ||
| 138 | } | ||
| 139 | |||
| 140 | static inline void invalidate_pt_entry(unsigned long *entry) | 134 | static inline void invalidate_pt_entry(unsigned long *entry) |
| 141 | { | 135 | { |
| 142 | WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_INVALID); | 136 | WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_INVALID); |
| @@ -173,11 +167,6 @@ static inline int pt_entry_isvalid(unsigned long entry) · 30 unmodified lines | |||
| 173 | return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID; | 167 | return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID; |
| 174 | } | 168 | } |
| 175 | 169 | ||
| 176 | static inline int entry_isprotected(unsigned long entry) | ||
| 177 | { | ||
| 178 | return (entry & ZPCI_TABLE_PROT_MASK) == ZPCI_TABLE_PROTECTED; | ||
| 179 | } | ||
| 180 | |||
| 181 | static inline unsigned long *get_rt_sto(unsigned long entry) | 170 | static inline unsigned long *get_rt_sto(unsigned long entry) |
| 182 | { | 171 | { |
| 183 | return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX) | 172 | return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX) |
| @@ -1669,7 +1669,7 @@ static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset) · 1668 unmodified lines | |||
| 1669 | #define kern_addr_valid(addr) (1) | 1669 | #define kern_addr_valid(addr) (1) |
| 1670 | 1670 | ||
| 1671 | extern int vmem_add_mapping(unsigned long start, unsigned long size); | 1671 | extern int vmem_add_mapping(unsigned long start, unsigned long size); |
| 1672 | extern int vmem_remove_mapping(unsigned long start, unsigned long size); | 1672 | extern void vmem_remove_mapping(unsigned long start, unsigned long size); |
| 1673 | extern int s390_enable_sie(void); | 1673 | extern int s390_enable_sie(void); |
| 1674 | extern int s390_enable_skey(void); | 1674 | extern int s390_enable_skey(void); |
| 1675 | extern void s390_reset_cmma(struct mm_struct *mm); | 1675 | extern void s390_reset_cmma(struct mm_struct *mm); |
| @@ -184,5 +184,10 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) · 183 unmodified lines | |||
| 184 | return regs->gprs[15]; | 184 | return regs->gprs[15]; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) | ||
| 188 | { | ||
| 189 | regs->gprs[2] = rc; | ||
| 190 | } | ||
| 191 | |||
| 187 | #endif /* __ASSEMBLY__ */ | 192 | #endif /* __ASSEMBLY__ */ |
| 188 | #endif /* _S390_PTRACE_H */ | 193 | #endif /* _S390_PTRACE_H */ |
| @@ -54,6 +54,10 @@ static inline int smp_get_base_cpu(int cpu) · 53 unmodified lines | |||
| 54 | return cpu - (cpu % (smp_cpu_mtid + 1)); | 54 | return cpu - (cpu % (smp_cpu_mtid + 1)); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static inline void smp_cpus_done(unsigned int max_cpus) | ||
| 58 | { | ||
| 59 | } | ||
| 60 | |||
| 57 | extern int smp_rescan_cpus(void); | 61 | extern int smp_rescan_cpus(void); |
| 58 | extern void __noreturn cpu_die(void); | 62 | extern void __noreturn cpu_die(void); |
| 59 | extern void __cpu_die(unsigned int cpu); | 63 | extern void __cpu_die(unsigned int cpu); |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | |||
| 30 | }) | 30 | }) |
| 31 | 31 | ||
| 32 | #define __S390_SYS_STUBx(x, name, ...) \ | 32 | #define __S390_SYS_STUBx(x, name, ...) \ |
| 33 | asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ | 33 | asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));\ |
| 34 | ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \ | 34 | ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \ |
| 35 | asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ | 35 | asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ |
| 36 | { \ | 36 | { \ |
| @@ -46,7 +46,7 @@ · 9 unmodified lines | |||
| 46 | #define COMPAT_SYSCALL_DEFINE0(sname) \ | 46 | #define COMPAT_SYSCALL_DEFINE0(sname) \ |
| 47 | SYSCALL_METADATA(_##sname, 0); \ | 47 | SYSCALL_METADATA(_##sname, 0); \ |
| 48 | asmlinkage long __s390_compat_sys_##sname(void); \ | 48 | asmlinkage long __s390_compat_sys_##sname(void); \ |
| 49 | ALLOW_ERROR_INJECTION(__s390_compat__sys_##sname, ERRNO); \ | 49 | ALLOW_ERROR_INJECTION(__s390_compat_sys_##sname, ERRNO); \ |
| 50 | asmlinkage long __s390_compat_sys_##sname(void) | 50 | asmlinkage long __s390_compat_sys_##sname(void) |
| 51 | 51 | ||
| 52 | #define SYSCALL_DEFINE0(sname) \ | 52 | #define SYSCALL_DEFINE0(sname) \ |
| @@ -72,7 +72,7 @@ · 19 unmodified lines | |||
| 72 | asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ | 72 | asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ |
| 73 | asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ | 73 | asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ |
| 74 | __attribute__((alias(__stringify(__se_compat_sys##name)))); \ | 74 | __attribute__((alias(__stringify(__se_compat_sys##name)))); \ |
| 75 | ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \ | 75 | ALLOW_ERROR_INJECTION(__s390_compat_sys##name, ERRNO); \ |
| 76 | static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ | 76 | static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ |
| 77 | asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ | 77 | asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ |
| 78 | asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ | 78 | asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ |
| @@ -49,11 +49,6 @@ static inline void set_clock_comparator(__u64 time) · 48 unmodified lines | |||
| 49 | asm volatile("sckc %0" : : "Q" (time)); | 49 | asm volatile("sckc %0" : : "Q" (time)); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static inline void store_clock_comparator(__u64 *time) | ||
| 53 | { | ||
| 54 | asm volatile("stckc %0" : "=Q" (*time)); | ||
| 55 | } | ||
| 56 | |||
| 57 | void clock_comparator_work(void); | 52 | void clock_comparator_work(void); |
| 58 | 53 | ||
| 59 | void __init time_early_init(void); | 54 | void __init time_early_init(void); |
| @@ -1,35 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | ||
| 2 | /* | ||
| 3 | * S/390 debug facility | ||
| 4 | * | ||
| 5 | * Copyright IBM Corp. 1999, 2000 | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef _UAPIDEBUG_H | ||
| 9 | #define _UAPIDEBUG_H | ||
| 10 | |||
| 11 | #include <linux/fs.h> | ||
| 12 | |||
| 13 | /* Note: | ||
| 14 | * struct __debug_entry must be defined outside of #ifdef __KERNEL__ | ||
| 15 | * in order to allow a user program to analyze the 'raw'-view. | ||
| 16 | */ | ||
| 17 | |||
| 18 | struct __debug_entry{ | ||
| 19 | union { | ||
| 20 | struct { | ||
| 21 | unsigned long long clock:52; | ||
| 22 | unsigned long long exception:1; | ||
| 23 | unsigned long long level:3; | ||
| 24 | unsigned long long cpuid:8; | ||
| 25 | } fields; | ||
| 26 | |||
| 27 | unsigned long long stck; | ||
| 28 | } id; | ||
| 29 | void* caller; | ||
| 30 | } __attribute__((packed)); | ||
| 31 | |||
| 32 | |||
| 33 | #define __DEBUG_FEATURE_VERSION 2 /* version of debug feature */ | ||
| 34 | |||
| 35 | #endif /* _UAPIDEBUG_H */ | ||
| @@ -36,12 +36,12 @@ · 35 unmodified lines | |||
| 36 | * - length(n_modulus) = inputdatalength | 36 | * - length(n_modulus) = inputdatalength |
| 37 | */ | 37 | */ |
| 38 | struct ica_rsa_modexpo { | 38 | struct ica_rsa_modexpo { |
| 39 | char __user *inputdata; | 39 | __u8 __user *inputdata; |
| 40 | unsigned int inputdatalength; | 40 | __u32 inputdatalength; |
| 41 | char __user *outputdata; | 41 | __u8 __user *outputdata; |
| 42 | unsigned int outputdatalength; | 42 | __u32 outputdatalength; |
| 43 | char __user *b_key; | 43 | __u8 __user *b_key; |
| 44 | char __user *n_modulus; | 44 | __u8 __user *n_modulus; |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | /** | 47 | /** |
| @@ -59,15 +59,15 @@ struct ica_rsa_modexpo { · 11 unmodified lines | |||
| 59 | * - length(u_mult_inv) = inputdatalength/2 + 8 | 59 | * - length(u_mult_inv) = inputdatalength/2 + 8 |
| 60 | */ | 60 | */ |
| 61 | struct ica_rsa_modexpo_crt { | 61 | struct ica_rsa_modexpo_crt { |
| 62 | char __user *inputdata; | 62 | __u8 __user *inputdata; |
| 63 | unsigned int inputdatalength; | 63 | __u32 inputdatalength; |
| 64 | char __user *outputdata; | 64 | __u8 __user *outputdata; |
| 65 | unsigned int outputdatalength; | 65 | __u32 outputdatalength; |
| 66 | char __user *bp_key; | 66 | __u8 __user *bp_key; |
| 67 | char __user *bq_key; | 67 | __u8 __user *bq_key; |
| 68 | char __user *np_prime; | 68 | __u8 __user *np_prime; |
| 69 | char __user *nq_prime; | 69 | __u8 __user *nq_prime; |
| 70 | char __user *u_mult_inv; | 70 | __u8 __user *u_mult_inv; |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | /** | 73 | /** |
| @@ -83,67 +83,67 @@ struct ica_rsa_modexpo_crt { · 9 unmodified lines | |||
| 83 | * key block | 83 | * key block |
| 84 | */ | 84 | */ |
| 85 | struct CPRBX { | 85 | struct CPRBX { |
| 86 | unsigned short cprb_len; /* CPRB length 220 */ | 86 | __u16 cprb_len; /* CPRB length 220 */ |
| 87 | unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ | 87 | __u8 cprb_ver_id; /* CPRB version id. 0x02 */ |
| 88 | unsigned char pad_000[3]; /* Alignment pad bytes */ | 88 | __u8 pad_000[3]; /* Alignment pad bytes */ |
| 89 | unsigned char func_id[2]; /* function id 0x5432 */ | 89 | __u8 func_id[2]; /* function id 0x5432 */ |
| 90 | unsigned char cprb_flags[4]; /* Flags */ | 90 | __u8 cprb_flags[4]; /* Flags */ |
| 91 | unsigned int req_parml; /* request parameter buffer len */ | 91 | __u32 req_parml; /* request parameter buffer len */ |
| 92 | unsigned int req_datal; /* request data buffer */ | 92 | __u32 req_datal; /* request data buffer */ |
| 93 | unsigned int rpl_msgbl; /* reply message block length */ | 93 | __u32 rpl_msgbl; /* reply message block length */ |
| 94 | unsigned int rpld_parml; /* replied parameter block len */ | 94 | __u32 rpld_parml; /* replied parameter block len */ |
| 95 | unsigned int rpl_datal; /* reply data block len */ | 95 | __u32 rpl_datal; /* reply data block len */ |
| 96 | unsigned int rpld_datal; /* replied data block len */ | 96 | __u32 rpld_datal; /* replied data block len */ |
| 97 | unsigned int req_extbl; /* request extension block len */ | 97 | __u32 req_extbl; /* request extension block len */ |
| 98 | unsigned char pad_001[4]; /* reserved */ | 98 | __u8 pad_001[4]; /* reserved */ |
| 99 | unsigned int rpld_extbl; /* replied extension block len */ | 99 | __u32 rpld_extbl; /* replied extension block len */ |
| 100 | unsigned char padx000[16 - sizeof(char *)]; | 100 | __u8 padx000[16 - sizeof(__u8 *)]; |
| 101 | unsigned char *req_parmb; /* request parm block 'address' */ | 101 | __u8 __user *req_parmb; /* request parm block 'address' */ |
| 102 | unsigned char padx001[16 - sizeof(char *)]; | 102 | __u8 padx001[16 - sizeof(__u8 *)]; |
| 103 | unsigned char *req_datab; /* request data block 'address' */ | 103 | __u8 __user *req_datab; /* request data block 'address' */ |
| 104 | unsigned char padx002[16 - sizeof(char *)]; | 104 | __u8 padx002[16 - sizeof(__u8 *)]; |
| 105 | unsigned char *rpl_parmb; /* reply parm block 'address' */ | 105 | __u8 __user *rpl_parmb; /* reply parm block 'address' */ |
| 106 | unsigned char padx003[16 - sizeof(char *)]; | 106 | __u8 padx003[16 - sizeof(__u8 *)]; |
| 107 | unsigned char *rpl_datab; /* reply data block 'address' */ | 107 | __u8 __user *rpl_datab; /* reply data block 'address' */ |
| 108 | unsigned char padx004[16 - sizeof(char *)]; | 108 | __u8 padx004[16 - sizeof(__u8 *)]; |
| 109 | unsigned char *req_extb; /* request extension block 'addr'*/ | 109 | __u8 __user *req_extb; /* request extension block 'addr'*/ |
| 110 | unsigned char padx005[16 - sizeof(char *)]; | 110 | __u8 padx005[16 - sizeof(__u8 *)]; |
| 111 | unsigned char *rpl_extb; /* reply extension block 'address'*/ | 111 | __u8 __user *rpl_extb; /* reply extension block 'address'*/ |
| 112 | unsigned short ccp_rtcode; /* server return code */ | 112 | __u16 ccp_rtcode; /* server return code */ |
| 113 | unsigned short ccp_rscode; /* server reason code */ | 113 | __u16 ccp_rscode; /* server reason code */ |
| 114 | unsigned int mac_data_len; /* Mac Data Length */ | 114 | __u32 mac_data_len; /* Mac Data Length */ |
| 115 | unsigned char logon_id[8]; /* Logon Identifier */ | 115 | __u8 logon_id[8]; /* Logon Identifier */ |
| 116 | unsigned char mac_value[8]; /* Mac Value */ | 116 | __u8 mac_value[8]; /* Mac Value */ |
| 117 | unsigned char mac_content_flgs;/* Mac content flag byte */ | 117 | __u8 mac_content_flgs; /* Mac content flag byte */ |
| 118 | unsigned char pad_002; /* Alignment */ | 118 | __u8 pad_002; /* Alignment */ |
| 119 | unsigned short domain; /* Domain */ | 119 | __u16 domain; /* Domain */ |
| 120 | unsigned char usage_domain[4];/* Usage domain */ | 120 | __u8 usage_domain[4]; /* Usage domain */ |
| 121 | unsigned char cntrl_domain[4];/* Control domain */ | 121 | __u8 cntrl_domain[4]; /* Control domain */ |
| 122 | unsigned char S390enf_mask[4];/* S/390 enforcement mask */ | 122 | __u8 S390enf_mask[4]; /* S/390 enforcement mask */ |
| 123 | unsigned char pad_004[36]; /* reserved */ | 123 | __u8 pad_004[36]; /* reserved */ |
| 124 | } __attribute__((packed)); | 124 | } __attribute__((packed)); |
| 125 | 125 | ||
| 126 | /** | 126 | /** |
| 127 | * xcRB | 127 | * xcRB |
| 128 | */ | 128 | */ |
| 129 | struct ica_xcRB { | 129 | struct ica_xcRB { |
| 130 | unsigned short agent_ID; | 130 | __u16 agent_ID; |
| 131 | unsigned int user_defined; | 131 | __u32 user_defined; |
| 132 | unsigned short request_ID; | 132 | __u16 request_ID; |
| 133 | unsigned int request_control_blk_length; | 133 | __u32 request_control_blk_length; |
| 134 | unsigned char padding1[16 - sizeof(char *)]; | 134 | __u8 _padding1[16 - sizeof(__u8 *)]; |
| 135 | char __user *request_control_blk_addr; | 135 | __u8 __user *request_control_blk_addr; |
| 136 | unsigned int request_data_length; | 136 | __u32 request_data_length; |
| 137 | char padding2[16 - sizeof(char *)]; | 137 | __u8 _padding2[16 - sizeof(__u8 *)]; |
| 138 | char __user *request_data_address; | 138 | __u8 __user *request_data_address; |
| 139 | unsigned int reply_control_blk_length; | 139 | __u32 reply_control_blk_length; |
| 140 | char padding3[16 - sizeof(char *)]; | 140 | __u8 _padding3[16 - sizeof(__u8 *)]; |
| 141 | char __user *reply_control_blk_addr; | 141 | __u8 __user *reply_control_blk_addr; |
| 142 | unsigned int reply_data_length; | 142 | __u32 reply_data_length; |
| 143 | char padding4[16 - sizeof(char *)]; | 143 | __u8 __padding4[16 - sizeof(__u8 *)]; |
| 144 | char __user *reply_data_addr; | 144 | __u8 __user *reply_data_addr; |
| 145 | unsigned short priority_window; | 145 | __u16 priority_window; |
| 146 | unsigned int status; | 146 | __u32 status; |
| 147 | } __attribute__((packed)); | 147 | } __attribute__((packed)); |
| 148 | 148 | ||
| 149 | /** | 149 | /** |
| @@ -549,8 +549,7 @@ static int get_mem_chunk_cnt(void) · 548 unmodified lines | |||
| 549 | int cnt = 0; | 549 | int cnt = 0; |
| 550 | u64 idx; | 550 | u64 idx; |
| 551 | 551 | ||
| 552 | for_each_mem_range(idx, &memblock.physmem, &oldmem_type, NUMA_NO_NODE, | 552 | for_each_physmem_range(idx, &oldmem_type, NULL, NULL) |
| 553 | MEMBLOCK_NONE, NULL, NULL, NULL) | ||
| 554 | cnt++; | 553 | cnt++; |
| 555 | return cnt; | 554 | return cnt; |
| 556 | } | 555 | } |
| @@ -563,8 +562,7 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset) · 6 unmodified lines | |||
| 563 | phys_addr_t start, end; | 562 | phys_addr_t start, end; |
| 564 | u64 idx; | 563 | u64 idx; |
| 565 | 564 | ||
| 566 | for_each_mem_range(idx, &memblock.physmem, &oldmem_type, NUMA_NO_NODE, | 565 | for_each_physmem_range(idx, &oldmem_type, &start, &end) { |
| 567 | MEMBLOCK_NONE, &start, &end, NULL) { | ||
| 568 | phdr->p_filesz = end - start; | 566 | phdr->p_filesz = end - start; |
| 569 | phdr->p_type = PT_LOAD; | 567 | phdr->p_type = PT_LOAD; |
| 570 | phdr->p_offset = start; | 568 | phdr->p_offset = start; |
| @@ -90,27 +90,11 @@ static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view, · 89 unmodified lines | |||
| 90 | size_t user_buf_size, loff_t *offset); | 90 | size_t user_buf_size, loff_t *offset); |
| 91 | static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view, | 91 | static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view, |
| 92 | char *out_buf, const char *in_buf); | 92 | char *out_buf, const char *in_buf); |
| 93 | static int debug_raw_format_fn(debug_info_t *id, | ||
| 94 | struct debug_view *view, char *out_buf, | ||
| 95 | const char *in_buf); | ||
| 96 | static int debug_raw_header_fn(debug_info_t *id, struct debug_view *view, | ||
| 97 | int area, debug_entry_t *entry, char *out_buf); | ||
| 98 | |||
| 99 | static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view, | 93 | static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view, |
| 100 | char *out_buf, debug_sprintf_entry_t *curr_event); | 94 | char *out_buf, debug_sprintf_entry_t *curr_event); |
| 101 | 95 | ||
| 102 | /* globals */ | 96 | /* globals */ |
| 103 | 97 | ||
| 104 | struct debug_view debug_raw_view = { | ||
| 105 | "raw", | ||
| 106 | NULL, | ||
| 107 | &debug_raw_header_fn, | ||
| 108 | &debug_raw_format_fn, | ||
| 109 | NULL, | ||
| 110 | NULL | ||
| 111 | }; | ||
| 112 | EXPORT_SYMBOL(debug_raw_view); | ||
| 113 | |||
| 114 | struct debug_view debug_hex_ascii_view = { | 98 | struct debug_view debug_hex_ascii_view = { |
| 115 | "hex_ascii", | 99 | "hex_ascii", |
| 116 | NULL, | 100 | NULL, |
| @@ -1385,32 +1369,6 @@ out: · 1268 unmodified lines | |||
| 1385 | return rc; /* number of input characters */ | 1369 | return rc; /* number of input characters */ |
| 1386 | } | 1370 | } |
| 1387 | 1371 | ||
| 1388 | /* | ||
| 1389 | * prints debug header in raw format | ||
| 1390 | */ | ||
| 1391 | static int debug_raw_header_fn(debug_info_t *id, struct debug_view *view, | ||
| 1392 | int area, debug_entry_t *entry, char *out_buf) | ||
| 1393 | { | ||
| 1394 | int rc; | ||
| 1395 | |||
| 1396 | rc = sizeof(debug_entry_t); | ||
| 1397 | memcpy(out_buf, entry, sizeof(debug_entry_t)); | ||
| 1398 | return rc; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | /* | ||
| 1402 | * prints debug data in raw format | ||
| 1403 | */ | ||
| 1404 | static int debug_raw_format_fn(debug_info_t *id, struct debug_view *view, | ||
| 1405 | char *out_buf, const char *in_buf) | ||
| 1406 | { | ||
| 1407 | int rc; | ||
| 1408 | |||
| 1409 | rc = id->buf_size; | ||
| 1410 | memcpy(out_buf, in_buf, id->buf_size); | ||
| 1411 | return rc; | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | /* | 1372 | /* |
| 1415 | * prints debug data in hex/ascii format | 1373 | * prints debug data in hex/ascii format |
| 1416 | */ | 1374 | */ |
| @@ -370,7 +370,7 @@ EXPORT_SYMBOL(sie_exit) · 369 unmodified lines | |||
| 370 | 370 | ||
| 371 | /* | 371 | /* |
| 372 | * SVC interrupt handler routine. System calls are synchronous events and | 372 | * SVC interrupt handler routine. System calls are synchronous events and |
| 373 | * are executed with interrupts enabled. | 373 | * are entered with interrupts disabled. |
| 374 | */ | 374 | */ |
| 375 | 375 | ||
| 376 | ENTRY(system_call) | 376 | ENTRY(system_call) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/cpu.h> | 15 | #include <linux/cpu.h> |
| 16 | #include <linux/sched/cputime.h> | 16 | #include <linux/sched/cputime.h> |
| 17 | #include <trace/events/power.h> | ||
| 17 | #include <asm/nmi.h> | 18 | #include <asm/nmi.h> |
| 18 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
| 19 | #include "entry.h" | 20 | #include "entry.h" |
| @@ -32,11 +33,12 @@ void enabled_wait(void) · 12 unmodified lines | |||
| 32 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; | 33 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; |
| 33 | clear_cpu_flag(CIF_NOHZ_DELAY); | 34 | clear_cpu_flag(CIF_NOHZ_DELAY); |
| 34 | 35 | ||
| 36 | trace_cpu_idle_rcuidle(1, smp_processor_id()); | ||
| 35 | local_irq_save(flags); | 37 | local_irq_save(flags); |
| 36 | /* Call the assembler magic in entry.S */ | 38 | /* Call the assembler magic in entry.S */ |
| 37 | psw_idle(idle, psw_mask); | 39 | psw_idle(idle, psw_mask); |
| 38 | local_irq_restore(flags); | 40 | local_irq_restore(flags); |
| 39 | 41 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); | |
| 40 | 42 | ||
| 41 | /* Account time spent with enabled wait psw loaded as idle time. */ | 43 | /* Account time spent with enabled wait psw loaded as idle time. */ |
| 42 | write_seqcount_begin(&idle->seqcount); | 44 | write_seqcount_begin(&idle->seqcount); |
| @@ -523,10 +523,8 @@ static int kprobe_trap_handler(struct pt_regs *regs, int trapnr) · 522 unmodified lines | |||
| 523 | * zero, try to fix up. | 523 | * zero, try to fix up. |
| 524 | */ | 524 | */ |
| 525 | entry = s390_search_extables(regs->psw.addr); | 525 | entry = s390_search_extables(regs->psw.addr); |
| 526 | if (entry) { | 526 | if (entry && ex_handle(entry, regs)) |
| 527 | regs->psw.addr = extable_fixup(entry); | ||
| 528 | return 1; | 527 | return 1; |
| 529 | } | ||
| 530 | 528 | ||
| 531 | /* | 529 | /* |
| 532 | * fixup_exception() could not handle it, | 530 | * fixup_exception() could not handle it, |
| @@ -167,7 +167,7 @@ static struct timer_list lgr_timer; · 166 unmodified lines | |||
| 167 | */ | 167 | */ |
| 168 | static void lgr_timer_set(void) | 168 | static void lgr_timer_set(void) |
| 169 | { | 169 | { |
| 170 | mod_timer(&lgr_timer, jiffies + LGR_TIMER_INTERVAL_SECS * HZ); | 170 | mod_timer(&lgr_timer, jiffies + msecs_to_jiffies(LGR_TIMER_INTERVAL_SECS * MSEC_PER_SEC)); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | /* | 173 | /* |
| @@ -1127,14 +1127,6 @@ void __init setup_arch(char **cmdline_p) · 1126 unmodified lines | |||
| 1127 | free_mem_detect_info(); | 1127 | free_mem_detect_info(); |
| 1128 | remove_oldmem(); | 1128 | remove_oldmem(); |
| 1129 | 1129 | ||
| 1130 | /* | ||
| 1131 | * Make sure all chunks are MAX_ORDER aligned so we don't need the | ||
| 1132 | * extra checks that HOLES_IN_ZONE would require. | ||
| 1133 | * | ||
| 1134 | * Is this still required? | ||
| 1135 | */ | ||
| 1136 | memblock_trim_memory(1UL << (MAX_ORDER - 1 + PAGE_SHIFT)); | ||
| 1137 | |||
| 1138 | if (is_prot_virt_host()) | 1130 | if (is_prot_virt_host()) |
| 1139 | setup_uv(); | 1131 | setup_uv(); |
| 1140 | setup_memory_end(); | 1132 | setup_memory_end(); |
| @@ -1012,10 +1012,6 @@ void __init smp_prepare_boot_cpu(void) · 1011 unmodified lines | |||
| 1012 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 1012 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
| 1013 | } | 1013 | } |
| 1014 | 1014 | ||
| 1015 | void __init smp_cpus_done(unsigned int max_cpus) | ||
| 1016 | { | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | void __init smp_setup_processor_id(void) | 1015 | void __init smp_setup_processor_id(void) |
| 1020 | { | 1016 | { |
| 1021 | pcpu_devices[0].address = stap(); | 1017 | pcpu_devices[0].address = stap(); |
| @@ -1145,6 +1141,7 @@ static int smp_cpu_online(unsigned int cpu) · 123 unmodified lines | |||
| 1145 | 1141 | ||
| 1146 | return sysfs_create_group(&s->kobj, &cpu_online_attr_group); | 1142 | return sysfs_create_group(&s->kobj, &cpu_online_attr_group); |
| 1147 | } | 1143 | } |
| 1144 | |||
| 1148 | static int smp_cpu_pre_down(unsigned int cpu) | 1145 | static int smp_cpu_pre_down(unsigned int cpu) |
| 1149 | { | 1146 | { |
| 1150 | struct device *s = &per_cpu(cpu_device, cpu)->dev; | 1147 | struct device *s = &per_cpu(cpu_device, cpu)->dev; |
| @@ -237,7 +237,7 @@ static u64 read_tod_clock(struct clocksource *cs) · 236 unmodified lines | |||
| 237 | preempt_disable(); /* protect from changes to steering parameters */ | 237 | preempt_disable(); /* protect from changes to steering parameters */ |
| 238 | now = get_tod_clock(); | 238 | now = get_tod_clock(); |
| 239 | adj = tod_steering_end - now; | 239 | adj = tod_steering_end - now; |
| 240 | if (unlikely((s64) adj >= 0)) | 240 | if (unlikely((s64) adj > 0)) |
| 241 | /* | 241 | /* |
| 242 | * manually steer by 1 cycle every 2^16 cycles. This | 242 | * manually steer by 1 cycle every 2^16 cycles. This |
| 243 | * corresponds to shifting the tod delta by 15. 1s is | 243 | * corresponds to shifting the tod delta by 15. 1s is |
| @@ -253,7 +253,7 @@ static struct clocksource clocksource_tod = { · 9 unmodified lines | |||
| 253 | .name = "tod", | 253 | .name = "tod", |
| 254 | .rating = 400, | 254 | .rating = 400, |
| 255 | .read = read_tod_clock, | 255 | .read = read_tod_clock, |
| 256 | .mask = -1ULL, | 256 | .mask = CLOCKSOURCE_MASK(64), |
| 257 | .mult = 1000, | 257 | .mult = 1000, |
| 258 | .shift = 12, | 258 | .shift = 12, |
| 259 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 259 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| @@ -669,7 +669,7 @@ static void stp_work_fn(struct work_struct *work) · 409 unmodified lines | |||
| 669 | * There is a usable clock but the synchonization failed. | 669 | * There is a usable clock but the synchonization failed. |
| 670 | * Retry after a second. | 670 | * Retry after a second. |
| 671 | */ | 671 | */ |
| 672 | mod_timer(&stp_timer, jiffies + HZ); | 672 | mod_timer(&stp_timer, jiffies + msecs_to_jiffies(MSEC_PER_SEC)); |
| 673 | 673 | ||
| 674 | out_unlock: | 674 | out_unlock: |
| 675 | mutex_unlock(&stp_work_mutex); | 675 | mutex_unlock(&stp_work_mutex); |
| @@ -683,7 +683,7 @@ static struct bus_type stp_subsys = { · 7 unmodified lines | |||
| 683 | .dev_name = "stp", | 683 | .dev_name = "stp", |
| 684 | }; | 684 | }; |
| 685 | 685 | ||
| 686 | static ssize_t stp_ctn_id_show(struct device *dev, | 686 | static ssize_t ctn_id_show(struct device *dev, |
| 687 | struct device_attribute *attr, | 687 | struct device_attribute *attr, |
| 688 | char *buf) | 688 | char *buf) |
| 689 | { | 689 | { |
| @@ -693,9 +693,9 @@ static ssize_t stp_ctn_id_show(struct device *dev, · 3 unmodified lines | |||
| 693 | *(unsigned long long *) stp_info.ctnid); | 693 | *(unsigned long long *) stp_info.ctnid); |
| 694 | } | 694 | } |
| 695 | 695 | ||
| 696 | static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); | 696 | static DEVICE_ATTR_RO(ctn_id); |
| 697 | 697 | ||
| 698 | static ssize_t stp_ctn_type_show(struct device *dev, | 698 | static ssize_t ctn_type_show(struct device *dev, |
| 699 | struct device_attribute *attr, | 699 | struct device_attribute *attr, |
| 700 | char *buf) | 700 | char *buf) |
| 701 | { | 701 | { |
| @@ -704,9 +704,9 @@ static ssize_t stp_ctn_type_show(struct device *dev, · 2 unmodified lines | |||
| 704 | return sprintf(buf, "%i\n", stp_info.ctn); | 704 | return sprintf(buf, "%i\n", stp_info.ctn); |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); | 707 | static DEVICE_ATTR_RO(ctn_type); |
| 708 | 708 | ||
| 709 | static ssize_t stp_dst_offset_show(struct device *dev, | 709 | static ssize_t dst_offset_show(struct device *dev, |
| 710 | struct device_attribute *attr, | 710 | struct device_attribute *attr, |
| 711 | char *buf) | 711 | char *buf) |
| 712 | { | 712 | { |
| @@ -715,9 +715,9 @@ static ssize_t stp_dst_offset_show(struct device *dev, · 2 unmodified lines | |||
| 715 | return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); | 715 | return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); |
| 716 | } | 716 | } |
| 717 | 717 | ||
| 718 | static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); | 718 | static DEVICE_ATTR_RO(dst_offset); |
| 719 | 719 | ||
| 720 | static ssize_t stp_leap_seconds_show(struct device *dev, | 720 | static ssize_t leap_seconds_show(struct device *dev, |
| 721 | struct device_attribute *attr, | 721 | struct device_attribute *attr, |
| 722 | char *buf) | 722 | char *buf) |
| 723 | { | 723 | { |
| @@ -726,9 +726,9 @@ static ssize_t stp_leap_seconds_show(struct device *dev, · 2 unmodified lines | |||
| 726 | return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); | 726 | return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); | 729 | static DEVICE_ATTR_RO(leap_seconds); |
| 730 | 730 | ||
| 731 | static ssize_t stp_stratum_show(struct device *dev, | 731 | static ssize_t stratum_show(struct device *dev, |
| 732 | struct device_attribute *attr, | 732 | struct device_attribute *attr, |
| 733 | char *buf) | 733 | char *buf) |
| 734 | { | 734 | { |
| @@ -737,9 +737,9 @@ static ssize_t stp_stratum_show(struct device *dev, · 2 unmodified lines | |||
| 737 | return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); | 737 | return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); |
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL); | 740 | static DEVICE_ATTR_RO(stratum); |
| 741 | 741 | ||
| 742 | static ssize_t stp_time_offset_show(struct device *dev, | 742 | static ssize_t time_offset_show(struct device *dev, |
| 743 | struct device_attribute *attr, | 743 | struct device_attribute *attr, |
| 744 | char *buf) | 744 | char *buf) |
| 745 | { | 745 | { |
| @@ -748,9 +748,9 @@ static ssize_t stp_time_offset_show(struct device *dev, · 2 unmodified lines | |||
| 748 | return sprintf(buf, "%i\n", (int) stp_info.tto); | 748 | return sprintf(buf, "%i\n", (int) stp_info.tto); |
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL); | 751 | static DEVICE_ATTR_RO(time_offset); |
| 752 | 752 | ||
| 753 | static ssize_t stp_time_zone_offset_show(struct device *dev, | 753 | static ssize_t time_zone_offset_show(struct device *dev, |
| 754 | struct device_attribute *attr, | 754 | struct device_attribute *attr, |
| 755 | char *buf) | 755 | char *buf) |
| 756 | { | 756 | { |
| @@ -759,10 +759,9 @@ static ssize_t stp_time_zone_offset_show(struct device *dev, · 2 unmodified lines | |||
| 759 | return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); | 759 | return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); |
| 760 | } | 760 | } |
| 761 | 761 | ||
| 762 | static DEVICE_ATTR(time_zone_offset, 0400, | 762 | static DEVICE_ATTR_RO(time_zone_offset); |
| 763 | stp_time_zone_offset_show, NULL); | ||
| 764 | 763 | ||
| 765 | static ssize_t stp_timing_mode_show(struct device *dev, | 764 | static ssize_t timing_mode_show(struct device *dev, |
| 766 | struct device_attribute *attr, | 765 | struct device_attribute *attr, |
| 767 | char *buf) | 766 | char *buf) |
| 768 | { | 767 | { |
| @@ -771,9 +770,9 @@ static ssize_t stp_timing_mode_show(struct device *dev, · 2 unmodified lines | |||
| 771 | return sprintf(buf, "%i\n", stp_info.tmd); | 770 | return sprintf(buf, "%i\n", stp_info.tmd); |
| 772 | } | 771 | } |
| 773 | 772 | ||
| 774 | static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); | 773 | static DEVICE_ATTR_RO(timing_mode); |
| 775 | 774 | ||
| 776 | static ssize_t stp_timing_state_show(struct device *dev, | 775 | static ssize_t timing_state_show(struct device *dev, |
| 777 | struct device_attribute *attr, | 776 | struct device_attribute *attr, |
| 778 | char *buf) | 777 | char *buf) |
| 779 | { | 778 | { |
| @@ -782,16 +781,16 @@ static ssize_t stp_timing_state_show(struct device *dev, · 2 unmodified lines | |||
| 782 | return sprintf(buf, "%i\n", stp_info.tst); | 781 | return sprintf(buf, "%i\n", stp_info.tst); |
| 783 | } | 782 | } |
| 784 | 783 | ||
| 785 | static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL); | 784 | static DEVICE_ATTR_RO(timing_state); |
| 786 | 785 | ||
| 787 | static ssize_t stp_online_show(struct device *dev, | 786 | static ssize_t online_show(struct device *dev, |
| 788 | struct device_attribute *attr, | 787 | struct device_attribute *attr, |
| 789 | char *buf) | 788 | char *buf) |
| 790 | { | 789 | { |
| 791 | return sprintf(buf, "%i\n", stp_online); | 790 | return sprintf(buf, "%i\n", stp_online); |
| 792 | } | 791 | } |
| 793 | 792 | ||
| 794 | static ssize_t stp_online_store(struct device *dev, | 793 | static ssize_t online_store(struct device *dev, |
| 795 | struct device_attribute *attr, | 794 | struct device_attribute *attr, |
| 796 | const char *buf, size_t count) | 795 | const char *buf, size_t count) |
| 797 | { | 796 | { |
| @@ -817,18 +816,14 @@ static ssize_t stp_online_store(struct device *dev, · 19 unmodified lines | |||
| 817 | * Can't use DEVICE_ATTR because the attribute should be named | 816 | * Can't use DEVICE_ATTR because the attribute should be named |
| 818 | * stp/online but dev_attr_online already exists in this file .. | 817 | * stp/online but dev_attr_online already exists in this file .. |
| 819 | */ | 818 | */ |
| 820 | static struct device_attribute dev_attr_stp_online = { | 819 | static DEVICE_ATTR_RW(online); |
| 821 | .attr = { .name = "online", .mode = 0600 }, | ||
| 822 | .show = stp_online_show, | ||
| 823 | .store = stp_online_store, | ||
| 824 | }; | ||
| 825 | 820 | ||
| 826 | static struct device_attribute *stp_attributes[] = { | 821 | static struct device_attribute *stp_attributes[] = { |
| 827 | &dev_attr_ctn_id, | 822 | &dev_attr_ctn_id, |
| 828 | &dev_attr_ctn_type, | 823 | &dev_attr_ctn_type, |
| 829 | &dev_attr_dst_offset, | 824 | &dev_attr_dst_offset, |
| 830 | &dev_attr_leap_seconds, | 825 | &dev_attr_leap_seconds, |
| 831 | &dev_attr_stp_online, | 826 | &dev_attr_online, |
| 832 | &dev_attr_stratum, | 827 | &dev_attr_stratum, |
| 833 | &dev_attr_time_offset, | 828 | &dev_attr_time_offset, |
| 834 | &dev_attr_time_zone_offset, | 829 | &dev_attr_time_zone_offset, |
| @@ -356,9 +356,9 @@ static atomic_t topology_poll = ATOMIC_INIT(0); · 355 unmodified lines | |||
| 356 | static void set_topology_timer(void) | 356 | static void set_topology_timer(void) |
| 357 | { | 357 | { |
| 358 | if (atomic_add_unless(&topology_poll, -1, 0)) | 358 | if (atomic_add_unless(&topology_poll, -1, 0)) |
| 359 | mod_timer(&topology_timer, jiffies + HZ / 10); | 359 | mod_timer(&topology_timer, jiffies + msecs_to_jiffies(100)); |
| 360 | else | 360 | else |
| 361 | mod_timer(&topology_timer, jiffies + HZ * 60); | 361 | mod_timer(&topology_timer, jiffies + msecs_to_jiffies(60 * MSEC_PER_SEC)); |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | void topology_expect_change(void) | 364 | void topology_expect_change(void) |
| @@ -50,11 +50,8 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str) · 49 unmodified lines | |||
| 50 | } else { | 50 | } else { |
| 51 | const struct exception_table_entry *fixup; | 51 | const struct exception_table_entry *fixup; |
| 52 | fixup = s390_search_extables(regs->psw.addr); | 52 | fixup = s390_search_extables(regs->psw.addr); |
| 53 | if (fixup) | 53 | if (!fixup || !ex_handle(fixup, regs)) |
| 54 | regs->psw.addr = extable_fixup(fixup); | ||
| 55 | else { | ||
| 56 | die(regs, str); | 54 | die(regs, str); |
| 57 | } | ||
| 58 | } | 55 | } |
| 59 | } | 56 | } |
| 60 | 57 | ||
| @@ -251,7 +248,7 @@ void monitor_event_exception(struct pt_regs *regs) · 190 unmodified lines | |||
| 251 | case BUG_TRAP_TYPE_NONE: | 248 | case BUG_TRAP_TYPE_NONE: |
| 252 | fixup = s390_search_extables(regs->psw.addr); | 249 | fixup = s390_search_extables(regs->psw.addr); |
| 253 | if (fixup) | 250 | if (fixup) |
| 254 | regs->psw.addr = extable_fixup(fixup); | 251 | ex_handle(fixup, regs); |
| 255 | break; | 252 | break; |
| 256 | case BUG_TRAP_TYPE_WARN: | 253 | case BUG_TRAP_TYPE_WARN: |
| 257 | break; | 254 | break; |
| @@ -14,3 +14,5 @@ KASAN_SANITIZE_uaccess.o := n · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | obj-$(CONFIG_S390_UNWIND_SELFTEST) += test_unwind.o | 15 | obj-$(CONFIG_S390_UNWIND_SELFTEST) += test_unwind.o |
| 16 | CFLAGS_test_unwind.o += -fno-optimize-sibling-calls | 16 | CFLAGS_test_unwind.o += -fno-optimize-sibling-calls |
| 17 | |||
| 18 | lib-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | #include <asm/ptrace.h> | ||
| 3 | #include <linux/error-injection.h> | ||
| 4 | #include <linux/kprobes.h> | ||
| 5 | |||
| 6 | void override_function_with_return(struct pt_regs *regs) | ||
| 7 | { | ||
| 8 | /* | ||
| 9 | * Emulate 'br 14'. 'regs' is captured by kprobes on entry to some | ||
| 10 | * kernel function. | ||
| 11 | */ | ||
| 12 | regs->psw.addr = regs->gprs[14]; | ||
| 13 | } | ||
| 14 | NOKPROBE_SYMBOL(override_function_with_return); | ||
| @@ -189,7 +189,7 @@ static void cmm_set_timer(void) · 188 unmodified lines | |||
| 189 | del_timer(&cmm_timer); | 189 | del_timer(&cmm_timer); |
| 190 | return; | 190 | return; |
| 191 | } | 191 | } |
| 192 | mod_timer(&cmm_timer, jiffies + cmm_timeout_seconds * HZ); | 192 | mod_timer(&cmm_timer, jiffies + msecs_to_jiffies(cmm_timeout_seconds * MSEC_PER_SEC)); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | static void cmm_timer_fn(struct timer_list *unused) | 195 | static void cmm_timer_fn(struct timer_list *unused) |
| @@ -313,15 +313,10 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long · 312 unmodified lines | |||
| 313 | goto out_free; | 313 | goto out_free; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1); | ||
| 317 | |||
| 318 | if (rc) | ||
| 319 | goto out_free; | ||
| 320 | |||
| 321 | seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL); | 316 | seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL); |
| 322 | if (seg->res == NULL) { | 317 | if (seg->res == NULL) { |
| 323 | rc = -ENOMEM; | 318 | rc = -ENOMEM; |
| 324 | goto out_shared; | 319 | goto out_free; |
| 325 | } | 320 | } |
| 326 | seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; | 321 | seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; |
| 327 | seg->res->start = seg->start_addr; | 322 | seg->res->start = seg->start_addr; |
| @@ -335,12 +330,17 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long · 7 unmodified lines | |||
| 335 | if (rc == SEG_TYPE_SC || | 330 | if (rc == SEG_TYPE_SC || |
| 336 | ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared)) | 331 | ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared)) |
| 337 | seg->res->flags |= IORESOURCE_READONLY; | 332 | seg->res->flags |= IORESOURCE_READONLY; |
| 333 | |||
| 334 | /* Check for overlapping resources before adding the mapping. */ | ||
| 338 | if (request_resource(&iomem_resource, seg->res)) { | 335 | if (request_resource(&iomem_resource, seg->res)) { |
| 339 | rc = -EBUSY; | 336 | rc = -EBUSY; |
| 340 | kfree(seg->res); | 337 | goto out_free_resource; |
| 341 | goto out_shared; | ||
| 342 | } | 338 | } |
| 343 | 339 | ||
| 340 | rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1); | ||
| 341 | if (rc) | ||
| 342 | goto out_resource; | ||
| 343 | |||
| 344 | if (do_nonshared) | 344 | if (do_nonshared) |
| 345 | diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, | 345 | diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, |
| 346 | &start_addr, &end_addr); | 346 | &start_addr, &end_addr); |
| @@ -351,14 +351,14 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long · 4 unmodified lines | |||
| 351 | dcss_diag(&purgeseg_scode, seg->dcss_name, | 351 | dcss_diag(&purgeseg_scode, seg->dcss_name, |
| 352 | &dummy, &dummy); | 352 | &dummy, &dummy); |
| 353 | rc = diag_cc; | 353 | rc = diag_cc; |
| 354 | goto out_resource; | 354 | goto out_mapping; |
| 355 | } | 355 | } |
| 356 | if (diag_cc > 1) { | 356 | if (diag_cc > 1) { |
| 357 | pr_warn("Loading DCSS %s failed with rc=%ld\n", name, end_addr); | 357 | pr_warn("Loading DCSS %s failed with rc=%ld\n", name, end_addr); |
| 358 | rc = dcss_diag_translate_rc(end_addr); | 358 | rc = dcss_diag_translate_rc(end_addr); |
| 359 | dcss_diag(&purgeseg_scode, seg->dcss_name, | 359 | dcss_diag(&purgeseg_scode, seg->dcss_name, |
| 360 | &dummy, &dummy); | 360 | &dummy, &dummy); |
| 361 | goto out_resource; | 361 | goto out_mapping; |
| 362 | } | 362 | } |
| 363 | seg->start_addr = start_addr; | 363 | seg->start_addr = start_addr; |
| 364 | seg->end = end_addr; | 364 | seg->end = end_addr; |
| @@ -377,11 +377,12 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long · 12 unmodified lines | |||
| 377 | (void*) seg->end, segtype_string[seg->vm_segtype]); | 377 | (void*) seg->end, segtype_string[seg->vm_segtype]); |
| 378 | } | 378 | } |
| 379 | goto out; | 379 | goto out; |
| 380 | out_mapping: | ||
| 381 | vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); | ||
| 380 | out_resource: | 382 | out_resource: |
| 381 | release_resource(seg->res); | 383 | release_resource(seg->res); |
| 384 | out_free_resource: | ||
| 382 | kfree(seg->res); | 385 | kfree(seg->res); |
| 383 | out_shared: | ||
| 384 | vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); | ||
| 385 | out_free: | 386 | out_free: |
| 386 | kfree(seg); | 387 | kfree(seg); |
| 387 | out: | 388 | out: |
| @@ -400,8 +401,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long · 12 unmodified lines | |||
| 400 | * -EIO : could not perform query or load diagnose | 401 | * -EIO : could not perform query or load diagnose |
| 401 | * -ENOENT : no such segment | 402 | * -ENOENT : no such segment |
| 402 | * -EOPNOTSUPP: multi-part segment cannot be used with linux | 403 | * -EOPNOTSUPP: multi-part segment cannot be used with linux |
| 403 | * -ENOSPC : segment cannot be used (overlaps with storage) | 404 | * -EBUSY : segment cannot be used (overlaps with dcss or storage) |
| 404 | * -EBUSY : segment can temporarily not be used (overlaps with dcss) | ||
| 405 | * -ERANGE : segment cannot be used (exceeds kernel mapping range) | 405 | * -ERANGE : segment cannot be used (exceeds kernel mapping range) |
| 406 | * -EPERM : segment is currently loaded with incompatible permissions | 406 | * -EPERM : segment is currently loaded with incompatible permissions |
| 407 | * -ENOMEM : out of memory | 407 | * -ENOMEM : out of memory |
| @@ -626,10 +626,6 @@ void segment_warning(int rc, char *seg_name) · 218 unmodified lines | |||
| 626 | pr_err("DCSS %s has multiple page ranges and cannot be " | 626 | pr_err("DCSS %s has multiple page ranges and cannot be " |
| 627 | "loaded or queried\n", seg_name); | 627 | "loaded or queried\n", seg_name); |
| 628 | break; | 628 | break; |
| 629 | case -ENOSPC: | ||
| 630 | pr_err("DCSS %s overlaps with used storage and cannot " | ||
| 631 | "be loaded\n", seg_name); | ||
| 632 | break; | ||
| 633 | case -EBUSY: | 629 | case -EBUSY: |
| 634 | pr_err("%s needs used memory resources and cannot be " | 630 | pr_err("%s needs used memory resources and cannot be " |
| 635 | "loaded or queried\n", seg_name); | 631 | "loaded or queried\n", seg_name); |
| @@ -255,10 +255,8 @@ static noinline void do_no_context(struct pt_regs *regs) · 254 unmodified lines | |||
| 255 | 255 | ||
| 256 | /* Are we prepared to handle this kernel fault? */ | 256 | /* Are we prepared to handle this kernel fault? */ |
| 257 | fixup = s390_search_extables(regs->psw.addr); | 257 | fixup = s390_search_extables(regs->psw.addr); |
| 258 | if (fixup) { | 258 | if (fixup && ex_handle(fixup, regs)) |
| 259 | regs->psw.addr = extable_fixup(fixup); | ||
| 260 | return; | 259 | return; |
| 261 | } | ||
| 262 | 260 | ||
| 263 | /* | 261 | /* |
| 264 | * Oops. The kernel tried to access some bad page. We'll have to | 262 | * Oops. The kernel tried to access some bad page. We'll have to |
| @@ -376,7 +374,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int access, · 111 unmodified lines | |||
| 376 | * routines. | 374 | * routines. |
| 377 | * | 375 | * |
| 378 | * interruption code (int_code): | 376 | * interruption code (int_code): |
| 379 | * 04 Protection -> Write-Protection (suprression) | 377 | * 04 Protection -> Write-Protection (suppression) |
| 380 | * 10 Segment translation -> Not present (nullification) | 378 | * 10 Segment translation -> Not present (nullification) |
| 381 | * 11 Page translation -> Not present (nullification) | 379 | * 11 Page translation -> Not present (nullification) |
| 382 | * 3b Region third trans. -> Not present (nullification) | 380 | * 3b Region third trans. -> Not present (nullification) |
| @@ -20,14 +20,6 @@ · 19 unmodified lines | |||
| 20 | 20 | ||
| 21 | static DEFINE_MUTEX(vmem_mutex); | 21 | static DEFINE_MUTEX(vmem_mutex); |
| 22 | 22 | ||
| 23 | struct memory_segment { | ||
| 24 | struct list_head list; | ||
| 25 | unsigned long start; | ||
| 26 | unsigned long size; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static LIST_HEAD(mem_segs); | ||
| 30 | |||
| 31 | static void __ref *vmem_alloc_pages(unsigned int order) | 23 | static void __ref *vmem_alloc_pages(unsigned int order) |
| 32 | { | 24 | { |
| 33 | unsigned long size = PAGE_SIZE << order; | 25 | unsigned long size = PAGE_SIZE << order; |
| @@ -37,6 +29,15 @@ static void __ref *vmem_alloc_pages(unsigned int order) · 3 unmodified lines | |||
| 37 | return (void *) memblock_phys_alloc(size, size); | 29 | return (void *) memblock_phys_alloc(size, size); |
| 38 | } | 30 | } |
| 39 | 31 | ||
| 32 | static void vmem_free_pages(unsigned long addr, int order) | ||
| 33 | { | ||
| 34 | /* We don't expect boot memory to be removed ever. */ | ||
| 35 | if (!slab_is_available() || | ||
| 36 | WARN_ON_ONCE(PageReserved(phys_to_page(addr)))) | ||
| 37 | return; | ||
| 38 | free_pages(addr, order); | ||
| 39 | } | ||
| 40 | |||
| 40 | void *vmem_crst_alloc(unsigned long val) | 41 | void *vmem_crst_alloc(unsigned long val) |
| 41 | { | 42 | { |
| 42 | unsigned long *table; | 43 | unsigned long *table; |
| @@ -62,332 +63,486 @@ pte_t __ref *vmem_pte_alloc(void) · 19 unmodified lines | |||
| 62 | return pte; | 63 | return pte; |
| 63 | } | 64 | } |
| 64 | 65 | ||
| 66 | static void vmem_pte_free(unsigned long *table) | ||
| 67 | { | ||
| 68 | /* We don't expect boot memory to be removed ever. */ | ||
| 69 | if (!slab_is_available() || | ||
| 70 | WARN_ON_ONCE(PageReserved(virt_to_page(table)))) | ||
| 71 | return; | ||
| 72 | page_table_free(&init_mm, table); | ||
| 73 | } | ||
| 74 | |||
| 75 | #define PAGE_UNUSED 0xFD | ||
| 76 | |||
| 65 | /* | 77 | /* |
| 66 | * Add a physical memory range to the 1:1 mapping. | 78 | * The unused vmemmap range, which was not yet memset(PAGE_UNUSED) ranges |
| 79 | * from unused_pmd_start to next PMD_SIZE boundary. | ||
| 67 | */ | 80 | */ |
| 68 | static int vmem_add_mem(unsigned long start, unsigned long size) | 81 | static unsigned long unused_pmd_start; |
| 82 | |||
| 83 | static void vmemmap_flush_unused_pmd(void) | ||
| 69 | { | 84 | { |
| 70 | unsigned long pgt_prot, sgt_prot, r3_prot; | 85 | if (!unused_pmd_start) |
| 71 | unsigned long pages4k, pages1m, pages2g; | 86 | return; |
| 72 | unsigned long end = start + size; | 87 | memset(__va(unused_pmd_start), PAGE_UNUSED, |
| 73 | unsigned long address = start; | 88 | ALIGN(unused_pmd_start, PMD_SIZE) - unused_pmd_start); |
| 74 | pgd_t *pg_dir; | 89 | unused_pmd_start = 0; |
| 75 | p4d_t *p4_dir; | 90 | } |
| 76 | pud_t *pu_dir; | 91 | |
| 77 | pmd_t *pm_dir; | 92 | static void __vmemmap_use_sub_pmd(unsigned long start, unsigned long end) |
| 78 | pte_t *pt_dir; | 93 | { |
| 79 | int ret = -ENOMEM; | 94 | /* |
| 95 | * As we expect to add in the same granularity as we remove, it's | ||
| 96 | * sufficient to mark only some piece used to block the memmap page from | ||
| 97 | * getting removed (just in case the memmap never gets initialized, | ||
| 98 | * e.g., because the memory block never gets onlined). | ||
| 99 | */ | ||
| 100 | memset(__va(start), 0, sizeof(struct page)); | ||
| 101 | } | ||
| 80 | 102 | ||
| 81 | pgt_prot = pgprot_val(PAGE_KERNEL); | 103 | static void vmemmap_use_sub_pmd(unsigned long start, unsigned long end) |
| 82 | sgt_prot = pgprot_val(SEGMENT_KERNEL); | 104 | { |
| 83 | r3_prot = pgprot_val(REGION3_KERNEL); | 105 | /* |
| 84 | if (!MACHINE_HAS_NX) { | 106 | * We only optimize if the new used range directly follows the |
| 85 | pgt_prot &= ~_PAGE_NOEXEC; | 107 | * previously unused range (esp., when populating consecutive sections). |
| 86 | sgt_prot &= ~_SEGMENT_ENTRY_NOEXEC; | 108 | */ |
| 87 | r3_prot &= ~_REGION_ENTRY_NOEXEC; | 109 | if (unused_pmd_start == start) { |
| 110 | unused_pmd_start = end; | ||
| 111 | if (likely(IS_ALIGNED(unused_pmd_start, PMD_SIZE))) | ||
| 112 | unused_pmd_start = 0; | ||
| 113 | return; | ||
| 88 | } | 114 | } |
| 89 | pages4k = pages1m = pages2g = 0; | 115 | vmemmap_flush_unused_pmd(); |
| 90 | while (address < end) { | 116 | __vmemmap_use_sub_pmd(start, end); |
| 91 | pg_dir = pgd_offset_k(address); | 117 | } |
| 92 | if (pgd_none(*pg_dir)) { | 118 | |
| 93 | p4_dir = vmem_crst_alloc(_REGION2_ENTRY_EMPTY); | 119 | static void vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end) |
| 94 | if (!p4_dir) | 120 | { |
| 95 | goto out; | 121 | void *page = __va(ALIGN_DOWN(start, PMD_SIZE)); |
| 96 | pgd_populate(&init_mm, pg_dir, p4_dir); | 122 | |
| 97 | } | 123 | vmemmap_flush_unused_pmd(); |
| 98 | p4_dir = p4d_offset(pg_dir, address); | 124 | |
| 99 | if (p4d_none(*p4_dir)) { | 125 | /* Could be our memmap page is filled with PAGE_UNUSED already ... */ |
| 100 | pu_dir = vmem_crst_alloc(_REGION3_ENTRY_EMPTY); | 126 | __vmemmap_use_sub_pmd(start, end); |
| 101 | if (!pu_dir) | 127 | |
| 102 | goto out; | 128 | /* Mark the unused parts of the new memmap page PAGE_UNUSED. */ |
| 103 | p4d_populate(&init_mm, p4_dir, pu_dir); | 129 | if (!IS_ALIGNED(start, PMD_SIZE)) |
| 104 | } | 130 | memset(page, PAGE_UNUSED, start - __pa(page)); |
| 105 | pu_dir = pud_offset(p4_dir, address); | 131 | /* |
| 106 | if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address && | 132 | * We want to avoid memset(PAGE_UNUSED) when populating the vmemmap of |
| 107 | !(address & ~PUD_MASK) && (address + PUD_SIZE <= end) && | 133 | * consecutive sections. Remember for the last added PMD the last |
| 108 | !debug_pagealloc_enabled()) { | 134 | * unused range in the populated PMD. |
| 109 | pud_val(*pu_dir) = address | r3_prot; | 135 | */ |
| 110 | address += PUD_SIZE; | 136 | if (!IS_ALIGNED(end, PMD_SIZE)) |
| 111 | pages2g++; | 137 | unused_pmd_start = end; |
| 112 | continue; | 138 | } |
| 113 | } | 139 | |
| 114 | if (pud_none(*pu_dir)) { | 140 | /* Returns true if the PMD is completely unused and can be freed. */ |
| 115 | pm_dir = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY); | 141 | static bool vmemmap_unuse_sub_pmd(unsigned long start, unsigned long end) |
| 116 | if (!pm_dir) | 142 | { |
| 117 | goto out; | 143 | void *page = __va(ALIGN_DOWN(start, PMD_SIZE)); |
| 118 | pud_populate(&init_mm, pu_dir, pm_dir); | 144 | |
| 119 | } | 145 | vmemmap_flush_unused_pmd(); |
| 120 | pm_dir = pmd_offset(pu_dir, address); | 146 | memset(__va(start), PAGE_UNUSED, end - start); |
| 121 | if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address && | 147 | return !memchr_inv(page, PAGE_UNUSED, PMD_SIZE); |
| 122 | !(address & ~PMD_MASK) && (address + PMD_SIZE <= end) && | 148 | } |
| 123 | !debug_pagealloc_enabled()) { | 149 | |
| 124 | pmd_val(*pm_dir) = address | sgt_prot; | 150 | /* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */ |
| 125 | address += PMD_SIZE; | 151 | static int __ref modify_pte_table(pmd_t *pmd, unsigned long addr, |
| 126 | pages1m++; | 152 | unsigned long end, bool add, bool direct) |
| 153 | { | ||
| 154 | unsigned long prot, pages = 0; | ||
| 155 | int ret = -ENOMEM; | ||
| 156 | pte_t *pte; | ||
| 157 | |||
| 158 | prot = pgprot_val(PAGE_KERNEL); | ||
| 159 | if (!MACHINE_HAS_NX) | ||
| 160 | prot &= ~_PAGE_NOEXEC; | ||
| 161 | |||
| 162 | pte = pte_offset_kernel(pmd, addr); | ||
| 163 | for (; addr < end; addr += PAGE_SIZE, pte++) { | ||
| 164 | if (!add) { | ||
| 165 | if (pte_none(*pte)) | ||
| 166 | continue; | ||
| 167 | if (!direct) | ||
| 168 | vmem_free_pages(pfn_to_phys(pte_pfn(*pte)), 0); | ||
| 169 | pte_clear(&init_mm, addr, pte); | ||
| 170 | } else if (pte_none(*pte)) { | ||
| 171 | if (!direct) { | ||
| 172 | void *new_page = vmemmap_alloc_block(PAGE_SIZE, NUMA_NO_NODE); | ||
| 173 | |||
| 174 | if (!new_page) | ||
| 175 | goto out; | ||
| 176 | pte_val(*pte) = __pa(new_page) | prot; | ||
| 177 | } else { | ||
| 178 | pte_val(*pte) = addr | prot; | ||
| 179 | } | ||
| 180 | } else { | ||
| 127 | continue; | 181 | continue; |
| 128 | } | 182 | } |
| 129 | if (pmd_none(*pm_dir)) { | 183 | pages++; |
| 130 | pt_dir = vmem_pte_alloc(); | ||
| 131 | if (!pt_dir) | ||
| 132 | goto out; | ||
| 133 | pmd_populate(&init_mm, pm_dir, pt_dir); | ||
| 134 | } | ||
| 135 | |||
| 136 | pt_dir = pte_offset_kernel(pm_dir, address); | ||
| 137 | pte_val(*pt_dir) = address | pgt_prot; | ||
| 138 | address += PAGE_SIZE; | ||
| 139 | pages4k++; | ||
| 140 | } | 184 | } |
| 141 | ret = 0; | 185 | ret = 0; |
| 142 | out: | 186 | out: |
| 143 | update_page_count(PG_DIRECT_MAP_4K, pages4k); | 187 | if (direct) |
| 144 | update_page_count(PG_DIRECT_MAP_1M, pages1m); | 188 | update_page_count(PG_DIRECT_MAP_4K, add ? pages : -pages); |
| 145 | update_page_count(PG_DIRECT_MAP_2G, pages2g); | ||
| 146 | return ret; | 189 | return ret; |
| 147 | } | 190 | } |
| 148 | 191 | ||
| 149 | /* | 192 | static void try_free_pte_table(pmd_t *pmd, unsigned long start) |
| 150 | * Remove a physical memory range from the 1:1 mapping. | ||
| 151 | * Currently only invalidates page table entries. | ||
| 152 | */ | ||
| 153 | static void vmem_remove_range(unsigned long start, unsigned long size) | ||
| 154 | { | 193 | { |
| 155 | unsigned long pages4k, pages1m, pages2g; | 194 | pte_t *pte; |
| 156 | unsigned long end = start + size; | 195 | int i; |
| 157 | unsigned long address = start; | 196 | |
| 158 | pgd_t *pg_dir; | 197 | /* We can safely assume this is fully in 1:1 mapping & vmemmap area */ |
| 159 | p4d_t *p4_dir; | 198 | pte = pte_offset_kernel(pmd, start); |
| 160 | pud_t *pu_dir; | 199 | for (i = 0; i < PTRS_PER_PTE; i++, pte++) { |
| 161 | pmd_t *pm_dir; | 200 | if (!pte_none(*pte)) |
| 162 | pte_t *pt_dir; | 201 | return; |
| 163 | |||
| 164 | pages4k = pages1m = pages2g = 0; | ||
| 165 | while (address < end) { | ||
| 166 | pg_dir = pgd_offset_k(address); | ||
| 167 | if (pgd_none(*pg_dir)) { | ||
| 168 | address += PGDIR_SIZE; | ||
| 169 | continue; | ||
| 170 | } | ||
| 171 | p4_dir = p4d_offset(pg_dir, address); | ||
| 172 | if (p4d_none(*p4_dir)) { | ||
| 173 | address += P4D_SIZE; | ||
| 174 | continue; | ||
| 175 | } | ||
| 176 | pu_dir = pud_offset(p4_dir, address); | ||
| 177 | if (pud_none(*pu_dir)) { | ||
| 178 | address += PUD_SIZE; | ||
| 179 | continue; | ||
| 180 | } | ||
| 181 | if (pud_large(*pu_dir)) { | ||
| 182 | pud_clear(pu_dir); | ||
| 183 | address += PUD_SIZE; | ||
| 184 | pages2g++; | ||
| 185 | continue; | ||
| 186 | } | ||
| 187 | pm_dir = pmd_offset(pu_dir, address); | ||
| 188 | if (pmd_none(*pm_dir)) { | ||
| 189 | address += PMD_SIZE; | ||
| 190 | continue; | ||
| 191 | } | ||
| 192 | if (pmd_large(*pm_dir)) { | ||
| 193 | pmd_clear(pm_dir); | ||
| 194 | address += PMD_SIZE; | ||
| 195 | pages1m++; | ||
| 196 | continue; | ||
| 197 | } | ||
| 198 | pt_dir = pte_offset_kernel(pm_dir, address); | ||
| 199 | pte_clear(&init_mm, address, pt_dir); | ||
| 200 | address += PAGE_SIZE; | ||
| 201 | pages4k++; | ||
| 202 | } | 202 | } |
| 203 | flush_tlb_kernel_range(start, end); | 203 | vmem_pte_free(__va(pmd_deref(*pmd))); |
| 204 | update_page_count(PG_DIRECT_MAP_4K, -pages4k); | 204 | pmd_clear(pmd); |
| 205 | update_page_count(PG_DIRECT_MAP_1M, -pages1m); | ||
| 206 | update_page_count(PG_DIRECT_MAP_2G, -pages2g); | ||
| 207 | } | 205 | } |
| 208 | 206 | ||
| 209 | /* | 207 | /* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */ |
| 210 | * Add a backed mem_map array to the virtual mem_map array. | 208 | static int __ref modify_pmd_table(pud_t *pud, unsigned long addr, |
| 211 | */ | 209 | unsigned long end, bool add, bool direct) |
| 212 | int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, | ||
| 213 | struct vmem_altmap *altmap) | ||
| 214 | { | 210 | { |
| 215 | unsigned long pgt_prot, sgt_prot; | 211 | unsigned long next, prot, pages = 0; |
| 216 | unsigned long address = start; | ||
| 217 | pgd_t *pg_dir; | ||
| 218 | p4d_t *p4_dir; | ||
| 219 | pud_t *pu_dir; | ||
| 220 | pmd_t *pm_dir; | ||
| 221 | pte_t *pt_dir; | ||
| 222 | int ret = -ENOMEM; | 212 | int ret = -ENOMEM; |
| 213 | pmd_t *pmd; | ||
| 214 | pte_t *pte; | ||
| 223 | 215 | ||
| 224 | pgt_prot = pgprot_val(PAGE_KERNEL); | 216 | prot = pgprot_val(SEGMENT_KERNEL); |
| 225 | sgt_prot = pgprot_val(SEGMENT_KERNEL); | 217 | if (!MACHINE_HAS_NX) |
| 226 | if (!MACHINE_HAS_NX) { | 218 | prot &= ~_SEGMENT_ENTRY_NOEXEC; |
| 227 | pgt_prot &= ~_PAGE_NOEXEC; | ||
| 228 | sgt_prot &= ~_SEGMENT_ENTRY_NOEXEC; | ||
| 229 | } | ||
| 230 | for (address = start; address < end;) { | ||
| 231 | pg_dir = pgd_offset_k(address); | ||
| 232 | if (pgd_none(*pg_dir)) { | ||
| 233 | p4_dir = vmem_crst_alloc(_REGION2_ENTRY_EMPTY); | ||
| 234 | if (!p4_dir) | ||
| 235 | goto out; | ||
| 236 | pgd_populate(&init_mm, pg_dir, p4_dir); | ||
| 237 | } | ||
| 238 | 219 | ||
| 239 | p4_dir = p4d_offset(pg_dir, address); | 220 | pmd = pmd_offset(pud, addr); |
| 240 | if (p4d_none(*p4_dir)) { | 221 | for (; addr < end; addr = next, pmd++) { |
| 241 | pu_dir = vmem_crst_alloc(_REGION3_ENTRY_EMPTY); | 222 | next = pmd_addr_end(addr, end); |
| 242 | if (!pu_dir) | 223 | if (!add) { |
| 243 | goto out; | 224 | if (pmd_none(*pmd)) |
| 244 | p4d_populate(&init_mm, p4_dir, pu_dir); | 225 | continue; |
| 245 | } | 226 | if (pmd_large(*pmd) && !add) { |
| 227 | if (IS_ALIGNED(addr, PMD_SIZE) && | ||
| 228 | IS_ALIGNED(next, PMD_SIZE)) { | ||
| 229 | if (!direct) | ||
| 230 | vmem_free_pages(pmd_deref(*pmd), get_order(PMD_SIZE)); | ||
| 231 | pmd_clear(pmd); | ||
| 232 | pages++; | ||
| 233 | } else if (!direct && vmemmap_unuse_sub_pmd(addr, next)) { | ||
| 234 | vmem_free_pages(pmd_deref(*pmd), get_order(PMD_SIZE)); | ||
| 235 | pmd_clear(pmd); | ||
| 236 | } | ||
| 237 | continue; | ||
| 238 | } | ||
| 239 | } else if (pmd_none(*pmd)) { | ||
| 240 | if (IS_ALIGNED(addr, PMD_SIZE) && | ||
| 241 | IS_ALIGNED(next, PMD_SIZE) && | ||
| 242 | MACHINE_HAS_EDAT1 && addr && direct && | ||
| 243 | !debug_pagealloc_enabled()) { | ||
| 244 | pmd_val(*pmd) = addr | prot; | ||
| 245 | pages++; | ||
| 246 | continue; | ||
| 247 | } else if (!direct && MACHINE_HAS_EDAT1) { | ||
| 248 | void *new_page; | ||
| 246 | 249 | ||
| 247 | pu_dir = pud_offset(p4_dir, address); | 250 | /* |
| 248 | if (pud_none(*pu_dir)) { | 251 | * Use 1MB frames for vmemmap if available. We |
| 249 | pm_dir = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY); | 252 | * always use large frames even if they are only |
| 250 | if (!pm_dir) | 253 | * partially used. Otherwise we would have also |
| 254 | * page tables since vmemmap_populate gets | ||
| 255 | * called for each section separately. | ||
| 256 | */ | ||
| 257 | new_page = vmemmap_alloc_block(PMD_SIZE, NUMA_NO_NODE); | ||
| 258 | if (new_page) { | ||
| 259 | pmd_val(*pmd) = __pa(new_page) | prot; | ||
| 260 | if (!IS_ALIGNED(addr, PMD_SIZE) || | ||
| 261 | !IS_ALIGNED(next, PMD_SIZE)) { | ||
| 262 | vmemmap_use_new_sub_pmd(addr, next); | ||
| 263 | } | ||
| 264 | continue; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | pte = vmem_pte_alloc(); | ||
| 268 | if (!pte) | ||
| 251 | goto out; | 269 | goto out; |
| 252 | pud_populate(&init_mm, pu_dir, pm_dir); | 270 | pmd_populate(&init_mm, pmd, pte); |
| 271 | } else if (pmd_large(*pmd)) { | ||
| 272 | if (!direct) | ||
| 273 | vmemmap_use_sub_pmd(addr, next); | ||
| 274 | continue; | ||
| 253 | } | 275 | } |
| 276 | ret = modify_pte_table(pmd, addr, next, add, direct); | ||
| 277 | if (ret) | ||
| 278 | goto out; | ||
| 279 | if (!add) | ||
| 280 | try_free_pte_table(pmd, addr & PMD_MASK); | ||
| 281 | } | ||
| 282 | ret = 0; | ||
| 283 | out: | ||
| 284 | if (direct) | ||
| 285 | update_page_count(PG_DIRECT_MAP_1M, add ? pages : -pages); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 254 | 288 | ||
| 255 | pm_dir = pmd_offset(pu_dir, address); | 289 | static void try_free_pmd_table(pud_t *pud, unsigned long start) |
| 256 | if (pmd_none(*pm_dir)) { | 290 | { |
| 257 | /* Use 1MB frames for vmemmap if available. We always | 291 | const unsigned long end = start + PUD_SIZE; |
| 258 | * use large frames even if they are only partially | 292 | pmd_t *pmd; |
| 259 | * used. | 293 | int i; |
| 260 | * Otherwise we would have also page tables since | 294 | |
| 261 | * vmemmap_populate gets called for each section | 295 | /* Don't mess with any tables not fully in 1:1 mapping & vmemmap area */ |
| 262 | * separately. */ | 296 | if (end > VMALLOC_START) |
| 263 | if (MACHINE_HAS_EDAT1) { | 297 | return; |
| 264 | void *new_page; | 298 | #ifdef CONFIG_KASAN |
| 299 | if (start < KASAN_SHADOW_END && KASAN_SHADOW_START > end) | ||
| 300 | return; | ||
| 301 | #endif | ||
| 302 | pmd = pmd_offset(pud, start); | ||
| 303 | for (i = 0; i < PTRS_PER_PMD; i++, pmd++) | ||
| 304 | if (!pmd_none(*pmd)) | ||
| 305 | return; | ||
| 306 | vmem_free_pages(pud_deref(*pud), CRST_ALLOC_ORDER); | ||
| 307 | pud_clear(pud); | ||
| 308 | } | ||
| 265 | 309 | ||
| 266 | new_page = vmemmap_alloc_block(PMD_SIZE, node); | 310 | static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end, |
| 267 | if (!new_page) | 311 | bool add, bool direct) |
| 268 | goto out; | 312 | { |
| 269 | pmd_val(*pm_dir) = __pa(new_page) | sgt_prot; | 313 | unsigned long next, prot, pages = 0; |
| 270 | address = (address + PMD_SIZE) & PMD_MASK; | 314 | int ret = -ENOMEM; |
| 315 | pud_t *pud; | ||
| 316 | pmd_t *pmd; | ||
| 317 | |||
| 318 | prot = pgprot_val(REGION3_KERNEL); | ||
| 319 | if (!MACHINE_HAS_NX) | ||
| 320 | prot &= ~_REGION_ENTRY_NOEXEC; | ||
| 321 | pud = pud_offset(p4d, addr); | ||
| 322 | for (; addr < end; addr = next, pud++) { | ||
| 323 | next = pud_addr_end(addr, end); | ||
| 324 | if (!add) { | ||
| 325 | if (pud_none(*pud)) | ||
| 326 | continue; | ||
| 327 | if (pud_large(*pud)) { | ||
| 328 | if (IS_ALIGNED(addr, PUD_SIZE) && | ||
| 329 | IS_ALIGNED(next, PUD_SIZE)) { | ||
| 330 | pud_clear(pud); | ||
| 331 | pages++; | ||
| 332 | } | ||
| 333 | continue; | ||
| 334 | } | ||
| 335 | } else if (pud_none(*pud)) { | ||
| 336 | if (IS_ALIGNED(addr, PUD_SIZE) && | ||
| 337 | IS_ALIGNED(next, PUD_SIZE) && | ||
| 338 | MACHINE_HAS_EDAT2 && addr && direct && | ||
| 339 | !debug_pagealloc_enabled()) { | ||
| 340 | pud_val(*pud) = addr | prot; | ||
| 341 | pages++; | ||
| 271 | continue; | 342 | continue; |
| 272 | } | 343 | } |
| 273 | pt_dir = vmem_pte_alloc(); | 344 | pmd = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY); |
| 274 | if (!pt_dir) | 345 | if (!pmd) |
| 275 | goto out; | 346 | goto out; |
| 276 | pmd_populate(&init_mm, pm_dir, pt_dir); | 347 | pud_populate(&init_mm, pud, pmd); |
| 277 | } else if (pmd_large(*pm_dir)) { | 348 | } else if (pud_large(*pud)) { |
| 278 | address = (address + PMD_SIZE) & PMD_MASK; | ||
| 279 | continue; | 349 | continue; |
| 280 | } | 350 | } |
| 351 | ret = modify_pmd_table(pud, addr, next, add, direct); | ||
| 352 | if (ret) | ||
| 353 | goto out; | ||
| 354 | if (!add) | ||
| 355 | try_free_pmd_table(pud, addr & PUD_MASK); | ||
| 356 | } | ||
| 357 | ret = 0; | ||
| 358 | out: | ||
| 359 | if (direct) | ||
| 360 | update_page_count(PG_DIRECT_MAP_2G, add ? pages : -pages); | ||
| 361 | return ret; | ||
| 362 | } | ||
| 281 | 363 | ||
| 282 | pt_dir = pte_offset_kernel(pm_dir, address); | 364 | static void try_free_pud_table(p4d_t *p4d, unsigned long start) |
| 283 | if (pte_none(*pt_dir)) { | 365 | { |
| 284 | void *new_page; | 366 | const unsigned long end = start + P4D_SIZE; |
| 367 | pud_t *pud; | ||
| 368 | int i; | ||
| 369 | |||
| 370 | /* Don't mess with any tables not fully in 1:1 mapping & vmemmap area */ | ||
| 371 | if (end > VMALLOC_START) | ||
| 372 | return; | ||
| 373 | #ifdef CONFIG_KASAN | ||
| 374 | if (start < KASAN_SHADOW_END && KASAN_SHADOW_START > end) | ||
| 375 | return; | ||
| 376 | #endif | ||
| 377 | |||
| 378 | pud = pud_offset(p4d, start); | ||
| 379 | for (i = 0; i < PTRS_PER_PUD; i++, pud++) { | ||
| 380 | if (!pud_none(*pud)) | ||
| 381 | return; | ||
| 382 | } | ||
| 383 | vmem_free_pages(p4d_deref(*p4d), CRST_ALLOC_ORDER); | ||
| 384 | p4d_clear(p4d); | ||
| 385 | } | ||
| 285 | 386 | ||
| 286 | new_page = vmemmap_alloc_block(PAGE_SIZE, node); | 387 | static int modify_p4d_table(pgd_t *pgd, unsigned long addr, unsigned long end, |
| 287 | if (!new_page) | 388 | bool add, bool direct) |
| 389 | { | ||
| 390 | unsigned long next; | ||
| 391 | int ret = -ENOMEM; | ||
| 392 | p4d_t *p4d; | ||
| 393 | pud_t *pud; | ||
| 394 | |||
| 395 | p4d = p4d_offset(pgd, addr); | ||
| 396 | for (; addr < end; addr = next, p4d++) { | ||
| 397 | next = p4d_addr_end(addr, end); | ||
| 398 | if (!add) { | ||
| 399 | if (p4d_none(*p4d)) | ||
| 400 | continue; | ||
| 401 | } else if (p4d_none(*p4d)) { | ||
| 402 | pud = vmem_crst_alloc(_REGION3_ENTRY_EMPTY); | ||
| 403 | if (!pud) | ||
| 288 | goto out; | 404 | goto out; |
| 289 | pte_val(*pt_dir) = __pa(new_page) | pgt_prot; | ||
| 290 | } | 405 | } |
| 291 | address += PAGE_SIZE; | 406 | ret = modify_pud_table(p4d, addr, next, add, direct); |
| 407 | if (ret) | ||
| 408 | goto out; | ||
| 409 | if (!add) | ||
| 410 | try_free_pud_table(p4d, addr & P4D_MASK); | ||
| 292 | } | 411 | } |
| 293 | ret = 0; | 412 | ret = 0; |
| 294 | out: | 413 | out: |
| 295 | return ret; | 414 | return ret; |
| 296 | } | 415 | } |
| 297 | 416 | ||
| 298 | void vmemmap_free(unsigned long start, unsigned long end, | 417 | static void try_free_p4d_table(pgd_t *pgd, unsigned long start) |
| 299 | struct vmem_altmap *altmap) | ||
| 300 | { | 418 | { |
| 419 | const unsigned long end = start + PGDIR_SIZE; | ||
| 420 | p4d_t *p4d; | ||
| 421 | int i; | ||
| 422 | |||
| 423 | /* Don't mess with any tables not fully in 1:1 mapping & vmemmap area */ | ||
| 424 | if (end > VMALLOC_START) | ||
| 425 | return; | ||
| 426 | #ifdef CONFIG_KASAN | ||
| 427 | if (start < KASAN_SHADOW_END && KASAN_SHADOW_START > end) | ||
| 428 | return; | ||
| 429 | #endif | ||
| 430 | |||
| 431 | p4d = p4d_offset(pgd, start); | ||
| 432 | for (i = 0; i < PTRS_PER_P4D; i++, p4d++) { | ||
| 433 | if (!p4d_none(*p4d)) | ||
| 434 | return; | ||
| 435 | } | ||
| 436 | vmem_free_pages(pgd_deref(*pgd), CRST_ALLOC_ORDER); | ||
| 437 | pgd_clear(pgd); | ||
| 301 | } | 438 | } |
| 302 | 439 | ||
| 303 | /* | 440 | static int modify_pagetable(unsigned long start, unsigned long end, bool add, |
| 304 | * Add memory segment to the segment list if it doesn't overlap with | 441 | bool direct) |
| 305 | * an already present segment. | ||
| 306 | */ | ||
| 307 | static int insert_memory_segment(struct memory_segment *seg) | ||
| 308 | { | 442 | { |
| 309 | struct memory_segment *tmp; | 443 | unsigned long addr, next; |
| 444 | int ret = -ENOMEM; | ||
| 445 | pgd_t *pgd; | ||
| 446 | p4d_t *p4d; | ||
| 310 | 447 | ||
| 311 | if (seg->start + seg->size > VMEM_MAX_PHYS || | 448 | if (WARN_ON_ONCE(!PAGE_ALIGNED(start | end))) |
| 312 | seg->start + seg->size < seg->start) | 449 | return -EINVAL; |
| 313 | return -ERANGE; | 450 | for (addr = start; addr < end; addr = next) { |
| 451 | next = pgd_addr_end(addr, end); | ||
| 452 | pgd = pgd_offset_k(addr); | ||
| 314 | 453 | ||
| 315 | list_for_each_entry(tmp, &mem_segs, list) { | 454 | if (!add) { |
| 316 | if (seg->start >= tmp->start + tmp->size) | 455 | if (pgd_none(*pgd)) |
| 317 | continue; | 456 | continue; |
| 318 | if (seg->start + seg->size <= tmp->start) | 457 | } else if (pgd_none(*pgd)) { |
| 319 | continue; | 458 | p4d = vmem_crst_alloc(_REGION2_ENTRY_EMPTY); |
| 320 | return -ENOSPC; | 459 | if (!p4d) |
| 460 | goto out; | ||
| 461 | pgd_populate(&init_mm, pgd, p4d); | ||
| 462 | } | ||
| 463 | ret = modify_p4d_table(pgd, addr, next, add, direct); | ||
| 464 | if (ret) | ||
| 465 | goto out; | ||
| 466 | if (!add) | ||
| 467 | try_free_p4d_table(pgd, addr & PGDIR_MASK); | ||
| 321 | } | 468 | } |
| 322 | list_add(&seg->list, &mem_segs); | 469 | ret = 0; |
| 323 | return 0; | 470 | out: |
| 471 | if (!add) | ||
| 472 | flush_tlb_kernel_range(start, end); | ||
| 473 | return ret; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int add_pagetable(unsigned long start, unsigned long end, bool direct) | ||
| 477 | { | ||
| 478 | return modify_pagetable(start, end, true, direct); | ||
| 479 | } | ||
| 480 | |||
| 481 | static int remove_pagetable(unsigned long start, unsigned long end, bool direct) | ||
| 482 | { | ||
| 483 | return modify_pagetable(start, end, false, direct); | ||
| 324 | } | 484 | } |
| 325 | 485 | ||
| 326 | /* | 486 | /* |
| 327 | * Remove memory segment from the segment list. | 487 | * Add a physical memory range to the 1:1 mapping. |
| 328 | */ | 488 | */ |
| 329 | static void remove_memory_segment(struct memory_segment *seg) | 489 | static int vmem_add_range(unsigned long start, unsigned long size) |
| 330 | { | 490 | { |
| 331 | list_del(&seg->list); | 491 | return add_pagetable(start, start + size, true); |
| 332 | } | 492 | } |
| 333 | 493 | ||
| 334 | static void __remove_shared_memory(struct memory_segment *seg) | 494 | /* |
| 495 | * Remove a physical memory range from the 1:1 mapping. | ||
| 496 | */ | ||
| 497 | static void vmem_remove_range(unsigned long start, unsigned long size) | ||
| 335 | { | 498 | { |
| 336 | remove_memory_segment(seg); | 499 | remove_pagetable(start, start + size, true); |
| 337 | vmem_remove_range(seg->start, seg->size); | ||
| 338 | } | 500 | } |
| 339 | 501 | ||
| 340 | int vmem_remove_mapping(unsigned long start, unsigned long size) | 502 | /* |
| 503 | * Add a backed mem_map array to the virtual mem_map array. | ||
| 504 | */ | ||
| 505 | int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, | ||
| 506 | struct vmem_altmap *altmap) | ||
| 341 | { | 507 | { |
| 342 | struct memory_segment *seg; | ||
| 343 | int ret; | 508 | int ret; |
| 344 | 509 | ||
| 345 | mutex_lock(&vmem_mutex); | 510 | mutex_lock(&vmem_mutex); |
| 511 | /* We don't care about the node, just use NUMA_NO_NODE on allocations */ | ||
| 512 | ret = add_pagetable(start, end, false); | ||
| 513 | if (ret) | ||
| 514 | remove_pagetable(start, end, false); | ||
| 515 | mutex_unlock(&vmem_mutex); | ||
| 516 | return ret; | ||
| 517 | } | ||
| 346 | 518 | ||
| 347 | ret = -ENOENT; | 519 | void vmemmap_free(unsigned long start, unsigned long end, |
| 348 | list_for_each_entry(seg, &mem_segs, list) { | 520 | struct vmem_altmap *altmap) |
| 349 | if (seg->start == start && seg->size == size) | 521 | { |
| 350 | break; | 522 | mutex_lock(&vmem_mutex); |
| 351 | } | 523 | remove_pagetable(start, end, false); |
| 352 | 524 | mutex_unlock(&vmem_mutex); | |
| 353 | if (seg->start != start || seg->size != size) | 525 | } |
| 354 | goto out; | ||
| 355 | 526 | ||
| 356 | ret = 0; | 527 | void vmem_remove_mapping(unsigned long start, unsigned long size) |
| 357 | __remove_shared_memory(seg); | 528 | { |
| 358 | kfree(seg); | 529 | mutex_lock(&vmem_mutex); |
| 359 | out: | 530 | vmem_remove_range(start, size); |
| 360 | mutex_unlock(&vmem_mutex); | 531 | mutex_unlock(&vmem_mutex); |
| 361 | return ret; | ||
| 362 | } | 532 | } |
| 363 | 533 | ||
| 364 | int vmem_add_mapping(unsigned long start, unsigned long size) | 534 | int vmem_add_mapping(unsigned long start, unsigned long size) |
| 365 | { | 535 | { |
| 366 | struct memory_segment *seg; | ||
| 367 | int ret; | 536 | int ret; |
| 368 | 537 | ||
| 369 | mutex_lock(&vmem_mutex); | 538 | if (start + size > VMEM_MAX_PHYS || |
| 370 | ret = -ENOMEM; | 539 | start + size < start) |
| 371 | seg = kzalloc(sizeof(*seg), GFP_KERNEL); | 540 | return -ERANGE; |
| 372 | if (!seg) | ||
| 373 | goto out; | ||
| 374 | seg->start = start; | ||
| 375 | seg->size = size; | ||
| 376 | |||
| 377 | ret = insert_memory_segment(seg); | ||
| 378 | if (ret) | ||
| 379 | goto out_free; | ||
| 380 | 541 | ||
| 381 | ret = vmem_add_mem(start, size); | 542 | mutex_lock(&vmem_mutex); |
| 543 | ret = vmem_add_range(start, size); | ||
| 382 | if (ret) | 544 | if (ret) |
| 383 | goto out_remove; | 545 | vmem_remove_range(start, size); |
| 384 | goto out; | ||
| 385 | |||
| 386 | out_remove: | ||
| 387 | __remove_shared_memory(seg); | ||
| 388 | out_free: | ||
| 389 | kfree(seg); | ||
| 390 | out: | ||
| 391 | mutex_unlock(&vmem_mutex); | 546 | mutex_unlock(&vmem_mutex); |
| 392 | return ret; | 547 | return ret; |
| 393 | } | 548 | } |
| @@ -402,7 +557,7 @@ void __init vmem_map_init(void) · 8 unmodified lines | |||
| 402 | struct memblock_region *reg; | 557 | struct memblock_region *reg; |
| 403 | 558 | ||
| 404 | for_each_memblock(memory, reg) | 559 | for_each_memblock(memory, reg) |
| 405 | vmem_add_mem(reg->base, reg->size); | 560 | vmem_add_range(reg->base, reg->size); |
| 406 | __set_memory((unsigned long)_stext, | 561 | __set_memory((unsigned long)_stext, |
| 407 | (unsigned long)(_etext - _stext) >> PAGE_SHIFT, | 562 | (unsigned long)(_etext - _stext) >> PAGE_SHIFT, |
| 408 | SET_MEMORY_RO | SET_MEMORY_X); | 563 | SET_MEMORY_RO | SET_MEMORY_X); |
| @@ -421,27 +576,3 @@ void __init vmem_map_init(void) · 12 unmodified lines | |||
| 421 | pr_info("Write protected kernel read-only data: %luk\n", | 576 | pr_info("Write protected kernel read-only data: %luk\n", |
| 422 | (unsigned long)(__end_rodata - _stext) >> 10); | 577 | (unsigned long)(__end_rodata - _stext) >> 10); |
| 423 | } | 578 | } |
| 424 | |||
| 425 | /* | ||
| 426 | * Convert memblock.memory to a memory segment list so there is a single | ||
| 427 | * list that contains all memory segments. | ||
| 428 | */ | ||
| 429 | static int __init vmem_convert_memory_chunk(void) | ||
| 430 | { | ||
| 431 | struct memblock_region *reg; | ||
| 432 | struct memory_segment *seg; | ||
| 433 | |||
| 434 | mutex_lock(&vmem_mutex); | ||
| 435 | for_each_memblock(memory, reg) { | ||
| 436 | seg = kzalloc(sizeof(*seg), GFP_KERNEL); | ||
| 437 | if (!seg) | ||
| 438 | panic("Out of memory...\n"); | ||
| 439 | seg->start = reg->base; | ||
| 440 | seg->size = reg->size; | ||
| 441 | insert_memory_segment(seg); | ||
| 442 | } | ||
| 443 | mutex_unlock(&vmem_mutex); | ||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | core_initcall(vmem_convert_memory_chunk); | ||
| @@ -49,6 +49,7 @@ struct bpf_jit { · 48 unmodified lines | |||
| 49 | int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */ | 49 | int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */ |
| 50 | int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */ | 50 | int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */ |
| 51 | int tail_call_start; /* Tail call start offset */ | 51 | int tail_call_start; /* Tail call start offset */ |
| 52 | int excnt; /* Number of exception table entries */ | ||
| 52 | int labels[1]; /* Labels for local jumps */ | 53 | int labels[1]; /* Labels for local jumps */ |
| 53 | }; | 54 | }; |
| 54 | 55 | ||
| @@ -588,6 +589,84 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth) · 533 unmodified lines | |||
| 588 | } | 589 | } |
| 589 | } | 590 | } |
| 590 | 591 | ||
| 592 | static int get_probe_mem_regno(const u8 *insn) | ||
| 593 | { | ||
| 594 | /* | ||
| 595 | * insn must point to llgc, llgh, llgf or lg, which have destination | ||
| 596 | * register at the same position. | ||
| 597 | */ | ||
| 598 | if (insn[0] != 0xe3) /* common llgc, llgh, llgf and lg prefix */ | ||
| 599 | return -1; | ||
| 600 | if (insn[5] != 0x90 && /* llgc */ | ||
| 601 | insn[5] != 0x91 && /* llgh */ | ||
| 602 | insn[5] != 0x16 && /* llgf */ | ||
| 603 | insn[5] != 0x04) /* lg */ | ||
| 604 | return -1; | ||
| 605 | return insn[1] >> 4; | ||
| 606 | } | ||
| 607 | |||
| 608 | static bool ex_handler_bpf(const struct exception_table_entry *x, | ||
| 609 | struct pt_regs *regs) | ||
| 610 | { | ||
| 611 | int regno; | ||
| 612 | u8 *insn; | ||
| 613 | |||
| 614 | regs->psw.addr = extable_fixup(x); | ||
| 615 | insn = (u8 *)__rewind_psw(regs->psw, regs->int_code >> 16); | ||
| 616 | regno = get_probe_mem_regno(insn); | ||
| 617 | if (WARN_ON_ONCE(regno < 0)) | ||
| 618 | /* JIT bug - unexpected instruction. */ | ||
| 619 | return false; | ||
| 620 | regs->gprs[regno] = 0; | ||
| 621 | return true; | ||
| 622 | } | ||
| 623 | |||
| 624 | static int bpf_jit_probe_mem(struct bpf_jit *jit, struct bpf_prog *fp, | ||
| 625 | int probe_prg, int nop_prg) | ||
| 626 | { | ||
| 627 | struct exception_table_entry *ex; | ||
| 628 | s64 delta; | ||
| 629 | u8 *insn; | ||
| 630 | int prg; | ||
| 631 | int i; | ||
| 632 | |||
| 633 | if (!fp->aux->extable) | ||
| 634 | /* Do nothing during early JIT passes. */ | ||
| 635 | return 0; | ||
| 636 | insn = jit->prg_buf + probe_prg; | ||
| 637 | if (WARN_ON_ONCE(get_probe_mem_regno(insn) < 0)) | ||
| 638 | /* JIT bug - unexpected probe instruction. */ | ||
| 639 | return -1; | ||
| 640 | if (WARN_ON_ONCE(probe_prg + insn_length(*insn) != nop_prg)) | ||
| 641 | /* JIT bug - gap between probe and nop instructions. */ | ||
| 642 | return -1; | ||
| 643 | for (i = 0; i < 2; i++) { | ||
| 644 | if (WARN_ON_ONCE(jit->excnt >= fp->aux->num_exentries)) | ||
| 645 | /* Verifier bug - not enough entries. */ | ||
| 646 | return -1; | ||
| 647 | ex = &fp->aux->extable[jit->excnt]; | ||
| 648 | /* Add extable entries for probe and nop instructions. */ | ||
| 649 | prg = i == 0 ? probe_prg : nop_prg; | ||
| 650 | delta = jit->prg_buf + prg - (u8 *)&ex->insn; | ||
| 651 | if (WARN_ON_ONCE(delta < INT_MIN || delta > INT_MAX)) | ||
| 652 | /* JIT bug - code and extable must be close. */ | ||
| 653 | return -1; | ||
| 654 | ex->insn = delta; | ||
| 655 | /* | ||
| 656 | * Always land on the nop. Note that extable infrastructure | ||
| 657 | * ignores fixup field, it is handled by ex_handler_bpf(). | ||
| 658 | */ | ||
| 659 | delta = jit->prg_buf + nop_prg - (u8 *)&ex->fixup; | ||
| 660 | if (WARN_ON_ONCE(delta < INT_MIN || delta > INT_MAX)) | ||
| 661 | /* JIT bug - landing pad and extable must be close. */ | ||
| 662 | return -1; | ||
| 663 | ex->fixup = delta; | ||
| 664 | ex->handler = (u8 *)ex_handler_bpf - (u8 *)&ex->handler; | ||
| 665 | jit->excnt++; | ||
| 666 | } | ||
| 667 | return 0; | ||
| 668 | } | ||
| 669 | |||
| 591 | /* | 670 | /* |
| 592 | * Compile one eBPF instruction into s390x code | 671 | * Compile one eBPF instruction into s390x code |
| 593 | * | 672 | * |
| @@ -604,7 +683,14 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 10 unmodified lines | |||
| 604 | u32 *addrs = jit->addrs; | 683 | u32 *addrs = jit->addrs; |
| 605 | s32 imm = insn->imm; | 684 | s32 imm = insn->imm; |
| 606 | s16 off = insn->off; | 685 | s16 off = insn->off; |
| 686 | int probe_prg = -1; | ||
| 607 | unsigned int mask; | 687 | unsigned int mask; |
| 688 | int nop_prg; | ||
| 689 | int err; | ||
| 690 | |||
| 691 | if (BPF_CLASS(insn->code) == BPF_LDX && | ||
| 692 | BPF_MODE(insn->code) == BPF_PROBE_MEM) | ||
| 693 | probe_prg = jit->prg; | ||
| 608 | 694 | ||
| 609 | switch (insn->code) { | 695 | switch (insn->code) { |
| 610 | /* | 696 | /* |
| @@ -1119,6 +1205,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 508 unmodified lines | |||
| 1119 | * BPF_LDX | 1205 | * BPF_LDX |
| 1120 | */ | 1206 | */ |
| 1121 | case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */ | 1207 | case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */ |
| 1208 | case BPF_LDX | BPF_PROBE_MEM | BPF_B: | ||
| 1122 | /* llgc %dst,0(off,%src) */ | 1209 | /* llgc %dst,0(off,%src) */ |
| 1123 | EMIT6_DISP_LH(0xe3000000, 0x0090, dst_reg, src_reg, REG_0, off); | 1210 | EMIT6_DISP_LH(0xe3000000, 0x0090, dst_reg, src_reg, REG_0, off); |
| 1124 | jit->seen |= SEEN_MEM; | 1211 | jit->seen |= SEEN_MEM; |
| @@ -1126,6 +1213,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 1 unmodified line | |||
| 1126 | insn_count = 2; | 1213 | insn_count = 2; |
| 1127 | break; | 1214 | break; |
| 1128 | case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */ | 1215 | case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */ |
| 1216 | case BPF_LDX | BPF_PROBE_MEM | BPF_H: | ||
| 1129 | /* llgh %dst,0(off,%src) */ | 1217 | /* llgh %dst,0(off,%src) */ |
| 1130 | EMIT6_DISP_LH(0xe3000000, 0x0091, dst_reg, src_reg, REG_0, off); | 1218 | EMIT6_DISP_LH(0xe3000000, 0x0091, dst_reg, src_reg, REG_0, off); |
| 1131 | jit->seen |= SEEN_MEM; | 1219 | jit->seen |= SEEN_MEM; |
| @@ -1133,6 +1221,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 1 unmodified line | |||
| 1133 | insn_count = 2; | 1221 | insn_count = 2; |
| 1134 | break; | 1222 | break; |
| 1135 | case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */ | 1223 | case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */ |
| 1224 | case BPF_LDX | BPF_PROBE_MEM | BPF_W: | ||
| 1136 | /* llgf %dst,off(%src) */ | 1225 | /* llgf %dst,off(%src) */ |
| 1137 | jit->seen |= SEEN_MEM; | 1226 | jit->seen |= SEEN_MEM; |
| 1138 | EMIT6_DISP_LH(0xe3000000, 0x0016, dst_reg, src_reg, REG_0, off); | 1227 | EMIT6_DISP_LH(0xe3000000, 0x0016, dst_reg, src_reg, REG_0, off); |
| @@ -1140,6 +1229,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, · 1 unmodified line | |||
| 1140 | insn_count = 2; | 1229 | insn_count = 2; |
| 1141 | break; | 1230 | break; |
| 1142 | case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */ | 1231 | case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */ |
| 1232 | case BPF_LDX | BPF_PROBE_MEM | BPF_DW: | ||
| 1143 | /* lg %dst,0(off,%src) */ | 1233 | /* lg %dst,0(off,%src) */ |
| 1144 | jit->seen |= SEEN_MEM; | 1234 | jit->seen |= SEEN_MEM; |
| 1145 | EMIT6_DISP_LH(0xe3000000, 0x0004, dst_reg, src_reg, REG_0, off); | 1235 | EMIT6_DISP_LH(0xe3000000, 0x0004, dst_reg, src_reg, REG_0, off); |
| @@ -1485,6 +1575,23 @@ branch_oc: · 339 unmodified lines | |||
| 1485 | pr_err("Unknown opcode %02x\n", insn->code); | 1575 | pr_err("Unknown opcode %02x\n", insn->code); |
| 1486 | return -1; | 1576 | return -1; |
| 1487 | } | 1577 | } |
| 1578 | |||
| 1579 | if (probe_prg != -1) { | ||
| 1580 | /* | ||
| 1581 | * Handlers of certain exceptions leave psw.addr pointing to | ||
| 1582 | * the instruction directly after the failing one. Therefore, | ||
| 1583 | * create two exception table entries and also add a nop in | ||
| 1584 | * case two probing instructions come directly after each | ||
| 1585 | * other. | ||
| 1586 | */ | ||
| 1587 | nop_prg = jit->prg; | ||
| 1588 | /* bcr 0,%0 */ | ||
| 1589 | _EMIT2(0x0700); | ||
| 1590 | err = bpf_jit_probe_mem(jit, fp, probe_prg, nop_prg); | ||
| 1591 | if (err < 0) | ||
| 1592 | return err; | ||
| 1593 | } | ||
| 1594 | |||
| 1488 | return insn_count; | 1595 | return insn_count; |
| 1489 | } | 1596 | } |
| 1490 | 1597 | ||
| @@ -1527,6 +1634,7 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp, · 36 unmodified lines | |||
| 1527 | jit->lit32 = jit->lit32_start; | 1634 | jit->lit32 = jit->lit32_start; |
| 1528 | jit->lit64 = jit->lit64_start; | 1635 | jit->lit64 = jit->lit64_start; |
| 1529 | jit->prg = 0; | 1636 | jit->prg = 0; |
| 1637 | jit->excnt = 0; | ||
| 1530 | 1638 | ||
| 1531 | bpf_jit_prologue(jit, stack_depth); | 1639 | bpf_jit_prologue(jit, stack_depth); |
| 1532 | if (bpf_set_addr(jit, 0) < 0) | 1640 | if (bpf_set_addr(jit, 0) < 0) |
| @@ -1551,6 +1659,12 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp, · 18 unmodified lines | |||
| 1551 | jit->lit64_start = ALIGN(jit->lit64_start, 8); | 1659 | jit->lit64_start = ALIGN(jit->lit64_start, 8); |
| 1552 | jit->size = jit->lit64_start + lit64_size; | 1660 | jit->size = jit->lit64_start + lit64_size; |
| 1553 | jit->size_prg = jit->prg; | 1661 | jit->size_prg = jit->prg; |
| 1662 | |||
| 1663 | if (WARN_ON_ONCE(fp->aux->extable && | ||
| 1664 | jit->excnt != fp->aux->num_exentries)) | ||
| 1665 | /* Verifier bug - too many entries. */ | ||
| 1666 | return -1; | ||
| 1667 | |||
| 1554 | return 0; | 1668 | return 0; |
| 1555 | } | 1669 | } |
| 1556 | 1670 | ||
| @@ -1565,6 +1679,29 @@ struct s390_jit_data { · 8 unmodified lines | |||
| 1565 | int pass; | 1679 | int pass; |
| 1566 | }; | 1680 | }; |
| 1567 | 1681 | ||
| 1682 | static struct bpf_binary_header *bpf_jit_alloc(struct bpf_jit *jit, | ||
| 1683 | struct bpf_prog *fp) | ||
| 1684 | { | ||
| 1685 | struct bpf_binary_header *header; | ||
| 1686 | u32 extable_size; | ||
| 1687 | u32 code_size; | ||
| 1688 | |||
| 1689 | /* We need two entries per insn. */ | ||
| 1690 | fp->aux->num_exentries *= 2; | ||
| 1691 | |||
| 1692 | code_size = roundup(jit->size, | ||
| 1693 | __alignof__(struct exception_table_entry)); | ||
| 1694 | extable_size = fp->aux->num_exentries * | ||
| 1695 | sizeof(struct exception_table_entry); | ||
| 1696 | header = bpf_jit_binary_alloc(code_size + extable_size, &jit->prg_buf, | ||
| 1697 | 8, jit_fill_hole); | ||
| 1698 | if (!header) | ||
| 1699 | return NULL; | ||
| 1700 | fp->aux->extable = (struct exception_table_entry *) | ||
| 1701 | (jit->prg_buf + code_size); | ||
| 1702 | return header; | ||
| 1703 | } | ||
| 1704 | |||
| 1568 | /* | 1705 | /* |
| 1569 | * Compile eBPF program "fp" | 1706 | * Compile eBPF program "fp" |
| 1570 | */ | 1707 | */ |
| @@ -1631,7 +1768,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) · 60 unmodified lines | |||
| 1631 | /* | 1768 | /* |
| 1632 | * Final pass: Allocate and generate program | 1769 | * Final pass: Allocate and generate program |
| 1633 | */ | 1770 | */ |
| 1634 | header = bpf_jit_binary_alloc(jit.size, &jit.prg_buf, 8, jit_fill_hole); | 1771 | header = bpf_jit_alloc(&jit, fp); |
| 1635 | if (!header) { | 1772 | if (!header) { |
| 1636 | fp = orig_fp; | 1773 | fp = orig_fp; |
| 1637 | goto free_addrs; | 1774 | goto free_addrs; |
| @@ -155,10 +155,12 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, · 154 unmodified lines | |||
| 155 | return -EINVAL; | 155 | return -EINVAL; |
| 156 | 156 | ||
| 157 | /* | 157 | /* |
| 158 | * Only support read access to MIO capable devices on a MIO enabled | 158 | * We only support write access to MIO capable devices if we are on |
| 159 | * system. Otherwise we would have to check for every address if it is | 159 | * a MIO enabled system. Otherwise we would have to check for every |
| 160 | * a special ZPCI_ADDR and we would have to do a get_pfn() which we | 160 | * address if it is a special ZPCI_ADDR and would have to do |
| 161 | * don't need for MIO capable devices. | 161 | * a get_pfn() which we don't need for MIO capable devices. Currently |
| 162 | * ISM devices are the only devices without MIO support and there is no | ||
| 163 | * known need for accessing these from userspace. | ||
| 162 | */ | 164 | */ |
| 163 | if (static_branch_likely(&have_mio)) { | 165 | if (static_branch_likely(&have_mio)) { |
| 164 | ret = __memcpy_toio_inuser((void __iomem *) mmio_addr, | 166 | ret = __memcpy_toio_inuser((void __iomem *) mmio_addr, |
| @@ -282,10 +284,12 @@ SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, · 117 unmodified lines | |||
| 282 | return -EINVAL; | 284 | return -EINVAL; |
| 283 | 285 | ||
| 284 | /* | 286 | /* |
| 285 | * Only support write access to MIO capable devices on a MIO enabled | 287 | * We only support read access to MIO capable devices if we are on |
| 286 | * system. Otherwise we would have to check for every address if it is | 288 | * a MIO enabled system. Otherwise we would have to check for every |
| 287 | * a special ZPCI_ADDR and we would have to do a get_pfn() which we | 289 | * address if it is a special ZPCI_ADDR and would have to do |
| 288 | * don't need for MIO capable devices. | 290 | * a get_pfn() which we don't need for MIO capable devices. Currently |
| 291 | * ISM devices are the only devices without MIO support and there is no | ||
| 292 | * known need for accessing these from userspace. | ||
| 289 | */ | 293 | */ |
| 290 | if (static_branch_likely(&have_mio)) { | 294 | if (static_branch_likely(&have_mio)) { |
| 291 | ret = __memcpy_fromio_inuser( | 295 | ret = __memcpy_fromio_inuser( |
| @@ -556,8 +556,9 @@ tty3270_scroll_backward(struct kbd_data *kbd) · 555 unmodified lines | |||
| 556 | * Pass input line to tty. | 556 | * Pass input line to tty. |
| 557 | */ | 557 | */ |
| 558 | static void | 558 | static void |
| 559 | tty3270_read_tasklet(struct raw3270_request *rrq) | 559 | tty3270_read_tasklet(unsigned long data) |
| 560 | { | 560 | { |
| 561 | struct raw3270_request *rrq = (struct raw3270_request *)data; | ||
| 561 | static char kreset_data = TW_KR; | 562 | static char kreset_data = TW_KR; |
| 562 | struct tty3270 *tp = container_of(rrq->view, struct tty3270, view); | 563 | struct tty3270 *tp = container_of(rrq->view, struct tty3270, view); |
| 563 | char *input; | 564 | char *input; |
| @@ -652,8 +653,9 @@ tty3270_issue_read(struct tty3270 *tp, int lock) · 88 unmodified lines | |||
| 652 | * Hang up the tty | 653 | * Hang up the tty |
| 653 | */ | 654 | */ |
| 654 | static void | 655 | static void |
| 655 | tty3270_hangup_tasklet(struct tty3270 *tp) | 656 | tty3270_hangup_tasklet(unsigned long data) |
| 656 | { | 657 | { |
| 658 | struct tty3270 *tp = (struct tty3270 *)data; | ||
| 657 | tty_port_tty_hangup(&tp->port, true); | 659 | tty_port_tty_hangup(&tp->port, true); |
| 658 | raw3270_put_view(&tp->view); | 660 | raw3270_put_view(&tp->view); |
| 659 | } | 661 | } |
| @@ -752,11 +754,9 @@ tty3270_alloc_view(void) · 92 unmodified lines | |||
| 752 | 754 | ||
| 753 | tty_port_init(&tp->port); | 755 | tty_port_init(&tp->port); |
| 754 | timer_setup(&tp->timer, tty3270_update, 0); | 756 | timer_setup(&tp->timer, tty3270_update, 0); |
| 755 | tasklet_init(&tp->readlet, | 757 | tasklet_init(&tp->readlet, tty3270_read_tasklet, |
| 756 | (void (*)(unsigned long)) tty3270_read_tasklet, | ||
| 757 | (unsigned long) tp->read); | 758 | (unsigned long) tp->read); |
| 758 | tasklet_init(&tp->hanglet, | 759 | tasklet_init(&tp->hanglet, tty3270_hangup_tasklet, |
| 759 | (void (*)(unsigned long)) tty3270_hangup_tasklet, | ||
| 760 | (unsigned long) tp); | 760 | (unsigned long) tp); |
| 761 | INIT_WORK(&tp->resize_work, tty3270_resize_work); | 761 | INIT_WORK(&tp->resize_work, tty3270_resize_work); |
| 762 | 762 | ||
| @@ -1,8 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-1.0+ | 1 | // SPDX-License-Identifier: GPL-1.0+ |
| 2 | /* | 2 | /* |
| 3 | * zcore module to export memory content and register sets for creating system | 3 | * zcore module to export memory content and register sets for creating system |
| 4 | * dumps on SCSI disks (zfcpdump). The "zcore/mem" debugfs file shows the same | 4 | * dumps on SCSI disks (zfcpdump). |
| 5 | * dump format as s390 standalone dumps. | ||
| 6 | * | 5 | * |
| 7 | * For more information please refer to Documentation/s390/zfcpdump.rst | 6 | * For more information please refer to Documentation/s390/zfcpdump.rst |
| 8 | * | 7 | * |
| @@ -16,7 +15,6 @@ · 7 unmodified lines | |||
| 16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 18 | #include <linux/debugfs.h> | 17 | #include <linux/debugfs.h> |
| 19 | #include <linux/memblock.h> | ||
| 20 | 18 | ||
| 21 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
| 22 | #include <asm/ipl.h> | 20 | #include <asm/ipl.h> |
| @@ -33,8 +31,6 @@ · 10 unmodified lines | |||
| 33 | 31 | ||
| 34 | #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) | 32 | #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) |
| 35 | 33 | ||
| 36 | #define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */ | ||
| 37 | |||
| 38 | enum arch_id { | 34 | enum arch_id { |
| 39 | ARCH_S390 = 0, | 35 | ARCH_S390 = 0, |
| 40 | ARCH_S390X = 1, | 36 | ARCH_S390X = 1, |
| @@ -48,7 +44,6 @@ struct ipib_info { · 7 unmodified lines | |||
| 48 | static struct debug_info *zcore_dbf; | 44 | static struct debug_info *zcore_dbf; |
| 49 | static int hsa_available; | 45 | static int hsa_available; |
| 50 | static struct dentry *zcore_dir; | 46 | static struct dentry *zcore_dir; |
| 51 | static struct dentry *zcore_memmap_file; | ||
| 52 | static struct dentry *zcore_reipl_file; | 47 | static struct dentry *zcore_reipl_file; |
| 53 | static struct dentry *zcore_hsa_file; | 48 | static struct dentry *zcore_hsa_file; |
| 54 | static struct ipl_parameter_block *zcore_ipl_block; | 49 | static struct ipl_parameter_block *zcore_ipl_block; |
| @@ -139,46 +134,6 @@ static void release_hsa(void) · 84 unmodified lines | |||
| 139 | hsa_available = 0; | 134 | hsa_available = 0; |
| 140 | } | 135 | } |
| 141 | 136 | ||
| 142 | static ssize_t zcore_memmap_read(struct file *filp, char __user *buf, | ||
| 143 | size_t count, loff_t *ppos) | ||
| 144 | { | ||
| 145 | return simple_read_from_buffer(buf, count, ppos, filp->private_data, | ||
| 146 | memblock.memory.cnt * CHUNK_INFO_SIZE); | ||
| 147 | } | ||
| 148 | |||
| 149 | static int zcore_memmap_open(struct inode *inode, struct file *filp) | ||
| 150 | { | ||
| 151 | struct memblock_region *reg; | ||
| 152 | char *buf; | ||
| 153 | int i = 0; | ||
| 154 | |||
| 155 | buf = kcalloc(memblock.memory.cnt, CHUNK_INFO_SIZE, GFP_KERNEL); | ||
| 156 | if (!buf) { | ||
| 157 | return -ENOMEM; | ||
| 158 | } | ||
| 159 | for_each_memblock(memory, reg) { | ||
| 160 | sprintf(buf + (i++ * CHUNK_INFO_SIZE), "%016llx %016llx ", | ||
| 161 | (unsigned long long) reg->base, | ||
| 162 | (unsigned long long) reg->size); | ||
| 163 | } | ||
| 164 | filp->private_data = buf; | ||
| 165 | return nonseekable_open(inode, filp); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int zcore_memmap_release(struct inode *inode, struct file *filp) | ||
| 169 | { | ||
| 170 | kfree(filp->private_data); | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static const struct file_operations zcore_memmap_fops = { | ||
| 175 | .owner = THIS_MODULE, | ||
| 176 | .read = zcore_memmap_read, | ||
| 177 | .open = zcore_memmap_open, | ||
| 178 | .release = zcore_memmap_release, | ||
| 179 | .llseek = no_llseek, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, | 137 | static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, |
| 183 | size_t count, loff_t *ppos) | 138 | size_t count, loff_t *ppos) |
| 184 | { | 139 | { |
| @@ -335,17 +290,11 @@ static int __init zcore_init(void) · 150 unmodified lines | |||
| 335 | rc = -ENOMEM; | 290 | rc = -ENOMEM; |
| 336 | goto fail; | 291 | goto fail; |
| 337 | } | 292 | } |
| 338 | zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir, | ||
| 339 | NULL, &zcore_memmap_fops); | ||
| 340 | if (!zcore_memmap_file) { | ||
| 341 | rc = -ENOMEM; | ||
| 342 | goto fail_dir; | ||
| 343 | } | ||
| 344 | zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, | 293 | zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, |
| 345 | NULL, &zcore_reipl_fops); | 294 | NULL, &zcore_reipl_fops); |
| 346 | if (!zcore_reipl_file) { | 295 | if (!zcore_reipl_file) { |
| 347 | rc = -ENOMEM; | 296 | rc = -ENOMEM; |
| 348 | goto fail_memmap_file; | 297 | goto fail_dir; |
| 349 | } | 298 | } |
| 350 | zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir, | 299 | zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir, |
| 351 | NULL, &zcore_hsa_fops); | 300 | NULL, &zcore_hsa_fops); |
| @@ -357,8 +306,6 @@ static int __init zcore_init(void) · 5 unmodified lines | |||
| 357 | 306 | ||
| 358 | fail_reipl_file: | 307 | fail_reipl_file: |
| 359 | debugfs_remove(zcore_reipl_file); | 308 | debugfs_remove(zcore_reipl_file); |
| 360 | fail_memmap_file: | ||
| 361 | debugfs_remove(zcore_memmap_file); | ||
| 362 | fail_dir: | 309 | fail_dir: |
| 363 | debugfs_remove(zcore_dir); | 310 | debugfs_remove(zcore_dir); |
| 364 | fail: | 311 | fail: |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | |||
| 15 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ | 15 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
| 16 | #define QDIO_BUSY_BIT_RETRY_DELAY 10 /* 10 milliseconds */ | 16 | #define QDIO_BUSY_BIT_RETRY_DELAY 10 /* 10 milliseconds */ |
| 17 | #define QDIO_BUSY_BIT_RETRIES 1000 /* = 10s retry time */ | 17 | #define QDIO_BUSY_BIT_RETRIES 1000 /* = 10s retry time */ |
| 18 | #define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ | ||
| 19 | 18 | ||
| 20 | enum qdio_irq_states { | 19 | enum qdio_irq_states { |
| 21 | QDIO_IRQ_STATE_INACTIVE, | 20 | QDIO_IRQ_STATE_INACTIVE, |
| @@ -166,11 +165,7 @@ struct qdio_dev_perf_stat { · 144 unmodified lines | |||
| 166 | } ____cacheline_aligned; | 165 | } ____cacheline_aligned; |
| 167 | 166 | ||
| 168 | struct qdio_queue_perf_stat { | 167 | struct qdio_queue_perf_stat { |
| 169 | /* | 168 | /* Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. */ |
| 170 | * Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. | ||
| 171 | * Since max. 127 SBALs are scanned reuse entry for 128 as queue full | ||
| 172 | * aka 127 SBALs found. | ||
| 173 | */ | ||
| 174 | unsigned int nr_sbals[8]; | 169 | unsigned int nr_sbals[8]; |
| 175 | unsigned int nr_sbal_error; | 170 | unsigned int nr_sbal_error; |
| 176 | unsigned int nr_sbal_nop; | 171 | unsigned int nr_sbal_nop; |
| @@ -185,8 +180,6 @@ struct qdio_input_q { · 8 unmodified lines | |||
| 185 | /* Batch of SBALs that we processed while polling the queue: */ | 180 | /* Batch of SBALs that we processed while polling the queue: */ |
| 186 | unsigned int batch_start; | 181 | unsigned int batch_start; |
| 187 | unsigned int batch_count; | 182 | unsigned int batch_count; |
| 188 | /* last time of noticing incoming data */ | ||
| 189 | u64 timestamp; | ||
| 190 | }; | 183 | }; |
| 191 | 184 | ||
| 192 | struct qdio_output_q { | 185 | struct qdio_output_q { |
| @@ -165,7 +165,7 @@ static int qstat_show(struct seq_file *m, void *v) · 164 unmodified lines | |||
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | seq_printf(m, "\n1 2.. 4.. 8.. " | 167 | seq_printf(m, "\n1 2.. 4.. 8.. " |
| 168 | "16.. 32.. 64.. 127\n"); | 168 | "16.. 32.. 64.. 128\n"); |
| 169 | for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++) | 169 | for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++) |
| 170 | seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]); | 170 | seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]); |
| 171 | seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n", | 171 | seq_printf(m, "\nError NOP Total\n%-10u %-10u %-10u\n\n", |
| @@ -413,15 +413,8 @@ static inline void qdio_stop_polling(struct qdio_q *q) · 412 unmodified lines | |||
| 413 | 413 | ||
| 414 | static inline void account_sbals(struct qdio_q *q, unsigned int count) | 414 | static inline void account_sbals(struct qdio_q *q, unsigned int count) |
| 415 | { | 415 | { |
| 416 | int pos; | ||
| 417 | |||
| 418 | q->q_stats.nr_sbal_total += count; | 416 | q->q_stats.nr_sbal_total += count; |
| 419 | if (count == QDIO_MAX_BUFFERS_MASK) { | 417 | q->q_stats.nr_sbals[ilog2(count)]++; |
| 420 | q->q_stats.nr_sbals[7]++; | ||
| 421 | return; | ||
| 422 | } | ||
| 423 | pos = ilog2(count); | ||
| 424 | q->q_stats.nr_sbals[pos]++; | ||
| 425 | } | 418 | } |
| 426 | 419 | ||
| 427 | static void process_buffer_error(struct qdio_q *q, unsigned int start, | 420 | static void process_buffer_error(struct qdio_q *q, unsigned int start, |
| @@ -464,11 +457,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start) · 36 unmodified lines | |||
| 464 | 457 | ||
| 465 | q->timestamp = get_tod_clock_fast(); | 458 | q->timestamp = get_tod_clock_fast(); |
| 466 | 459 | ||
| 467 | /* | 460 | count = atomic_read(&q->nr_buf_used); |
| 468 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | ||
| 469 | * would return 0. | ||
| 470 | */ | ||
| 471 | count = min(atomic_read(&q->nr_buf_used), QDIO_MAX_BUFFERS_MASK); | ||
| 472 | if (!count) | 461 | if (!count) |
| 473 | return 0; | 462 | return 0; |
| 474 | 463 | ||
| @@ -521,14 +510,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start) · 46 unmodified lines | |||
| 521 | 510 | ||
| 522 | static int qdio_inbound_q_moved(struct qdio_q *q, unsigned int start) | 511 | static int qdio_inbound_q_moved(struct qdio_q *q, unsigned int start) |
| 523 | { | 512 | { |
| 524 | int count; | 513 | return get_inbound_buffer_frontier(q, start); |
| 525 | |||
| 526 | count = get_inbound_buffer_frontier(q, start); | ||
| 527 | |||
| 528 | if (count && !is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) | ||
| 529 | q->u.in.timestamp = get_tod_clock(); | ||
| 530 | |||
| 531 | return count; | ||
| 532 | } | 514 | } |
| 533 | 515 | ||
| 534 | static inline int qdio_inbound_q_done(struct qdio_q *q, unsigned int start) | 516 | static inline int qdio_inbound_q_done(struct qdio_q *q, unsigned int start) |
| @@ -546,22 +528,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q, unsigned int start) · 11 unmodified lines | |||
| 546 | /* more work coming */ | 528 | /* more work coming */ |
| 547 | return 0; | 529 | return 0; |
| 548 | 530 | ||
| 549 | if (is_thinint_irq(q->irq_ptr)) | 531 | return 1; |
| 550 | return 1; | ||
| 551 | |||
| 552 | /* don't poll under z/VM */ | ||
| 553 | if (MACHINE_IS_VM) | ||
| 554 | return 1; | ||
| 555 | |||
| 556 | /* | ||
| 557 | * At this point we know, that inbound first_to_check | ||
| 558 | * has (probably) not moved (see qdio_inbound_processing). | ||
| 559 | */ | ||
| 560 | if (get_tod_clock_fast() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | ||
| 561 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", start); | ||
| 562 | return 1; | ||
| 563 | } else | ||
| 564 | return 0; | ||
| 565 | } | 532 | } |
| 566 | 533 | ||
| 567 | static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count) | 534 | static inline void qdio_handle_aobs(struct qdio_q *q, int start, int count) |
| @@ -73,8 +73,7 @@ EXPORT_SYMBOL(ap_perms); · 72 unmodified lines | |||
| 73 | DEFINE_MUTEX(ap_perms_mutex); | 73 | DEFINE_MUTEX(ap_perms_mutex); |
| 74 | EXPORT_SYMBOL(ap_perms_mutex); | 74 | EXPORT_SYMBOL(ap_perms_mutex); |
| 75 | 75 | ||
| 76 | static struct ap_config_info *ap_configuration; | 76 | static struct ap_config_info *ap_qci_info; |
| 77 | static bool initialised; | ||
| 78 | 77 | ||
| 79 | /* | 78 | /* |
| 80 | * AP bus related debug feature things. | 79 | * AP bus related debug feature things. |
| @@ -105,8 +104,10 @@ static struct hrtimer ap_poll_timer; · 24 unmodified lines | |||
| 105 | */ | 104 | */ |
| 106 | static unsigned long long poll_timeout = 250000; | 105 | static unsigned long long poll_timeout = 250000; |
| 107 | 106 | ||
| 108 | /* Maximum domain id */ | 107 | /* Maximum domain id, if not given via qci */ |
| 109 | static int ap_max_domain_id; | 108 | static int ap_max_domain_id = 15; |
| 109 | /* Maximum adapter id, if not given via qci */ | ||
| 110 | static int ap_max_adapter_id = 63; | ||
| 110 | 111 | ||
| 111 | static struct bus_type ap_bus_type; | 112 | static struct bus_type ap_bus_type; |
| 112 | 113 | ||
| @@ -154,12 +155,12 @@ static int ap_interrupts_available(void) · 41 unmodified lines | |||
| 154 | } | 155 | } |
| 155 | 156 | ||
| 156 | /** | 157 | /** |
| 157 | * ap_configuration_available(): Test if AP configuration | 158 | * ap_qci_available(): Test if AP configuration |
| 158 | * information is available. | 159 | * information can be queried via QCI subfunction. |
| 159 | * | 160 | * |
| 160 | * Returns 1 if AP configuration information is available. | 161 | * Returns 1 if subfunction PQAP(QCI) is available. |
| 161 | */ | 162 | */ |
| 162 | static int ap_configuration_available(void) | 163 | static int ap_qci_available(void) |
| 163 | { | 164 | { |
| 164 | return test_facility(12); | 165 | return test_facility(12); |
| 165 | } | 166 | } |
| @@ -182,22 +183,22 @@ static int ap_apft_available(void) · 16 unmodified lines | |||
| 182 | */ | 183 | */ |
| 183 | static inline int ap_qact_available(void) | 184 | static inline int ap_qact_available(void) |
| 184 | { | 185 | { |
| 185 | if (ap_configuration) | 186 | if (ap_qci_info) |
| 186 | return ap_configuration->qact; | 187 | return ap_qci_info->qact; |
| 187 | return 0; | 188 | return 0; |
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | /* | 191 | /* |
| 191 | * ap_query_configuration(): Fetch cryptographic config info | 192 | * ap_fetch_qci_info(): Fetch cryptographic config info |
| 192 | * | 193 | * |
| 193 | * Returns the ap configuration info fetched via PQAP(QCI). | 194 | * Returns the ap configuration info fetched via PQAP(QCI). |
| 194 | * On success 0 is returned, on failure a negative errno | 195 | * On success 0 is returned, on failure a negative errno |
| 195 | * is returned, e.g. if the PQAP(QCI) instruction is not | 196 | * is returned, e.g. if the PQAP(QCI) instruction is not |
| 196 | * available, the return value will be -EOPNOTSUPP. | 197 | * available, the return value will be -EOPNOTSUPP. |
| 197 | */ | 198 | */ |
| 198 | static inline int ap_query_configuration(struct ap_config_info *info) | 199 | static inline int ap_fetch_qci_info(struct ap_config_info *info) |
| 199 | { | 200 | { |
| 200 | if (!ap_configuration_available()) | 201 | if (!ap_qci_available()) |
| 201 | return -EOPNOTSUPP; | 202 | return -EOPNOTSUPP; |
| 202 | if (!info) | 203 | if (!info) |
| 203 | return -EINVAL; | 204 | return -EINVAL; |
| @@ -205,21 +206,40 @@ static inline int ap_query_configuration(struct ap_config_info *info) · 1 unmodified line | |||
| 205 | } | 206 | } |
| 206 | 207 | ||
| 207 | /** | 208 | /** |
| 208 | * ap_init_configuration(): Allocate and query configuration array. | 209 | * ap_init_qci_info(): Allocate and query qci config info. |
| 210 | * Does also update the static variables ap_max_domain_id | ||
| 211 | * and ap_max_adapter_id if this info is available. | ||
| 212 | |||
| 209 | */ | 213 | */ |
| 210 | static void ap_init_configuration(void) | 214 | static void __init ap_init_qci_info(void) |
| 211 | { | 215 | { |
| 212 | if (!ap_configuration_available()) | 216 | if (!ap_qci_available()) { |
| 217 | AP_DBF(DBF_INFO, "%s QCI not supported\n", __func__); | ||
| 213 | return; | 218 | return; |
| 219 | } | ||
| 214 | 220 | ||
| 215 | ap_configuration = kzalloc(sizeof(*ap_configuration), GFP_KERNEL); | 221 | ap_qci_info = kzalloc(sizeof(*ap_qci_info), GFP_KERNEL); |
| 216 | if (!ap_configuration) | 222 | if (!ap_qci_info) |
| 217 | return; | 223 | return; |
| 218 | if (ap_query_configuration(ap_configuration) != 0) { | 224 | if (ap_fetch_qci_info(ap_qci_info) != 0) { |
| 219 | kfree(ap_configuration); | 225 | kfree(ap_qci_info); |
| 220 | ap_configuration = NULL; | 226 | ap_qci_info = NULL; |
| 221 | return; | 227 | return; |
| 222 | } | 228 | } |
| 229 | AP_DBF(DBF_INFO, "%s successful fetched initial qci info\n", __func__); | ||
| 230 | |||
| 231 | if (ap_qci_info->apxa) { | ||
| 232 | if (ap_qci_info->Na) { | ||
| 233 | ap_max_adapter_id = ap_qci_info->Na; | ||
| 234 | AP_DBF(DBF_INFO, "%s new ap_max_adapter_id is %d\n", | ||
| 235 | __func__, ap_max_adapter_id); | ||
| 236 | } | ||
| 237 | if (ap_qci_info->Nd) { | ||
| 238 | ap_max_domain_id = ap_qci_info->Nd; | ||
| 239 | AP_DBF(DBF_INFO, "%s new ap_max_domain_id is %d\n", | ||
| 240 | __func__, ap_max_domain_id); | ||
| 241 | } | ||
| 242 | } | ||
| 223 | } | 243 | } |
| 224 | 244 | ||
| 225 | /* | 245 | /* |
| @@ -233,7 +253,6 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr) · 7 unmodified lines | |||
| 233 | 253 | ||
| 234 | /* | 254 | /* |
| 235 | * ap_test_config_card_id(): Test, whether an AP card ID is configured. | 255 | * ap_test_config_card_id(): Test, whether an AP card ID is configured. |
| 236 | * @id AP card ID | ||
| 237 | * | 256 | * |
| 238 | * Returns 0 if the card is not configured | 257 | * Returns 0 if the card is not configured |
| 239 | * 1 if the card is configured or | 258 | * 1 if the card is configured or |
| @@ -241,16 +260,16 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr) · 1 unmodified line | |||
| 241 | */ | 260 | */ |
| 242 | static inline int ap_test_config_card_id(unsigned int id) | 261 | static inline int ap_test_config_card_id(unsigned int id) |
| 243 | { | 262 | { |
| 244 | if (!ap_configuration) /* QCI not supported */ | 263 | if (id > ap_max_adapter_id) |
| 245 | /* only ids 0...3F may be probed */ | 264 | return 0; |
| 246 | return id < 0x40 ? 1 : 0; | 265 | if (ap_qci_info) |
| 247 | return ap_test_config(ap_configuration->apm, id); | 266 | return ap_test_config(ap_qci_info->apm, id); |
| 267 | return 1; | ||
| 248 | } | 268 | } |
| 249 | 269 | ||
| 250 | /* | 270 | /* |
| 251 | * ap_test_config_usage_domain(): Test, whether an AP usage domain | 271 | * ap_test_config_usage_domain(): Test, whether an AP usage domain |
| 252 | * is configured. | 272 | * is configured. |
| 253 | * @domain AP usage domain ID | ||
| 254 | * | 273 | * |
| 255 | * Returns 0 if the usage domain is not configured | 274 | * Returns 0 if the usage domain is not configured |
| 256 | * 1 if the usage domain is configured or | 275 | * 1 if the usage domain is configured or |
| @@ -258,9 +277,11 @@ static inline int ap_test_config_card_id(unsigned int id) · 1 unmodified line | |||
| 258 | */ | 277 | */ |
| 259 | int ap_test_config_usage_domain(unsigned int domain) | 278 | int ap_test_config_usage_domain(unsigned int domain) |
| 260 | { | 279 | { |
| 261 | if (!ap_configuration) /* QCI not supported */ | 280 | if (domain > ap_max_domain_id) |
| 262 | return domain < 16; | 281 | return 0; |
| 263 | return ap_test_config(ap_configuration->aqm, domain); | 282 | if (ap_qci_info) |
| 283 | return ap_test_config(ap_qci_info->aqm, domain); | ||
| 284 | return 1; | ||
| 264 | } | 285 | } |
| 265 | EXPORT_SYMBOL(ap_test_config_usage_domain); | 286 | EXPORT_SYMBOL(ap_test_config_usage_domain); |
| 266 | 287 | ||
| @@ -274,43 +295,44 @@ EXPORT_SYMBOL(ap_test_config_usage_domain); · 7 unmodified lines | |||
| 274 | */ | 295 | */ |
| 275 | int ap_test_config_ctrl_domain(unsigned int domain) | 296 | int ap_test_config_ctrl_domain(unsigned int domain) |
| 276 | { | 297 | { |
| 277 | if (!ap_configuration) /* QCI not supported */ | 298 | if (!ap_qci_info || domain > ap_max_domain_id) |
| 278 | return 0; | 299 | return 0; |
| 279 | return ap_test_config(ap_configuration->adm, domain); | 300 | return ap_test_config(ap_qci_info->adm, domain); |
| 280 | } | 301 | } |
| 281 | EXPORT_SYMBOL(ap_test_config_ctrl_domain); | 302 | EXPORT_SYMBOL(ap_test_config_ctrl_domain); |
| 282 | 303 | ||
| 283 | /** | 304 | /* |
| 284 | * ap_query_queue(): Check if an AP queue is available. | 305 | * ap_queue_info(): Check and get AP queue info. |
| 285 | * @qid: The AP queue number | 306 | * Returns true if TAPQ succeeded and the info is filled or |
| 286 | * @queue_depth: Pointer to queue depth value | 307 | * false otherwise. |
| 287 | * @device_type: Pointer to device type value | ||
| 288 | * @facilities: Pointer to facility indicator | ||
| 289 | */ | 308 | */ |
| 290 | static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, | 309 | static bool ap_queue_info(ap_qid_t qid, int *q_type, |
| 291 | unsigned int *facilities) | 310 | unsigned int *q_fac, int *q_depth) |
| 292 | { | 311 | { |
| 293 | struct ap_queue_status status; | 312 | struct ap_queue_status status; |
| 294 | unsigned long info; | 313 | unsigned long info = 0; |
| 295 | int nd; | ||
| 296 | 314 | ||
| 297 | if (!ap_test_config_card_id(AP_QID_CARD(qid))) | 315 | /* make sure we don't run into a specifiation exception */ |
| 298 | return -ENODEV; | 316 | if (AP_QID_CARD(qid) > ap_max_adapter_id || |
| 317 | AP_QID_QUEUE(qid) > ap_max_domain_id) | ||
| 318 | return false; | ||
| 299 | 319 | ||
| 320 | /* call TAPQ on this APQN */ | ||
| 300 | status = ap_test_queue(qid, ap_apft_available(), &info); | 321 | status = ap_test_queue(qid, ap_apft_available(), &info); |
| 301 | switch (status.response_code) { | 322 | switch (status.response_code) { |
| 302 | case AP_RESPONSE_NORMAL: | 323 | case AP_RESPONSE_NORMAL: |
| 303 | *queue_depth = (int)(info & 0xff); | 324 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 304 | *device_type = (int)((info >> 24) & 0xff); | 325 | /* |
| 305 | *facilities = (unsigned int)(info >> 32); | 326 | * According to the architecture in all these cases the |
| 306 | /* Update maximum domain id */ | 327 | * info should be filled. All bits 0 is not possible as |
| 307 | nd = (info >> 16) & 0xff; | 328 | * there is at least one of the mode bits set. |
| 308 | /* if N bit is available, z13 and newer */ | 329 | */ |
| 309 | if ((info & (1UL << 57)) && nd > 0) | 330 | if (WARN_ON_ONCE(!info)) |
| 310 | ap_max_domain_id = nd; | 331 | return false; |
| 311 | else /* older machine types */ | 332 | *q_type = (int)((info >> 24) & 0xff); |
| 312 | ap_max_domain_id = 15; | 333 | *q_fac = (unsigned int)(info >> 32); |
| 313 | switch (*device_type) { | 334 | *q_depth = (int)(info & 0xff); |
| 335 | switch (*q_type) { | ||
| 314 | /* For CEX2 and CEX3 the available functions | 336 | /* For CEX2 and CEX3 the available functions |
| 315 | * are not reflected by the facilities bits. | 337 | * are not reflected by the facilities bits. |
| 316 | * Instead it is coded into the type. So here | 338 | * Instead it is coded into the type. So here |
| @@ -318,37 +340,31 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, · 1 unmodified line | |||
| 318 | */ | 340 | */ |
| 319 | case AP_DEVICE_TYPE_CEX2A: | 341 | case AP_DEVICE_TYPE_CEX2A: |
| 320 | case AP_DEVICE_TYPE_CEX3A: | 342 | case AP_DEVICE_TYPE_CEX3A: |
| 321 | *facilities |= 0x08000000; | 343 | *q_fac |= 0x08000000; |
| 322 | break; | 344 | break; |
| 323 | case AP_DEVICE_TYPE_CEX2C: | 345 | case AP_DEVICE_TYPE_CEX2C: |
| 324 | case AP_DEVICE_TYPE_CEX3C: | 346 | case AP_DEVICE_TYPE_CEX3C: |
| 325 | *facilities |= 0x10000000; | 347 | *q_fac |= 0x10000000; |
| 326 | break; | 348 | break; |
| 327 | default: | 349 | default: |
| 328 | break; | 350 | break; |
| 329 | } | 351 | } |
| 330 | return 0; | 352 | return true; |
| 331 | case AP_RESPONSE_Q_NOT_AVAIL: | ||
| 332 | case AP_RESPONSE_DECONFIGURED: | ||
| 333 | case AP_RESPONSE_CHECKSTOPPED: | ||
| 334 | case AP_RESPONSE_INVALID_ADDRESS: | ||
| 335 | return -ENODEV; | ||
| 336 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
| 337 | case AP_RESPONSE_OTHERWISE_CHANGED: | ||
| 338 | case AP_RESPONSE_BUSY: | ||
| 339 | return -EBUSY; | ||
| 340 | default: | 353 | default: |
| 341 | BUG(); | 354 | /* |
| 355 | * A response code which indicates, there is no info available. | ||
| 356 | */ | ||
| 357 | return false; | ||
| 342 | } | 358 | } |
| 343 | } | 359 | } |
| 344 | 360 | ||
| 345 | void ap_wait(enum ap_wait wait) | 361 | void ap_wait(enum ap_sm_wait wait) |
| 346 | { | 362 | { |
| 347 | ktime_t hr_time; | 363 | ktime_t hr_time; |
| 348 | 364 | ||
| 349 | switch (wait) { | 365 | switch (wait) { |
| 350 | case AP_WAIT_AGAIN: | 366 | case AP_SM_WAIT_AGAIN: |
| 351 | case AP_WAIT_INTERRUPT: | 367 | case AP_SM_WAIT_INTERRUPT: |
| 352 | if (ap_using_interrupts()) | 368 | if (ap_using_interrupts()) |
| 353 | break; | 369 | break; |
| 354 | if (ap_poll_kthread) { | 370 | if (ap_poll_kthread) { |
| @@ -356,7 +372,7 @@ void ap_wait(enum ap_wait wait) · 1 unmodified line | |||
| 356 | break; | 372 | break; |
| 357 | } | 373 | } |
| 358 | fallthrough; | 374 | fallthrough; |
| 359 | case AP_WAIT_TIMEOUT: | 375 | case AP_SM_WAIT_TIMEOUT: |
| 360 | spin_lock_bh(&ap_poll_timer_lock); | 376 | spin_lock_bh(&ap_poll_timer_lock); |
| 361 | if (!hrtimer_is_queued(&ap_poll_timer)) { | 377 | if (!hrtimer_is_queued(&ap_poll_timer)) { |
| 362 | hr_time = poll_timeout; | 378 | hr_time = poll_timeout; |
| @@ -365,7 +381,7 @@ void ap_wait(enum ap_wait wait) · 2 unmodified lines | |||
| 365 | } | 381 | } |
| 366 | spin_unlock_bh(&ap_poll_timer_lock); | 382 | spin_unlock_bh(&ap_poll_timer_lock); |
| 367 | break; | 383 | break; |
| 368 | case AP_WAIT_NONE: | 384 | case AP_SM_WAIT_NONE: |
| 369 | default: | 385 | default: |
| 370 | break; | 386 | break; |
| 371 | } | 387 | } |
| @@ -382,7 +398,7 @@ void ap_request_timeout(struct timer_list *t) · 10 unmodified lines | |||
| 382 | struct ap_queue *aq = from_timer(aq, t, timeout); | 398 | struct ap_queue *aq = from_timer(aq, t, timeout); |
| 383 | 399 | ||
| 384 | spin_lock_bh(&aq->lock); | 400 | spin_lock_bh(&aq->lock); |
| 385 | ap_wait(ap_sm_event(aq, AP_EVENT_TIMEOUT)); | 401 | ap_wait(ap_sm_event(aq, AP_SM_EVENT_TIMEOUT)); |
| 386 | spin_unlock_bh(&aq->lock); | 402 | spin_unlock_bh(&aq->lock); |
| 387 | } | 403 | } |
| 388 | 404 | ||
| @@ -418,7 +434,7 @@ static void ap_tasklet_fn(unsigned long dummy) · 29 unmodified lines | |||
| 418 | { | 434 | { |
| 419 | int bkt; | 435 | int bkt; |
| 420 | struct ap_queue *aq; | 436 | struct ap_queue *aq; |
| 421 | enum ap_wait wait = AP_WAIT_NONE; | 437 | enum ap_sm_wait wait = AP_SM_WAIT_NONE; |
| 422 | 438 | ||
| 423 | /* Reset the indicator if interrupts are used. Thus new interrupts can | 439 | /* Reset the indicator if interrupts are used. Thus new interrupts can |
| 424 | * be received. Doing it in the beginning of the tasklet is therefor | 440 | * be received. Doing it in the beginning of the tasklet is therefor |
| @@ -430,7 +446,7 @@ static void ap_tasklet_fn(unsigned long dummy) · 5 unmodified lines | |||
| 430 | spin_lock_bh(&ap_queues_lock); | 446 | spin_lock_bh(&ap_queues_lock); |
| 431 | hash_for_each(ap_queues, bkt, aq, hnode) { | 447 | hash_for_each(ap_queues, bkt, aq, hnode) { |
| 432 | spin_lock_bh(&aq->lock); | 448 | spin_lock_bh(&aq->lock); |
| 433 | wait = min(wait, ap_sm_event_loop(aq, AP_EVENT_POLL)); | 449 | wait = min(wait, ap_sm_event_loop(aq, AP_SM_EVENT_POLL)); |
| 434 | spin_unlock_bh(&aq->lock); | 450 | spin_unlock_bh(&aq->lock); |
| 435 | } | 451 | } |
| 436 | spin_unlock_bh(&ap_queues_lock); | 452 | spin_unlock_bh(&ap_queues_lock); |
| @@ -751,9 +767,6 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, · 314 unmodified lines | |||
| 751 | { | 767 | { |
| 752 | struct device_driver *drv = &ap_drv->driver; | 768 | struct device_driver *drv = &ap_drv->driver; |
| 753 | 769 | ||
| 754 | if (!initialised) | ||
| 755 | return -ENODEV; | ||
| 756 | |||
| 757 | drv->bus = &ap_bus_type; | 770 | drv->bus = &ap_bus_type; |
| 758 | drv->probe = ap_device_probe; | 771 | drv->probe = ap_device_probe; |
| 759 | drv->remove = ap_device_remove; | 772 | drv->remove = ap_device_remove; |
| @@ -929,11 +942,12 @@ static ssize_t ap_domain_store(struct bus_type *bus, · 169 unmodified lines | |||
| 929 | domain < 0 || domain > ap_max_domain_id || | 942 | domain < 0 || domain > ap_max_domain_id || |
| 930 | !test_bit_inv(domain, ap_perms.aqm)) | 943 | !test_bit_inv(domain, ap_perms.aqm)) |
| 931 | return -EINVAL; | 944 | return -EINVAL; |
| 945 | |||
| 932 | spin_lock_bh(&ap_domain_lock); | 946 | spin_lock_bh(&ap_domain_lock); |
| 933 | ap_domain_index = domain; | 947 | ap_domain_index = domain; |
| 934 | spin_unlock_bh(&ap_domain_lock); | 948 | spin_unlock_bh(&ap_domain_lock); |
| 935 | 949 | ||
| 936 | AP_DBF(DBF_DEBUG, "stored new default domain=%d\n", domain); | 950 | AP_DBF(DBF_INFO, "stored new default domain=%d\n", domain); |
| 937 | 951 | ||
| 938 | return count; | 952 | return count; |
| 939 | } | 953 | } |
| @@ -942,45 +956,45 @@ static BUS_ATTR_RW(ap_domain); · 2 unmodified lines | |||
| 942 | 956 | ||
| 943 | static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf) | 957 | static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf) |
| 944 | { | 958 | { |
| 945 | if (!ap_configuration) /* QCI not supported */ | 959 | if (!ap_qci_info) /* QCI not supported */ |
| 946 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); | 960 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
| 947 | 961 | ||
| 948 | return scnprintf(buf, PAGE_SIZE, | 962 | return scnprintf(buf, PAGE_SIZE, |
| 949 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", | 963 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
| 950 | ap_configuration->adm[0], ap_configuration->adm[1], | 964 | ap_qci_info->adm[0], ap_qci_info->adm[1], |
| 951 | ap_configuration->adm[2], ap_configuration->adm[3], | 965 | ap_qci_info->adm[2], ap_qci_info->adm[3], |
| 952 | ap_configuration->adm[4], ap_configuration->adm[5], | 966 | ap_qci_info->adm[4], ap_qci_info->adm[5], |
| 953 | ap_configuration->adm[6], ap_configuration->adm[7]); | 967 | ap_qci_info->adm[6], ap_qci_info->adm[7]); |
| 954 | } | 968 | } |
| 955 | 969 | ||
| 956 | static BUS_ATTR_RO(ap_control_domain_mask); | 970 | static BUS_ATTR_RO(ap_control_domain_mask); |
| 957 | 971 | ||
| 958 | static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf) | 972 | static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf) |
| 959 | { | 973 | { |
| 960 | if (!ap_configuration) /* QCI not supported */ | 974 | if (!ap_qci_info) /* QCI not supported */ |
| 961 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); | 975 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
| 962 | 976 | ||
| 963 | return scnprintf(buf, PAGE_SIZE, | 977 | return scnprintf(buf, PAGE_SIZE, |
| 964 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", | 978 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
| 965 | ap_configuration->aqm[0], ap_configuration->aqm[1], | 979 | ap_qci_info->aqm[0], ap_qci_info->aqm[1], |
| 966 | ap_configuration->aqm[2], ap_configuration->aqm[3], | 980 | ap_qci_info->aqm[2], ap_qci_info->aqm[3], |
| 967 | ap_configuration->aqm[4], ap_configuration->aqm[5], | 981 | ap_qci_info->aqm[4], ap_qci_info->aqm[5], |
| 968 | ap_configuration->aqm[6], ap_configuration->aqm[7]); | 982 | ap_qci_info->aqm[6], ap_qci_info->aqm[7]); |
| 969 | } | 983 | } |
| 970 | 984 | ||
| 971 | static BUS_ATTR_RO(ap_usage_domain_mask); | 985 | static BUS_ATTR_RO(ap_usage_domain_mask); |
| 972 | 986 | ||
| 973 | static ssize_t ap_adapter_mask_show(struct bus_type *bus, char *buf) | 987 | static ssize_t ap_adapter_mask_show(struct bus_type *bus, char *buf) |
| 974 | { | 988 | { |
| 975 | if (!ap_configuration) /* QCI not supported */ | 989 | if (!ap_qci_info) /* QCI not supported */ |
| 976 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); | 990 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
| 977 | 991 | ||
| 978 | return scnprintf(buf, PAGE_SIZE, | 992 | return scnprintf(buf, PAGE_SIZE, |
| 979 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", | 993 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
| 980 | ap_configuration->apm[0], ap_configuration->apm[1], | 994 | ap_qci_info->apm[0], ap_qci_info->apm[1], |
| 981 | ap_configuration->apm[2], ap_configuration->apm[3], | 995 | ap_qci_info->apm[2], ap_qci_info->apm[3], |
| 982 | ap_configuration->apm[4], ap_configuration->apm[5], | 996 | ap_qci_info->apm[4], ap_qci_info->apm[5], |
| 983 | ap_configuration->apm[6], ap_configuration->apm[7]); | 997 | ap_qci_info->apm[6], ap_qci_info->apm[7]); |
| 984 | } | 998 | } |
| 985 | 999 | ||
| 986 | static BUS_ATTR_RO(ap_adapter_mask); | 1000 | static BUS_ATTR_RO(ap_adapter_mask); |
| @@ -1066,17 +1080,18 @@ static BUS_ATTR_RW(poll_timeout); · 79 unmodified lines | |||
| 1066 | 1080 | ||
| 1067 | static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) | 1081 | static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) |
| 1068 | { | 1082 | { |
| 1069 | int max_domain_id; | 1083 | return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_domain_id); |
| 1070 | |||
| 1071 | if (ap_configuration) | ||
| 1072 | max_domain_id = ap_max_domain_id ? : -1; | ||
| 1073 | else | ||
| 1074 | max_domain_id = 15; | ||
| 1075 | return scnprintf(buf, PAGE_SIZE, "%d\n", max_domain_id); | ||
| 1076 | } | 1084 | } |
| 1077 | 1085 | ||
| 1078 | static BUS_ATTR_RO(ap_max_domain_id); | 1086 | static BUS_ATTR_RO(ap_max_domain_id); |
| 1079 | 1087 | ||
| 1088 | static ssize_t ap_max_adapter_id_show(struct bus_type *bus, char *buf) | ||
| 1089 | { | ||
| 1090 | return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_adapter_id); | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | static BUS_ATTR_RO(ap_max_adapter_id); | ||
| 1094 | |||
| 1080 | static ssize_t apmask_show(struct bus_type *bus, char *buf) | 1095 | static ssize_t apmask_show(struct bus_type *bus, char *buf) |
| 1081 | { | 1096 | { |
| 1082 | int rc; | 1097 | int rc; |
| @@ -1149,6 +1164,7 @@ static struct bus_attribute *const ap_bus_attrs[] = { · 66 unmodified lines | |||
| 1149 | &bus_attr_ap_interrupts, | 1164 | &bus_attr_ap_interrupts, |
| 1150 | &bus_attr_poll_timeout, | 1165 | &bus_attr_poll_timeout, |
| 1151 | &bus_attr_ap_max_domain_id, | 1166 | &bus_attr_ap_max_domain_id, |
| 1167 | &bus_attr_ap_max_adapter_id, | ||
| 1152 | &bus_attr_apmask, | 1168 | &bus_attr_apmask, |
| 1153 | &bus_attr_aqmask, | 1169 | &bus_attr_aqmask, |
| 1154 | NULL, | 1170 | NULL, |
| @@ -1160,47 +1176,42 @@ static struct bus_attribute *const ap_bus_attrs[] = { · 5 unmodified lines | |||
| 1160 | */ | 1176 | */ |
| 1161 | static void ap_select_domain(void) | 1177 | static void ap_select_domain(void) |
| 1162 | { | 1178 | { |
| 1163 | int count, max_count, best_domain; | ||
| 1164 | struct ap_queue_status status; | 1179 | struct ap_queue_status status; |
| 1165 | int i, j; | 1180 | int card, dom; |
| 1166 | 1181 | ||
| 1167 | /* | 1182 | /* |
| 1168 | * We want to use a single domain. Either the one specified with | 1183 | * Choose the default domain. Either the one specified with |
| 1169 | * the "domain=" parameter or the domain with the maximum number | 1184 | * the "domain=" parameter or the first domain with at least |
| 1170 | * of devices. | 1185 | * one valid APQN. |
| 1171 | */ | 1186 | */ |
| 1172 | spin_lock_bh(&ap_domain_lock); | 1187 | spin_lock_bh(&ap_domain_lock); |
| 1173 | if (ap_domain_index >= 0) { | 1188 | if (ap_domain_index >= 0) { |
| 1174 | /* Domain has already been selected. */ | 1189 | /* Domain has already been selected. */ |
| 1175 | spin_unlock_bh(&ap_domain_lock); | 1190 | goto out; |
| 1176 | return; | ||
| 1177 | } | 1191 | } |
| 1178 | best_domain = -1; | 1192 | for (dom = 0; dom <= ap_max_domain_id; dom++) { |
| 1179 | max_count = 0; | 1193 | if (!ap_test_config_usage_domain(dom) || |
| 1180 | for (i = 0; i < AP_DOMAINS; i++) { | 1194 | !test_bit_inv(dom, ap_perms.aqm)) |
| 1181 | if (!ap_test_config_usage_domain(i) || | ||
| 1182 | !test_bit_inv(i, ap_perms.aqm)) | ||
| 1183 | continue; | 1195 | continue; |
| 1184 | count = 0; | 1196 | for (card = 0; card <= ap_max_adapter_id; card++) { |
| 1185 | for (j = 0; j < AP_DEVICES; j++) { | 1197 | if (!ap_test_config_card_id(card) || |
| 1186 | if (!ap_test_config_card_id(j)) | 1198 | !test_bit_inv(card, ap_perms.apm)) |
| 1187 | continue; | 1199 | continue; |
| 1188 | status = ap_test_queue(AP_MKQID(j, i), | 1200 | status = ap_test_queue(AP_MKQID(card, dom), |
| 1189 | ap_apft_available(), | 1201 | ap_apft_available(), |
| 1190 | NULL); | 1202 | NULL); |
| 1191 | if (status.response_code != AP_RESPONSE_NORMAL) | 1203 | if (status.response_code == AP_RESPONSE_NORMAL) |
| 1192 | continue; | 1204 | break; |
| 1193 | count++; | ||
| 1194 | } | ||
| 1195 | if (count > max_count) { | ||
| 1196 | max_count = count; | ||
| 1197 | best_domain = i; | ||
| 1198 | } | 1205 | } |
| 1206 | if (card <= ap_max_adapter_id) | ||
| 1207 | break; | ||
| 1199 | } | 1208 | } |
| 1200 | if (best_domain >= 0) { | 1209 | if (dom <= ap_max_domain_id) { |
| 1201 | ap_domain_index = best_domain; | 1210 | ap_domain_index = dom; |
| 1202 | AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index); | 1211 | AP_DBF(DBF_DEBUG, "%s new default domain is %d\n", |
| 1212 | __func__, ap_domain_index); | ||
| 1203 | } | 1213 | } |
| 1214 | out: | ||
| 1204 | spin_unlock_bh(&ap_domain_lock); | 1215 | spin_unlock_bh(&ap_domain_lock); |
| 1205 | } | 1216 | } |
| 1206 | 1217 | ||
| @@ -1279,12 +1290,13 @@ static int __match_queue_device_with_queue_id(struct device *dev, const void *da · 72 unmodified lines | |||
| 1279 | */ | 1290 | */ |
| 1280 | static void _ap_scan_bus_adapter(int id) | 1291 | static void _ap_scan_bus_adapter(int id) |
| 1281 | { | 1292 | { |
| 1293 | bool broken; | ||
| 1282 | ap_qid_t qid; | 1294 | ap_qid_t qid; |
| 1283 | unsigned int func; | 1295 | unsigned int func; |
| 1284 | struct ap_card *ac; | 1296 | struct ap_card *ac; |
| 1285 | struct device *dev; | 1297 | struct device *dev; |
| 1286 | struct ap_queue *aq; | 1298 | struct ap_queue *aq; |
| 1287 | int rc, dom, depth, type, comp_type, borked; | 1299 | int rc, dom, depth, type, comp_type; |
| 1288 | 1300 | ||
| 1289 | /* check if there is a card device registered with this id */ | 1301 | /* check if there is a card device registered with this id */ |
| 1290 | dev = bus_find_device(&ap_bus_type, NULL, | 1302 | dev = bus_find_device(&ap_bus_type, NULL, |
| @@ -1312,23 +1324,23 @@ static void _ap_scan_bus_adapter(int id) · 21 unmodified lines | |||
| 1312 | /* find the first valid queue */ | 1324 | /* find the first valid queue */ |
| 1313 | for (dom = 0; dom < AP_DOMAINS; dom++) { | 1325 | for (dom = 0; dom < AP_DOMAINS; dom++) { |
| 1314 | qid = AP_MKQID(id, dom); | 1326 | qid = AP_MKQID(id, dom); |
| 1315 | if (ap_query_queue(qid, &depth, &type, &func) == 0) | 1327 | if (ap_queue_info(qid, &type, &func, &depth)) |
| 1316 | break; | 1328 | break; |
| 1317 | } | 1329 | } |
| 1318 | borked = 0; | 1330 | broken = false; |
| 1319 | if (dom >= AP_DOMAINS) { | 1331 | if (dom >= AP_DOMAINS) { |
| 1320 | /* no accessible queue on this card */ | 1332 | /* no accessible queue on this card */ |
| 1321 | borked = 1; | 1333 | broken = true; |
| 1322 | } else if (ac->raw_hwtype != type) { | 1334 | } else if (ac->raw_hwtype != type) { |
| 1323 | /* card type has changed */ | 1335 | /* card type has changed */ |
| 1324 | AP_DBF(DBF_INFO, "card=%02x type changed.\n", id); | 1336 | AP_DBF(DBF_INFO, "card=%02x type changed.\n", id); |
| 1325 | borked = 1; | 1337 | broken = true; |
| 1326 | } else if (ac->functions != func) { | 1338 | } else if (ac->functions != func) { |
| 1327 | /* card functions have changed */ | 1339 | /* card functions have changed */ |
| 1328 | AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id); | 1340 | AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id); |
| 1329 | borked = 1; | 1341 | broken = true; |
| 1330 | } | 1342 | } |
| 1331 | if (borked) { | 1343 | if (broken) { |
| 1332 | /* unregister card device and associated queues */ | 1344 | /* unregister card device and associated queues */ |
| 1333 | bus_for_each_dev(&ap_bus_type, NULL, | 1345 | bus_for_each_dev(&ap_bus_type, NULL, |
| 1334 | (void *)(long) id, | 1346 | (void *)(long) id, |
| @@ -1364,16 +1376,14 @@ static void _ap_scan_bus_adapter(int id) · 29 unmodified lines | |||
| 1364 | continue; | 1376 | continue; |
| 1365 | } | 1377 | } |
| 1366 | /* try to fetch infos about this queue */ | 1378 | /* try to fetch infos about this queue */ |
| 1367 | rc = ap_query_queue(qid, &depth, &type, &func); | 1379 | broken = !ap_queue_info(qid, &type, &func, &depth); |
| 1368 | if (dev) { | 1380 | if (dev) { |
| 1369 | if (rc == -ENODEV) | 1381 | if (!broken) { |
| 1370 | borked = 1; | ||
| 1371 | else { | ||
| 1372 | spin_lock_bh(&aq->lock); | 1382 | spin_lock_bh(&aq->lock); |
| 1373 | borked = aq->state == AP_STATE_BORKED; | 1383 | broken = aq->sm_state == AP_SM_STATE_BORKED; |
| 1374 | spin_unlock_bh(&aq->lock); | 1384 | spin_unlock_bh(&aq->lock); |
| 1375 | } | 1385 | } |
| 1376 | if (borked) { | 1386 | if (broken) { |
| 1377 | /* Remove broken device */ | 1387 | /* Remove broken device */ |
| 1378 | AP_DBF(DBF_DEBUG, | 1388 | AP_DBF(DBF_DEBUG, |
| 1379 | "removing broken queue=%02x.%04x\n", | 1389 | "removing broken queue=%02x.%04x\n", |
| @@ -1383,7 +1393,7 @@ static void _ap_scan_bus_adapter(int id) · 3 unmodified lines | |||
| 1383 | put_device(dev); | 1393 | put_device(dev); |
| 1384 | continue; | 1394 | continue; |
| 1385 | } | 1395 | } |
| 1386 | if (rc) | 1396 | if (broken) |
| 1387 | continue; | 1397 | continue; |
| 1388 | /* a new queue device is needed, check out comp type */ | 1398 | /* a new queue device is needed, check out comp type */ |
| 1389 | comp_type = ap_get_compatible_type(qid, type, func); | 1399 | comp_type = ap_get_compatible_type(qid, type, func); |
| @@ -1435,11 +1445,11 @@ static void ap_scan_bus(struct work_struct *unused) · 45 unmodified lines | |||
| 1435 | { | 1445 | { |
| 1436 | int id; | 1446 | int id; |
| 1437 | 1447 | ||
| 1438 | AP_DBF(DBF_DEBUG, "%s running\n", __func__); | 1448 | ap_fetch_qci_info(ap_qci_info); |
| 1439 | |||
| 1440 | ap_query_configuration(ap_configuration); | ||
| 1441 | ap_select_domain(); | 1449 | ap_select_domain(); |
| 1442 | 1450 | ||
| 1451 | AP_DBF(DBF_DEBUG, "%s running\n", __func__); | ||
| 1452 | |||
| 1443 | /* loop over all possible adapters */ | 1453 | /* loop over all possible adapters */ |
| 1444 | for (id = 0; id < AP_DEVICES; id++) | 1454 | for (id = 0; id < AP_DEVICES; id++) |
| 1445 | _ap_scan_bus_adapter(id); | 1455 | _ap_scan_bus_adapter(id); |
| @@ -1505,7 +1515,6 @@ static void __init ap_perms_init(void) · 59 unmodified lines | |||
| 1505 | */ | 1515 | */ |
| 1506 | static int __init ap_module_init(void) | 1516 | static int __init ap_module_init(void) |
| 1507 | { | 1517 | { |
| 1508 | int max_domain_id; | ||
| 1509 | int rc, i; | 1518 | int rc, i; |
| 1510 | 1519 | ||
| 1511 | rc = ap_debug_init(); | 1520 | rc = ap_debug_init(); |
| @@ -1524,14 +1533,10 @@ static int __init ap_module_init(void) · 12 unmodified lines | |||
| 1524 | ap_perms_init(); | 1533 | ap_perms_init(); |
| 1525 | 1534 | ||
| 1526 | /* Get AP configuration data if available */ | 1535 | /* Get AP configuration data if available */ |
| 1527 | ap_init_configuration(); | 1536 | ap_init_qci_info(); |
| 1528 | 1537 | ||
| 1529 | if (ap_configuration) | 1538 | /* check default domain setting */ |
| 1530 | max_domain_id = | 1539 | if (ap_domain_index < -1 || ap_domain_index > ap_max_domain_id || |
| 1531 | ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1; | ||
| 1532 | else | ||
| 1533 | max_domain_id = 15; | ||
| 1534 | if (ap_domain_index < -1 || ap_domain_index > max_domain_id || | ||
| 1535 | (ap_domain_index >= 0 && | 1540 | (ap_domain_index >= 0 && |
| 1536 | !test_bit_inv(ap_domain_index, ap_perms.aqm))) { | 1541 | !test_bit_inv(ap_domain_index, ap_perms.aqm))) { |
| 1537 | pr_warn("%d is not a valid cryptographic domain\n", | 1542 | pr_warn("%d is not a valid cryptographic domain\n", |
| @@ -1539,6 +1544,7 @@ static int __init ap_module_init(void) · 1 unmodified line | |||
| 1539 | ap_domain_index = -1; | 1544 | ap_domain_index = -1; |
| 1540 | } | 1545 | } |
| 1541 | 1546 | ||
| 1547 | /* enable interrupts if available */ | ||
| 1542 | if (ap_interrupts_available()) { | 1548 | if (ap_interrupts_available()) { |
| 1543 | rc = register_adapter_interrupt(&ap_airq); | 1549 | rc = register_adapter_interrupt(&ap_airq); |
| 1544 | ap_airq_flag = (rc == 0); | 1550 | ap_airq_flag = (rc == 0); |
| @@ -1581,7 +1587,6 @@ static int __init ap_module_init(void) · 36 unmodified lines | |||
| 1581 | } | 1587 | } |
| 1582 | 1588 | ||
| 1583 | queue_work(system_long_wq, &ap_scan_work); | 1589 | queue_work(system_long_wq, &ap_scan_work); |
| 1584 | initialised = true; | ||
| 1585 | 1590 | ||
| 1586 | return 0; | 1591 | return 0; |
| 1587 | 1592 | ||
| @@ -1595,7 +1600,7 @@ out_bus: · 7 unmodified lines | |||
| 1595 | out: | 1600 | out: |
| 1596 | if (ap_using_interrupts()) | 1601 | if (ap_using_interrupts()) |
| 1597 | unregister_adapter_interrupt(&ap_airq); | 1602 | unregister_adapter_interrupt(&ap_airq); |
| 1598 | kfree(ap_configuration); | 1603 | kfree(ap_qci_info); |
| 1599 | return rc; | 1604 | return rc; |
| 1600 | } | 1605 | } |
| 1601 | device_initcall(ap_module_init); | 1606 | device_initcall(ap_module_init); |
| @@ -83,39 +83,39 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) · 82 unmodified lines | |||
| 83 | #define AP_INTR_ENABLED 1 /* AP interrupt enabled */ | 83 | #define AP_INTR_ENABLED 1 /* AP interrupt enabled */ |
| 84 | 84 | ||
| 85 | /* | 85 | /* |
| 86 | * AP device states | 86 | * AP queue state machine states |
| 87 | */ | 87 | */ |
| 88 | enum ap_state { | 88 | enum ap_sm_state { |
| 89 | AP_STATE_RESET_START, | 89 | AP_SM_STATE_RESET_START, |
| 90 | AP_STATE_RESET_WAIT, | 90 | AP_SM_STATE_RESET_WAIT, |
| 91 | AP_STATE_SETIRQ_WAIT, | 91 | AP_SM_STATE_SETIRQ_WAIT, |
| 92 | AP_STATE_IDLE, | 92 | AP_SM_STATE_IDLE, |
| 93 | AP_STATE_WORKING, | 93 | AP_SM_STATE_WORKING, |
| 94 | AP_STATE_QUEUE_FULL, | 94 | AP_SM_STATE_QUEUE_FULL, |
| 95 | AP_STATE_REMOVE, /* about to be removed from driver */ | 95 | AP_SM_STATE_REMOVE, /* about to be removed from driver */ |
| 96 | AP_STATE_UNBOUND, /* momentary not bound to a driver */ | 96 | AP_SM_STATE_UNBOUND, /* momentary not bound to a driver */ |
| 97 | AP_STATE_BORKED, /* broken */ | 97 | AP_SM_STATE_BORKED, /* broken */ |
| 98 | NR_AP_STATES | 98 | NR_AP_SM_STATES |
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | /* | 101 | /* |
| 102 | * AP device events | 102 | * AP queue state machine events |
| 103 | */ | 103 | */ |
| 104 | enum ap_event { | 104 | enum ap_sm_event { |
| 105 | AP_EVENT_POLL, | 105 | AP_SM_EVENT_POLL, |
| 106 | AP_EVENT_TIMEOUT, | 106 | AP_SM_EVENT_TIMEOUT, |
| 107 | NR_AP_EVENTS | 107 | NR_AP_SM_EVENTS |
| 108 | }; | 108 | }; |
| 109 | 109 | ||
| 110 | /* | 110 | /* |
| 111 | * AP wait behaviour | 111 | * AP queue state wait behaviour |
| 112 | */ | 112 | */ |
| 113 | enum ap_wait { | 113 | enum ap_sm_wait { |
| 114 | AP_WAIT_AGAIN, /* retry immediately */ | 114 | AP_SM_WAIT_AGAIN, /* retry immediately */ |
| 115 | AP_WAIT_TIMEOUT, /* wait for timeout */ | 115 | AP_SM_WAIT_TIMEOUT, /* wait for timeout */ |
| 116 | AP_WAIT_INTERRUPT, /* wait for thin interrupt (if available) */ | 116 | AP_SM_WAIT_INTERRUPT, /* wait for thin interrupt (if available) */ |
| 117 | AP_WAIT_NONE, /* no wait */ | 117 | AP_SM_WAIT_NONE, /* no wait */ |
| 118 | NR_AP_WAIT | 118 | NR_AP_SM_WAIT |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | struct ap_device; | 121 | struct ap_device; |
| @@ -172,7 +172,7 @@ struct ap_queue { · 50 unmodified lines | |||
| 172 | ap_qid_t qid; /* AP queue id. */ | 172 | ap_qid_t qid; /* AP queue id. */ |
| 173 | int interrupt; /* indicate if interrupts are enabled */ | 173 | int interrupt; /* indicate if interrupts are enabled */ |
| 174 | int queue_count; /* # messages currently on AP queue. */ | 174 | int queue_count; /* # messages currently on AP queue. */ |
| 175 | enum ap_state state; /* State of the AP device. */ | 175 | enum ap_sm_state sm_state; /* ap queue state machine state */ |
| 176 | int pendingq_count; /* # requests on pendingq list. */ | 176 | int pendingq_count; /* # requests on pendingq list. */ |
| 177 | int requestq_count; /* # requests on requestq list. */ | 177 | int requestq_count; /* # requests on requestq list. */ |
| 178 | u64 total_request_count; /* # requests ever for this AP device.*/ | 178 | u64 total_request_count; /* # requests ever for this AP device.*/ |
| @@ -185,22 +185,23 @@ struct ap_queue { · 6 unmodified lines | |||
| 185 | 185 | ||
| 186 | #define to_ap_queue(x) container_of((x), struct ap_queue, ap_dev.device) | 186 | #define to_ap_queue(x) container_of((x), struct ap_queue, ap_dev.device) |
| 187 | 187 | ||
| 188 | typedef enum ap_wait (ap_func_t)(struct ap_queue *queue); | 188 | typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue); |
| 189 | 189 | ||
| 190 | struct ap_message { | 190 | struct ap_message { |
| 191 | struct list_head list; /* Request queueing. */ | 191 | struct list_head list; /* Request queueing. */ |
| 192 | unsigned long long psmid; /* Message id. */ | 192 | unsigned long long psmid; /* Message id. */ |
| 193 | void *message; /* Pointer to message buffer. */ | 193 | void *msg; /* Pointer to message buffer. */ |
| 194 | size_t length; /* Message length. */ | 194 | unsigned int len; /* Message length. */ |
| 195 | u32 flags; /* Flags, see AP_MSG_FLAG_xxx */ | ||
| 195 | int rc; /* Return code for this message */ | 196 | int rc; /* Return code for this message */ |
| 196 | |||
| 197 | void *private; /* ap driver private pointer. */ | 197 | void *private; /* ap driver private pointer. */ |
| 198 | unsigned int special:1; /* Used for special commands. */ | ||
| 199 | /* receive is called from tasklet context */ | 198 | /* receive is called from tasklet context */ |
| 200 | void (*receive)(struct ap_queue *, struct ap_message *, | 199 | void (*receive)(struct ap_queue *, struct ap_message *, |
| 201 | struct ap_message *); | 200 | struct ap_message *); |
| 202 | }; | 201 | }; |
| 203 | 202 | ||
| 203 | #define AP_MSG_FLAG_SPECIAL (1 << 16) /* flag msg as 'special' with NQAP */ | ||
| 204 | |||
| 204 | /** | 205 | /** |
| 205 | * ap_init_message() - Initialize ap_message. | 206 | * ap_init_message() - Initialize ap_message. |
| 206 | * Initialize a message before using. Otherwise this might result in | 207 | * Initialize a message before using. Otherwise this might result in |
| @@ -218,7 +219,7 @@ static inline void ap_init_message(struct ap_message *ap_msg) · 11 unmodified lines | |||
| 218 | */ | 219 | */ |
| 219 | static inline void ap_release_message(struct ap_message *ap_msg) | 220 | static inline void ap_release_message(struct ap_message *ap_msg) |
| 220 | { | 221 | { |
| 221 | kzfree(ap_msg->message); | 222 | kzfree(ap_msg->msg); |
| 222 | kzfree(ap_msg->private); | 223 | kzfree(ap_msg->private); |
| 223 | } | 224 | } |
| 224 | 225 | ||
| @@ -230,15 +231,15 @@ static inline void ap_release_message(struct ap_message *ap_msg) · 5 unmodified lines | |||
| 230 | int ap_send(ap_qid_t, unsigned long long, void *, size_t); | 231 | int ap_send(ap_qid_t, unsigned long long, void *, size_t); |
| 231 | int ap_recv(ap_qid_t, unsigned long long *, void *, size_t); | 232 | int ap_recv(ap_qid_t, unsigned long long *, void *, size_t); |
| 232 | 233 | ||
| 233 | enum ap_wait ap_sm_event(struct ap_queue *aq, enum ap_event event); | 234 | enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event); |
| 234 | enum ap_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_event event); | 235 | enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event); |
| 235 | 236 | ||
| 236 | void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg); | 237 | void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg); |
| 237 | void ap_cancel_message(struct ap_queue *aq, struct ap_message *ap_msg); | 238 | void ap_cancel_message(struct ap_queue *aq, struct ap_message *ap_msg); |
| 238 | void ap_flush_queue(struct ap_queue *aq); | 239 | void ap_flush_queue(struct ap_queue *aq); |
| 239 | 240 | ||
| 240 | void *ap_airq_ptr(void); | 241 | void *ap_airq_ptr(void); |
| 241 | void ap_wait(enum ap_wait wait); | 242 | void ap_wait(enum ap_sm_wait wait); |
| 242 | void ap_request_timeout(struct timer_list *t); | 243 | void ap_request_timeout(struct timer_list *t); |
| 243 | void ap_bus_force_rescan(void); | 244 | void ap_bus_force_rescan(void); |
| 244 | 245 | ||
| @@ -69,9 +69,9 @@ static int ap_queue_enable_interruption(struct ap_queue *aq, void *ind) · 68 unmodified lines | |||
| 69 | */ | 69 | */ |
| 70 | static inline struct ap_queue_status | 70 | static inline struct ap_queue_status |
| 71 | __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length, | 71 | __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length, |
| 72 | unsigned int special) | 72 | int special) |
| 73 | { | 73 | { |
| 74 | if (special == 1) | 74 | if (special) |
| 75 | qid |= 0x400000UL; | 75 | qid |= 0x400000UL; |
| 76 | return ap_nqap(qid, psmid, msg, length); | 76 | return ap_nqap(qid, psmid, msg, length); |
| 77 | } | 77 | } |
| @@ -119,9 +119,9 @@ EXPORT_SYMBOL(ap_recv); · 41 unmodified lines | |||
| 119 | 119 | ||
| 120 | /* State machine definitions and helpers */ | 120 | /* State machine definitions and helpers */ |
| 121 | 121 | ||
| 122 | static enum ap_wait ap_sm_nop(struct ap_queue *aq) | 122 | static enum ap_sm_wait ap_sm_nop(struct ap_queue *aq) |
| 123 | { | 123 | { |
| 124 | return AP_WAIT_NONE; | 124 | return AP_SM_WAIT_NONE; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | /** | 127 | /** |
| @@ -129,7 +129,7 @@ static enum ap_wait ap_sm_nop(struct ap_queue *aq) · 1 unmodified line | |||
| 129 | * not change the state of the device. | 129 | * not change the state of the device. |
| 130 | * @aq: pointer to the AP queue | 130 | * @aq: pointer to the AP queue |
| 131 | * | 131 | * |
| 132 | * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT | 132 | * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
| 133 | */ | 133 | */ |
| 134 | static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) | 134 | static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) |
| 135 | { | 135 | { |
| @@ -137,7 +137,7 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) · 1 unmodified line | |||
| 137 | struct ap_message *ap_msg; | 137 | struct ap_message *ap_msg; |
| 138 | 138 | ||
| 139 | status = ap_dqap(aq->qid, &aq->reply->psmid, | 139 | status = ap_dqap(aq->qid, &aq->reply->psmid, |
| 140 | aq->reply->message, aq->reply->length); | 140 | aq->reply->msg, aq->reply->len); |
| 141 | switch (status.response_code) { | 141 | switch (status.response_code) { |
| 142 | case AP_RESPONSE_NORMAL: | 142 | case AP_RESPONSE_NORMAL: |
| 143 | aq->queue_count--; | 143 | aq->queue_count--; |
| @@ -172,31 +172,31 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) · 28 unmodified lines | |||
| 172 | * ap_sm_read(): Receive pending reply messages from an AP queue. | 172 | * ap_sm_read(): Receive pending reply messages from an AP queue. |
| 173 | * @aq: pointer to the AP queue | 173 | * @aq: pointer to the AP queue |
| 174 | * | 174 | * |
| 175 | * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT | 175 | * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
| 176 | */ | 176 | */ |
| 177 | static enum ap_wait ap_sm_read(struct ap_queue *aq) | 177 | static enum ap_sm_wait ap_sm_read(struct ap_queue *aq) |
| 178 | { | 178 | { |
| 179 | struct ap_queue_status status; | 179 | struct ap_queue_status status; |
| 180 | 180 | ||
| 181 | if (!aq->reply) | 181 | if (!aq->reply) |
| 182 | return AP_WAIT_NONE; | 182 | return AP_SM_WAIT_NONE; |
| 183 | status = ap_sm_recv(aq); | 183 | status = ap_sm_recv(aq); |
| 184 | switch (status.response_code) { | 184 | switch (status.response_code) { |
| 185 | case AP_RESPONSE_NORMAL: | 185 | case AP_RESPONSE_NORMAL: |
| 186 | if (aq->queue_count > 0) { | 186 | if (aq->queue_count > 0) { |
| 187 | aq->state = AP_STATE_WORKING; | 187 | aq->sm_state = AP_SM_STATE_WORKING; |
| 188 | return AP_WAIT_AGAIN; | 188 | return AP_SM_WAIT_AGAIN; |
| 189 | } | 189 | } |
| 190 | aq->state = AP_STATE_IDLE; | 190 | aq->sm_state = AP_SM_STATE_IDLE; |
| 191 | return AP_WAIT_NONE; | 191 | return AP_SM_WAIT_NONE; |
| 192 | case AP_RESPONSE_NO_PENDING_REPLY: | 192 | case AP_RESPONSE_NO_PENDING_REPLY: |
| 193 | if (aq->queue_count > 0) | 193 | if (aq->queue_count > 0) |
| 194 | return AP_WAIT_INTERRUPT; | 194 | return AP_SM_WAIT_INTERRUPT; |
| 195 | aq->state = AP_STATE_IDLE; | 195 | aq->sm_state = AP_SM_STATE_IDLE; |
| 196 | return AP_WAIT_NONE; | 196 | return AP_SM_WAIT_NONE; |
| 197 | default: | 197 | default: |
| 198 | aq->state = AP_STATE_BORKED; | 198 | aq->sm_state = AP_SM_STATE_BORKED; |
| 199 | return AP_WAIT_NONE; | 199 | return AP_SM_WAIT_NONE; |
| 200 | } | 200 | } |
| 201 | } | 201 | } |
| 202 | 202 | ||
| @@ -204,19 +204,20 @@ static enum ap_wait ap_sm_read(struct ap_queue *aq) · 1 unmodified line | |||
| 204 | * ap_sm_write(): Send messages from the request queue to an AP queue. | 204 | * ap_sm_write(): Send messages from the request queue to an AP queue. |
| 205 | * @aq: pointer to the AP queue | 205 | * @aq: pointer to the AP queue |
| 206 | * | 206 | * |
| 207 | * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT | 207 | * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
| 208 | */ | 208 | */ |
| 209 | static enum ap_wait ap_sm_write(struct ap_queue *aq) | 209 | static enum ap_sm_wait ap_sm_write(struct ap_queue *aq) |
| 210 | { | 210 | { |
| 211 | struct ap_queue_status status; | 211 | struct ap_queue_status status; |
| 212 | struct ap_message *ap_msg; | 212 | struct ap_message *ap_msg; |
| 213 | 213 | ||
| 214 | if (aq->requestq_count <= 0) | 214 | if (aq->requestq_count <= 0) |
| 215 | return AP_WAIT_NONE; | 215 | return AP_SM_WAIT_NONE; |
| 216 | /* Start the next request on the queue. */ | 216 | /* Start the next request on the queue. */ |
| 217 | ap_msg = list_entry(aq->requestq.next, struct ap_message, list); | 217 | ap_msg = list_entry(aq->requestq.next, struct ap_message, list); |
| 218 | status = __ap_send(aq->qid, ap_msg->psmid, | 218 | status = __ap_send(aq->qid, ap_msg->psmid, |
| 219 | ap_msg->message, ap_msg->length, ap_msg->special); | 219 | ap_msg->msg, ap_msg->len, |
| 220 | ap_msg->flags & AP_MSG_FLAG_SPECIAL); | ||
| 220 | switch (status.response_code) { | 221 | switch (status.response_code) { |
| 221 | case AP_RESPONSE_NORMAL: | 222 | case AP_RESPONSE_NORMAL: |
| 222 | aq->queue_count++; | 223 | aq->queue_count++; |
| @@ -226,26 +227,26 @@ static enum ap_wait ap_sm_write(struct ap_queue *aq) · 3 unmodified lines | |||
| 226 | aq->requestq_count--; | 227 | aq->requestq_count--; |
| 227 | aq->pendingq_count++; | 228 | aq->pendingq_count++; |
| 228 | if (aq->queue_count < aq->card->queue_depth) { | 229 | if (aq->queue_count < aq->card->queue_depth) { |
| 229 | aq->state = AP_STATE_WORKING; | 230 | aq->sm_state = AP_SM_STATE_WORKING; |
| 230 | return AP_WAIT_AGAIN; | 231 | return AP_SM_WAIT_AGAIN; |
| 231 | } | 232 | } |
| 232 | fallthrough; | 233 | fallthrough; |
| 233 | case AP_RESPONSE_Q_FULL: | 234 | case AP_RESPONSE_Q_FULL: |
| 234 | aq->state = AP_STATE_QUEUE_FULL; | 235 | aq->sm_state = AP_SM_STATE_QUEUE_FULL; |
| 235 | return AP_WAIT_INTERRUPT; | 236 | return AP_SM_WAIT_INTERRUPT; |
| 236 | case AP_RESPONSE_RESET_IN_PROGRESS: | 237 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 237 | aq->state = AP_STATE_RESET_WAIT; | 238 | aq->sm_state = AP_SM_STATE_RESET_WAIT; |
| 238 | return AP_WAIT_TIMEOUT; | 239 | return AP_SM_WAIT_TIMEOUT; |
| 239 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 240 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
| 240 | case AP_RESPONSE_REQ_FAC_NOT_INST: | 241 | case AP_RESPONSE_REQ_FAC_NOT_INST: |
| 241 | list_del_init(&ap_msg->list); | 242 | list_del_init(&ap_msg->list); |
| 242 | aq->requestq_count--; | 243 | aq->requestq_count--; |
| 243 | ap_msg->rc = -EINVAL; | 244 | ap_msg->rc = -EINVAL; |
| 244 | ap_msg->receive(aq, ap_msg, NULL); | 245 | ap_msg->receive(aq, ap_msg, NULL); |
| 245 | return AP_WAIT_AGAIN; | 246 | return AP_SM_WAIT_AGAIN; |
| 246 | default: | 247 | default: |
| 247 | aq->state = AP_STATE_BORKED; | 248 | aq->sm_state = AP_SM_STATE_BORKED; |
| 248 | return AP_WAIT_NONE; | 249 | return AP_SM_WAIT_NONE; |
| 249 | } | 250 | } |
| 250 | } | 251 | } |
| 251 | 252 | ||
| @@ -253,9 +254,9 @@ static enum ap_wait ap_sm_write(struct ap_queue *aq) · 1 unmodified line | |||
| 253 | * ap_sm_read_write(): Send and receive messages to/from an AP queue. | 254 | * ap_sm_read_write(): Send and receive messages to/from an AP queue. |
| 254 | * @aq: pointer to the AP queue | 255 | * @aq: pointer to the AP queue |
| 255 | * | 256 | * |
| 256 | * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT | 257 | * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT |
| 257 | */ | 258 | */ |
| 258 | static enum ap_wait ap_sm_read_write(struct ap_queue *aq) | 259 | static enum ap_sm_wait ap_sm_read_write(struct ap_queue *aq) |
| 259 | { | 260 | { |
| 260 | return min(ap_sm_read(aq), ap_sm_write(aq)); | 261 | return min(ap_sm_read(aq), ap_sm_write(aq)); |
| 261 | } | 262 | } |
| @@ -266,7 +267,7 @@ static enum ap_wait ap_sm_read_write(struct ap_queue *aq) · 4 unmodified lines | |||
| 266 | * | 267 | * |
| 267 | * Submit the Reset command to an AP queue. | 268 | * Submit the Reset command to an AP queue. |
| 268 | */ | 269 | */ |
| 269 | static enum ap_wait ap_sm_reset(struct ap_queue *aq) | 270 | static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq) |
| 270 | { | 271 | { |
| 271 | struct ap_queue_status status; | 272 | struct ap_queue_status status; |
| 272 | 273 | ||
| @@ -274,17 +275,17 @@ static enum ap_wait ap_sm_reset(struct ap_queue *aq) · 1 unmodified line | |||
| 274 | switch (status.response_code) { | 275 | switch (status.response_code) { |
| 275 | case AP_RESPONSE_NORMAL: | 276 | case AP_RESPONSE_NORMAL: |
| 276 | case AP_RESPONSE_RESET_IN_PROGRESS: | 277 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 277 | aq->state = AP_STATE_RESET_WAIT; | 278 | aq->sm_state = AP_SM_STATE_RESET_WAIT; |
| 278 | aq->interrupt = AP_INTR_DISABLED; | 279 | aq->interrupt = AP_INTR_DISABLED; |
| 279 | return AP_WAIT_TIMEOUT; | 280 | return AP_SM_WAIT_TIMEOUT; |
| 280 | case AP_RESPONSE_BUSY: | 281 | case AP_RESPONSE_BUSY: |
| 281 | return AP_WAIT_TIMEOUT; | 282 | return AP_SM_WAIT_TIMEOUT; |
| 282 | case AP_RESPONSE_Q_NOT_AVAIL: | 283 | case AP_RESPONSE_Q_NOT_AVAIL: |
| 283 | case AP_RESPONSE_DECONFIGURED: | 284 | case AP_RESPONSE_DECONFIGURED: |
| 284 | case AP_RESPONSE_CHECKSTOPPED: | 285 | case AP_RESPONSE_CHECKSTOPPED: |
| 285 | default: | 286 | default: |
| 286 | aq->state = AP_STATE_BORKED; | 287 | aq->sm_state = AP_SM_STATE_BORKED; |
| 287 | return AP_WAIT_NONE; | 288 | return AP_SM_WAIT_NONE; |
| 288 | } | 289 | } |
| 289 | } | 290 | } |
| 290 | 291 | ||
| @@ -294,7 +295,7 @@ static enum ap_wait ap_sm_reset(struct ap_queue *aq) · 3 unmodified lines | |||
| 294 | * | 295 | * |
| 295 | * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0. | 296 | * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0. |
| 296 | */ | 297 | */ |
| 297 | static enum ap_wait ap_sm_reset_wait(struct ap_queue *aq) | 298 | static enum ap_sm_wait ap_sm_reset_wait(struct ap_queue *aq) |
| 298 | { | 299 | { |
| 299 | struct ap_queue_status status; | 300 | struct ap_queue_status status; |
| 300 | void *lsi_ptr; | 301 | void *lsi_ptr; |
| @@ -310,20 +311,20 @@ static enum ap_wait ap_sm_reset_wait(struct ap_queue *aq) · 9 unmodified lines | |||
| 310 | case AP_RESPONSE_NORMAL: | 311 | case AP_RESPONSE_NORMAL: |
| 311 | lsi_ptr = ap_airq_ptr(); | 312 | lsi_ptr = ap_airq_ptr(); |
| 312 | if (lsi_ptr && ap_queue_enable_interruption(aq, lsi_ptr) == 0) | 313 | if (lsi_ptr && ap_queue_enable_interruption(aq, lsi_ptr) == 0) |
| 313 | aq->state = AP_STATE_SETIRQ_WAIT; | 314 | aq->sm_state = AP_SM_STATE_SETIRQ_WAIT; |
| 314 | else | 315 | else |
| 315 | aq->state = (aq->queue_count > 0) ? | 316 | aq->sm_state = (aq->queue_count > 0) ? |
| 316 | AP_STATE_WORKING : AP_STATE_IDLE; | 317 | AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; |
| 317 | return AP_WAIT_AGAIN; | 318 | return AP_SM_WAIT_AGAIN; |
| 318 | case AP_RESPONSE_BUSY: | 319 | case AP_RESPONSE_BUSY: |
| 319 | case AP_RESPONSE_RESET_IN_PROGRESS: | 320 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 320 | return AP_WAIT_TIMEOUT; | 321 | return AP_SM_WAIT_TIMEOUT; |
| 321 | case AP_RESPONSE_Q_NOT_AVAIL: | 322 | case AP_RESPONSE_Q_NOT_AVAIL: |
| 322 | case AP_RESPONSE_DECONFIGURED: | 323 | case AP_RESPONSE_DECONFIGURED: |
| 323 | case AP_RESPONSE_CHECKSTOPPED: | 324 | case AP_RESPONSE_CHECKSTOPPED: |
| 324 | default: | 325 | default: |
| 325 | aq->state = AP_STATE_BORKED; | 326 | aq->sm_state = AP_SM_STATE_BORKED; |
| 326 | return AP_WAIT_NONE; | 327 | return AP_SM_WAIT_NONE; |
| 327 | } | 328 | } |
| 328 | } | 329 | } |
| 329 | 330 | ||
| @@ -333,7 +334,7 @@ static enum ap_wait ap_sm_reset_wait(struct ap_queue *aq) · 3 unmodified lines | |||
| 333 | * | 334 | * |
| 334 | * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0. | 335 | * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0. |
| 335 | */ | 336 | */ |
| 336 | static enum ap_wait ap_sm_setirq_wait(struct ap_queue *aq) | 337 | static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq) |
| 337 | { | 338 | { |
| 338 | struct ap_queue_status status; | 339 | struct ap_queue_status status; |
| 339 | 340 | ||
| @@ -347,75 +348,75 @@ static enum ap_wait ap_sm_setirq_wait(struct ap_queue *aq) · 7 unmodified lines | |||
| 347 | if (status.irq_enabled == 1) { | 348 | if (status.irq_enabled == 1) { |
| 348 | /* Irqs are now enabled */ | 349 | /* Irqs are now enabled */ |
| 349 | aq->interrupt = AP_INTR_ENABLED; | 350 | aq->interrupt = AP_INTR_ENABLED; |
| 350 | aq->state = (aq->queue_count > 0) ? | 351 | aq->sm_state = (aq->queue_count > 0) ? |
| 351 | AP_STATE_WORKING : AP_STATE_IDLE; | 352 | AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; |
| 352 | } | 353 | } |
| 353 | 354 | ||
| 354 | switch (status.response_code) { | 355 | switch (status.response_code) { |
| 355 | case AP_RESPONSE_NORMAL: | 356 | case AP_RESPONSE_NORMAL: |
| 356 | if (aq->queue_count > 0) | 357 | if (aq->queue_count > 0) |
| 357 | return AP_WAIT_AGAIN; | 358 | return AP_SM_WAIT_AGAIN; |
| 358 | fallthrough; | 359 | fallthrough; |
| 359 | case AP_RESPONSE_NO_PENDING_REPLY: | 360 | case AP_RESPONSE_NO_PENDING_REPLY: |
| 360 | return AP_WAIT_TIMEOUT; | 361 | return AP_SM_WAIT_TIMEOUT; |
| 361 | default: | 362 | default: |
| 362 | aq->state = AP_STATE_BORKED; | 363 | aq->sm_state = AP_SM_STATE_BORKED; |
| 363 | return AP_WAIT_NONE; | 364 | return AP_SM_WAIT_NONE; |
| 364 | } | 365 | } |
| 365 | } | 366 | } |
| 366 | 367 | ||
| 367 | /* | 368 | /* |
| 368 | * AP state machine jump table | 369 | * AP state machine jump table |
| 369 | */ | 370 | */ |
| 370 | static ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = { | 371 | static ap_func_t *ap_jumptable[NR_AP_SM_STATES][NR_AP_SM_EVENTS] = { |
| 371 | [AP_STATE_RESET_START] = { | 372 | [AP_SM_STATE_RESET_START] = { |
| 372 | [AP_EVENT_POLL] = ap_sm_reset, | 373 | [AP_SM_EVENT_POLL] = ap_sm_reset, |
| 373 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 374 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 374 | }, | 375 | }, |
| 375 | [AP_STATE_RESET_WAIT] = { | 376 | [AP_SM_STATE_RESET_WAIT] = { |
| 376 | [AP_EVENT_POLL] = ap_sm_reset_wait, | 377 | [AP_SM_EVENT_POLL] = ap_sm_reset_wait, |
| 377 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 378 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 378 | }, | 379 | }, |
| 379 | [AP_STATE_SETIRQ_WAIT] = { | 380 | [AP_SM_STATE_SETIRQ_WAIT] = { |
| 380 | [AP_EVENT_POLL] = ap_sm_setirq_wait, | 381 | [AP_SM_EVENT_POLL] = ap_sm_setirq_wait, |
| 381 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 382 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 382 | }, | 383 | }, |
| 383 | [AP_STATE_IDLE] = { | 384 | [AP_SM_STATE_IDLE] = { |
| 384 | [AP_EVENT_POLL] = ap_sm_write, | 385 | [AP_SM_EVENT_POLL] = ap_sm_write, |
| 385 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 386 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 386 | }, | 387 | }, |
| 387 | [AP_STATE_WORKING] = { | 388 | [AP_SM_STATE_WORKING] = { |
| 388 | [AP_EVENT_POLL] = ap_sm_read_write, | 389 | [AP_SM_EVENT_POLL] = ap_sm_read_write, |
| 389 | [AP_EVENT_TIMEOUT] = ap_sm_reset, | 390 | [AP_SM_EVENT_TIMEOUT] = ap_sm_reset, |
| 390 | }, | 391 | }, |
| 391 | [AP_STATE_QUEUE_FULL] = { | 392 | [AP_SM_STATE_QUEUE_FULL] = { |
| 392 | [AP_EVENT_POLL] = ap_sm_read, | 393 | [AP_SM_EVENT_POLL] = ap_sm_read, |
| 393 | [AP_EVENT_TIMEOUT] = ap_sm_reset, | 394 | [AP_SM_EVENT_TIMEOUT] = ap_sm_reset, |
| 394 | }, | 395 | }, |
| 395 | [AP_STATE_REMOVE] = { | 396 | [AP_SM_STATE_REMOVE] = { |
| 396 | [AP_EVENT_POLL] = ap_sm_nop, | 397 | [AP_SM_EVENT_POLL] = ap_sm_nop, |
| 397 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 398 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 398 | }, | 399 | }, |
| 399 | [AP_STATE_UNBOUND] = { | 400 | [AP_SM_STATE_UNBOUND] = { |
| 400 | [AP_EVENT_POLL] = ap_sm_nop, | 401 | [AP_SM_EVENT_POLL] = ap_sm_nop, |
| 401 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 402 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 402 | }, | 403 | }, |
| 403 | [AP_STATE_BORKED] = { | 404 | [AP_SM_STATE_BORKED] = { |
| 404 | [AP_EVENT_POLL] = ap_sm_nop, | 405 | [AP_SM_EVENT_POLL] = ap_sm_nop, |
| 405 | [AP_EVENT_TIMEOUT] = ap_sm_nop, | 406 | [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, |
| 406 | }, | 407 | }, |
| 407 | }; | 408 | }; |
| 408 | 409 | ||
| 409 | enum ap_wait ap_sm_event(struct ap_queue *aq, enum ap_event event) | 410 | enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event) |
| 410 | { | 411 | { |
| 411 | return ap_jumptable[aq->state][event](aq); | 412 | return ap_jumptable[aq->sm_state][event](aq); |
| 412 | } | 413 | } |
| 413 | 414 | ||
| 414 | enum ap_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_event event) | 415 | enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event) |
| 415 | { | 416 | { |
| 416 | enum ap_wait wait; | 417 | enum ap_sm_wait wait; |
| 417 | 418 | ||
| 418 | while ((wait = ap_sm_event(aq, event)) == AP_WAIT_AGAIN) | 419 | while ((wait = ap_sm_event(aq, event)) == AP_SM_WAIT_AGAIN) |
| 419 | ; | 420 | ; |
| 420 | return wait; | 421 | return wait; |
| 421 | } | 422 | } |
| @@ -486,13 +487,13 @@ static ssize_t reset_show(struct device *dev, · 64 unmodified lines | |||
| 486 | int rc = 0; | 487 | int rc = 0; |
| 487 | 488 | ||
| 488 | spin_lock_bh(&aq->lock); | 489 | spin_lock_bh(&aq->lock); |
| 489 | switch (aq->state) { | 490 | switch (aq->sm_state) { |
| 490 | case AP_STATE_RESET_START: | 491 | case AP_SM_STATE_RESET_START: |
| 491 | case AP_STATE_RESET_WAIT: | 492 | case AP_SM_STATE_RESET_WAIT: |
| 492 | rc = scnprintf(buf, PAGE_SIZE, "Reset in progress.\n"); | 493 | rc = scnprintf(buf, PAGE_SIZE, "Reset in progress.\n"); |
| 493 | break; | 494 | break; |
| 494 | case AP_STATE_WORKING: | 495 | case AP_SM_STATE_WORKING: |
| 495 | case AP_STATE_QUEUE_FULL: | 496 | case AP_SM_STATE_QUEUE_FULL: |
| 496 | rc = scnprintf(buf, PAGE_SIZE, "Reset Timer armed.\n"); | 497 | rc = scnprintf(buf, PAGE_SIZE, "Reset Timer armed.\n"); |
| 497 | break; | 498 | break; |
| 498 | default: | 499 | default: |
| @@ -510,8 +511,8 @@ static ssize_t reset_store(struct device *dev, · 11 unmodified lines | |||
| 510 | 511 | ||
| 511 | spin_lock_bh(&aq->lock); | 512 | spin_lock_bh(&aq->lock); |
| 512 | __ap_flush_queue(aq); | 513 | __ap_flush_queue(aq); |
| 513 | aq->state = AP_STATE_RESET_START; | 514 | aq->sm_state = AP_SM_STATE_RESET_START; |
| 514 | ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); | 515 | ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); |
| 515 | spin_unlock_bh(&aq->lock); | 516 | spin_unlock_bh(&aq->lock); |
| 516 | 517 | ||
| 517 | AP_DBF(DBF_INFO, "reset queue=%02x.%04x triggered by user\n", | 518 | AP_DBF(DBF_INFO, "reset queue=%02x.%04x triggered by user\n", |
| @@ -529,7 +530,7 @@ static ssize_t interrupt_show(struct device *dev, · 11 unmodified lines | |||
| 529 | int rc = 0; | 530 | int rc = 0; |
| 530 | 531 | ||
| 531 | spin_lock_bh(&aq->lock); | 532 | spin_lock_bh(&aq->lock); |
| 532 | if (aq->state == AP_STATE_SETIRQ_WAIT) | 533 | if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT) |
| 533 | rc = scnprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n"); | 534 | rc = scnprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n"); |
| 534 | else if (aq->interrupt == AP_INTR_ENABLED) | 535 | else if (aq->interrupt == AP_INTR_ENABLED) |
| 535 | rc = scnprintf(buf, PAGE_SIZE, "Interrupts enabled.\n"); | 536 | rc = scnprintf(buf, PAGE_SIZE, "Interrupts enabled.\n"); |
| @@ -586,7 +587,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type) · 50 unmodified lines | |||
| 586 | aq->ap_dev.device.type = &ap_queue_type; | 587 | aq->ap_dev.device.type = &ap_queue_type; |
| 587 | aq->ap_dev.device_type = device_type; | 588 | aq->ap_dev.device_type = device_type; |
| 588 | aq->qid = qid; | 589 | aq->qid = qid; |
| 589 | aq->state = AP_STATE_UNBOUND; | 590 | aq->sm_state = AP_SM_STATE_UNBOUND; |
| 590 | aq->interrupt = AP_INTR_DISABLED; | 591 | aq->interrupt = AP_INTR_DISABLED; |
| 591 | spin_lock_init(&aq->lock); | 592 | spin_lock_init(&aq->lock); |
| 592 | INIT_LIST_HEAD(&aq->pendingq); | 593 | INIT_LIST_HEAD(&aq->pendingq); |
| @@ -601,7 +602,7 @@ void ap_queue_init_reply(struct ap_queue *aq, struct ap_message *reply) · 8 unmodified lines | |||
| 601 | aq->reply = reply; | 602 | aq->reply = reply; |
| 602 | 603 | ||
| 603 | spin_lock_bh(&aq->lock); | 604 | spin_lock_bh(&aq->lock); |
| 604 | ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); | 605 | ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); |
| 605 | spin_unlock_bh(&aq->lock); | 606 | spin_unlock_bh(&aq->lock); |
| 606 | } | 607 | } |
| 607 | EXPORT_SYMBOL(ap_queue_init_reply); | 608 | EXPORT_SYMBOL(ap_queue_init_reply); |
| @@ -625,7 +626,7 @@ void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) · 17 unmodified lines | |||
| 625 | aq->total_request_count++; | 626 | aq->total_request_count++; |
| 626 | atomic64_inc(&aq->card->total_request_count); | 627 | atomic64_inc(&aq->card->total_request_count); |
| 627 | /* Send/receive as many request from the queue as possible. */ | 628 | /* Send/receive as many request from the queue as possible. */ |
| 628 | ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL)); | 629 | ap_wait(ap_sm_event_loop(aq, AP_SM_EVENT_POLL)); |
| 629 | spin_unlock_bh(&aq->lock); | 630 | spin_unlock_bh(&aq->lock); |
| 630 | } | 631 | } |
| 631 | EXPORT_SYMBOL(ap_queue_message); | 632 | EXPORT_SYMBOL(ap_queue_message); |
| @@ -698,7 +699,7 @@ void ap_queue_prepare_remove(struct ap_queue *aq) · 66 unmodified lines | |||
| 698 | /* flush queue */ | 699 | /* flush queue */ |
| 699 | __ap_flush_queue(aq); | 700 | __ap_flush_queue(aq); |
| 700 | /* set REMOVE state to prevent new messages are queued in */ | 701 | /* set REMOVE state to prevent new messages are queued in */ |
| 701 | aq->state = AP_STATE_REMOVE; | 702 | aq->sm_state = AP_SM_STATE_REMOVE; |
| 702 | spin_unlock_bh(&aq->lock); | 703 | spin_unlock_bh(&aq->lock); |
| 703 | del_timer_sync(&aq->timeout); | 704 | del_timer_sync(&aq->timeout); |
| 704 | } | 705 | } |
| @@ -707,22 +708,22 @@ void ap_queue_remove(struct ap_queue *aq) · 2 unmodified lines | |||
| 707 | { | 708 | { |
| 708 | /* | 709 | /* |
| 709 | * all messages have been flushed and the state is | 710 | * all messages have been flushed and the state is |
| 710 | * AP_STATE_REMOVE. Now reset with zero which also | 711 | * AP_SM_STATE_REMOVE. Now reset with zero which also |
| 711 | * clears the irq registration and move the state | 712 | * clears the irq registration and move the state |
| 712 | * to AP_STATE_UNBOUND to signal that this queue | 713 | * to AP_SM_STATE_UNBOUND to signal that this queue |
| 713 | * is not used by any driver currently. | 714 | * is not used by any driver currently. |
| 714 | */ | 715 | */ |
| 715 | spin_lock_bh(&aq->lock); | 716 | spin_lock_bh(&aq->lock); |
| 716 | ap_zapq(aq->qid); | 717 | ap_zapq(aq->qid); |
| 717 | aq->state = AP_STATE_UNBOUND; | 718 | aq->sm_state = AP_SM_STATE_UNBOUND; |
| 718 | spin_unlock_bh(&aq->lock); | 719 | spin_unlock_bh(&aq->lock); |
| 719 | } | 720 | } |
| 720 | 721 | ||
| 721 | void ap_queue_init_state(struct ap_queue *aq) | 722 | void ap_queue_init_state(struct ap_queue *aq) |
| 722 | { | 723 | { |
| 723 | spin_lock_bh(&aq->lock); | 724 | spin_lock_bh(&aq->lock); |
| 724 | aq->state = AP_STATE_RESET_START; | 725 | aq->sm_state = AP_SM_STATE_RESET_START; |
| 725 | ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); | 726 | ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); |
| 726 | spin_unlock_bh(&aq->lock); | 727 | spin_unlock_bh(&aq->lock); |
| 727 | } | 728 | } |
| 728 | EXPORT_SYMBOL(ap_queue_init_state); | 729 | EXPORT_SYMBOL(ap_queue_init_state); |
| @@ -1603,8 +1603,8 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, · 1602 unmodified lines | |||
| 1603 | if (rc == 0) | 1603 | if (rc == 0) |
| 1604 | break; | 1604 | break; |
| 1605 | } | 1605 | } |
| 1606 | if (rc) | 1606 | if (rc) |
| 1607 | return rc; | 1607 | return rc; |
| 1608 | 1608 | ||
| 1609 | if (is_xts) { | 1609 | if (is_xts) { |
| 1610 | keysize = CCACIPHERTOKENSIZE; | 1610 | keysize = CCACIPHERTOKENSIZE; |
| @@ -634,7 +634,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms, · 633 unmodified lines | |||
| 634 | { | 634 | { |
| 635 | struct zcrypt_card *zc, *pref_zc; | 635 | struct zcrypt_card *zc, *pref_zc; |
| 636 | struct zcrypt_queue *zq, *pref_zq; | 636 | struct zcrypt_queue *zq, *pref_zq; |
| 637 | unsigned int weight, pref_weight; | 637 | unsigned int weight = 0, pref_weight = 0; |
| 638 | unsigned int func_code; | 638 | unsigned int func_code; |
| 639 | int qid = 0, rc = -ENODEV; | 639 | int qid = 0, rc = -ENODEV; |
| 640 | struct module *mod; | 640 | struct module *mod; |
| @@ -718,7 +718,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms, · 77 unmodified lines | |||
| 718 | { | 718 | { |
| 719 | struct zcrypt_card *zc, *pref_zc; | 719 | struct zcrypt_card *zc, *pref_zc; |
| 720 | struct zcrypt_queue *zq, *pref_zq; | 720 | struct zcrypt_queue *zq, *pref_zq; |
| 721 | unsigned int weight, pref_weight; | 721 | unsigned int weight = 0, pref_weight = 0; |
| 722 | unsigned int func_code; | 722 | unsigned int func_code; |
| 723 | int qid = 0, rc = -ENODEV; | 723 | int qid = 0, rc = -ENODEV; |
| 724 | struct module *mod; | 724 | struct module *mod; |
| @@ -803,7 +803,7 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, · 78 unmodified lines | |||
| 803 | struct zcrypt_card *zc, *pref_zc; | 803 | struct zcrypt_card *zc, *pref_zc; |
| 804 | struct zcrypt_queue *zq, *pref_zq; | 804 | struct zcrypt_queue *zq, *pref_zq; |
| 805 | struct ap_message ap_msg; | 805 | struct ap_message ap_msg; |
| 806 | unsigned int weight, pref_weight; | 806 | unsigned int weight = 0, pref_weight = 0; |
| 807 | unsigned int func_code; | 807 | unsigned int func_code; |
| 808 | unsigned short *domain, tdom; | 808 | unsigned short *domain, tdom; |
| 809 | int qid = 0, rc = -ENODEV; | 809 | int qid = 0, rc = -ENODEV; |
| @@ -822,7 +822,7 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, · 12 unmodified lines | |||
| 822 | * domain but a control only domain, use the default domain as target. | 822 | * domain but a control only domain, use the default domain as target. |
| 823 | */ | 823 | */ |
| 824 | tdom = *domain; | 824 | tdom = *domain; |
| 825 | if (tdom >= 0 && tdom < AP_DOMAINS && | 825 | if (tdom < AP_DOMAINS && |
| 826 | !ap_test_config_usage_domain(tdom) && | 826 | !ap_test_config_usage_domain(tdom) && |
| 827 | ap_test_config_ctrl_domain(tdom) && | 827 | ap_test_config_ctrl_domain(tdom) && |
| 828 | ap_domain_index >= 0) | 828 | ap_domain_index >= 0) |
| @@ -931,7 +931,7 @@ static long _zcrypt_send_ep11_cprb(struct ap_perms *perms, · 102 unmodified lines | |||
| 931 | struct zcrypt_queue *zq, *pref_zq; | 931 | struct zcrypt_queue *zq, *pref_zq; |
| 932 | struct ep11_target_dev *targets; | 932 | struct ep11_target_dev *targets; |
| 933 | unsigned short target_num; | 933 | unsigned short target_num; |
| 934 | unsigned int weight, pref_weight; | 934 | unsigned int weight = 0, pref_weight = 0; |
| 935 | unsigned int func_code; | 935 | unsigned int func_code; |
| 936 | struct ap_message ap_msg; | 936 | struct ap_message ap_msg; |
| 937 | int qid = 0, rc = -ENODEV; | 937 | int qid = 0, rc = -ENODEV; |
| @@ -1040,7 +1040,7 @@ static long zcrypt_rng(char *buffer) · 102 unmodified lines | |||
| 1040 | { | 1040 | { |
| 1041 | struct zcrypt_card *zc, *pref_zc; | 1041 | struct zcrypt_card *zc, *pref_zc; |
| 1042 | struct zcrypt_queue *zq, *pref_zq; | 1042 | struct zcrypt_queue *zq, *pref_zq; |
| 1043 | unsigned int weight, pref_weight; | 1043 | unsigned int weight = 0, pref_weight = 0; |
| 1044 | unsigned int func_code; | 1044 | unsigned int func_code; |
| 1045 | struct ap_message ap_msg; | 1045 | struct ap_message ap_msg; |
| 1046 | unsigned int domain; | 1046 | unsigned int domain; |
| @@ -1298,99 +1298,119 @@ static int zcrypt_requestq_count(void) · 251 unmodified lines | |||
| 1298 | return requestq_count; | 1298 | return requestq_count; |
| 1299 | } | 1299 | } |
| 1300 | 1300 | ||
| 1301 | static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | 1301 | static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg) |
| 1302 | unsigned long arg) | ||
| 1303 | { | 1302 | { |
| 1304 | int rc; | 1303 | int rc; |
| 1305 | struct ap_perms *perms = | 1304 | struct ica_rsa_modexpo mex; |
| 1306 | (struct ap_perms *) filp->private_data; | 1305 | struct ica_rsa_modexpo __user *umex = (void __user *) arg; |
| 1307 | 1306 | ||
| 1308 | rc = zcrypt_check_ioctl(perms, cmd); | 1307 | if (copy_from_user(&mex, umex, sizeof(mex))) |
| 1309 | if (rc) | 1308 | return -EFAULT; |
| 1310 | return rc; | 1309 | do { |
| 1311 | 1310 | rc = zcrypt_rsa_modexpo(perms, &mex); | |
| 1312 | switch (cmd) { | 1311 | } while (rc == -EAGAIN); |
| 1313 | case ICARSAMODEXPO: { | 1312 | /* on failure: retry once again after a requested rescan */ |
| 1314 | struct ica_rsa_modexpo __user *umex = (void __user *) arg; | 1313 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) |
| 1315 | struct ica_rsa_modexpo mex; | ||
| 1316 | |||
| 1317 | if (copy_from_user(&mex, umex, sizeof(mex))) | ||
| 1318 | return -EFAULT; | ||
| 1319 | do { | 1314 | do { |
| 1320 | rc = zcrypt_rsa_modexpo(perms, &mex); | 1315 | rc = zcrypt_rsa_modexpo(perms, &mex); |
| 1321 | } while (rc == -EAGAIN); | 1316 | } while (rc == -EAGAIN); |
| 1322 | /* on failure: retry once again after a requested rescan */ | 1317 | if (rc) { |
| 1323 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | 1318 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc); |
| 1324 | do { | 1319 | return rc; |
| 1325 | rc = zcrypt_rsa_modexpo(perms, &mex); | ||
| 1326 | } while (rc == -EAGAIN); | ||
| 1327 | if (rc) { | ||
| 1328 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc); | ||
| 1329 | return rc; | ||
| 1330 | } | ||
| 1331 | return put_user(mex.outputdatalength, &umex->outputdatalength); | ||
| 1332 | } | 1320 | } |
| 1333 | case ICARSACRT: { | 1321 | return put_user(mex.outputdatalength, &umex->outputdatalength); |
| 1334 | struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg; | 1322 | } |
| 1335 | struct ica_rsa_modexpo_crt crt; | ||
| 1336 | 1323 | ||
| 1337 | if (copy_from_user(&crt, ucrt, sizeof(crt))) | 1324 | static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg) |
| 1338 | return -EFAULT; | 1325 | { |
| 1326 | int rc; | ||
| 1327 | struct ica_rsa_modexpo_crt crt; | ||
| 1328 | struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg; | ||
| 1329 | |||
| 1330 | if (copy_from_user(&crt, ucrt, sizeof(crt))) | ||
| 1331 | return -EFAULT; | ||
| 1332 | do { | ||
| 1333 | rc = zcrypt_rsa_crt(perms, &crt); | ||
| 1334 | } while (rc == -EAGAIN); | ||
| 1335 | /* on failure: retry once again after a requested rescan */ | ||
| 1336 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 1339 | do { | 1337 | do { |
| 1340 | rc = zcrypt_rsa_crt(perms, &crt); | 1338 | rc = zcrypt_rsa_crt(perms, &crt); |
| 1341 | } while (rc == -EAGAIN); | 1339 | } while (rc == -EAGAIN); |
| 1342 | /* on failure: retry once again after a requested rescan */ | 1340 | if (rc) { |
| 1343 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | 1341 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc); |
| 1344 | do { | 1342 | return rc; |
| 1345 | rc = zcrypt_rsa_crt(perms, &crt); | ||
| 1346 | } while (rc == -EAGAIN); | ||
| 1347 | if (rc) { | ||
| 1348 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc); | ||
| 1349 | return rc; | ||
| 1350 | } | ||
| 1351 | return put_user(crt.outputdatalength, &ucrt->outputdatalength); | ||
| 1352 | } | 1343 | } |
| 1353 | case ZSECSENDCPRB: { | 1344 | return put_user(crt.outputdatalength, &ucrt->outputdatalength); |
| 1354 | struct ica_xcRB __user *uxcRB = (void __user *) arg; | 1345 | } |
| 1355 | struct ica_xcRB xcRB; | ||
| 1356 | 1346 | ||
| 1357 | if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB))) | 1347 | static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg) |
| 1358 | return -EFAULT; | 1348 | { |
| 1349 | int rc; | ||
| 1350 | struct ica_xcRB xcRB; | ||
| 1351 | struct ica_xcRB __user *uxcRB = (void __user *) arg; | ||
| 1352 | |||
| 1353 | if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB))) | ||
| 1354 | return -EFAULT; | ||
| 1355 | do { | ||
| 1356 | rc = _zcrypt_send_cprb(perms, &xcRB); | ||
| 1357 | } while (rc == -EAGAIN); | ||
| 1358 | /* on failure: retry once again after a requested rescan */ | ||
| 1359 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 1359 | do { | 1360 | do { |
| 1360 | rc = _zcrypt_send_cprb(perms, &xcRB); | 1361 | rc = _zcrypt_send_cprb(perms, &xcRB); |
| 1361 | } while (rc == -EAGAIN); | 1362 | } while (rc == -EAGAIN); |
| 1362 | /* on failure: retry once again after a requested rescan */ | 1363 | if (rc) |
| 1363 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | 1364 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n", |
| 1364 | do { | 1365 | rc, xcRB.status); |
| 1365 | rc = _zcrypt_send_cprb(perms, &xcRB); | 1366 | if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) |
| 1366 | } while (rc == -EAGAIN); | 1367 | return -EFAULT; |
| 1367 | if (rc) | 1368 | return rc; |
| 1368 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n", | 1369 | } |
| 1369 | rc, xcRB.status); | ||
| 1370 | if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) | ||
| 1371 | return -EFAULT; | ||
| 1372 | return rc; | ||
| 1373 | } | ||
| 1374 | case ZSENDEP11CPRB: { | ||
| 1375 | struct ep11_urb __user *uxcrb = (void __user *)arg; | ||
| 1376 | struct ep11_urb xcrb; | ||
| 1377 | 1370 | ||
| 1378 | if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) | 1371 | static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg) |
| 1379 | return -EFAULT; | 1372 | { |
| 1373 | int rc; | ||
| 1374 | struct ep11_urb xcrb; | ||
| 1375 | struct ep11_urb __user *uxcrb = (void __user *)arg; | ||
| 1376 | |||
| 1377 | if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) | ||
| 1378 | return -EFAULT; | ||
| 1379 | do { | ||
| 1380 | rc = _zcrypt_send_ep11_cprb(perms, &xcrb); | ||
| 1381 | } while (rc == -EAGAIN); | ||
| 1382 | /* on failure: retry once again after a requested rescan */ | ||
| 1383 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 1380 | do { | 1384 | do { |
| 1381 | rc = _zcrypt_send_ep11_cprb(perms, &xcrb); | 1385 | rc = _zcrypt_send_ep11_cprb(perms, &xcrb); |
| 1382 | } while (rc == -EAGAIN); | 1386 | } while (rc == -EAGAIN); |
| 1383 | /* on failure: retry once again after a requested rescan */ | 1387 | if (rc) |
| 1384 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | 1388 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc); |
| 1385 | do { | 1389 | if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) |
| 1386 | rc = _zcrypt_send_ep11_cprb(perms, &xcrb); | 1390 | return -EFAULT; |
| 1387 | } while (rc == -EAGAIN); | 1391 | return rc; |
| 1388 | if (rc) | 1392 | } |
| 1389 | ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc); | 1393 | |
| 1390 | if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) | 1394 | static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, |
| 1391 | return -EFAULT; | 1395 | unsigned long arg) |
| 1396 | { | ||
| 1397 | int rc; | ||
| 1398 | struct ap_perms *perms = | ||
| 1399 | (struct ap_perms *) filp->private_data; | ||
| 1400 | |||
| 1401 | rc = zcrypt_check_ioctl(perms, cmd); | ||
| 1402 | if (rc) | ||
| 1392 | return rc; | 1403 | return rc; |
| 1393 | } | 1404 | |
| 1405 | switch (cmd) { | ||
| 1406 | case ICARSAMODEXPO: | ||
| 1407 | return icarsamodexpo_ioctl(perms, arg); | ||
| 1408 | case ICARSACRT: | ||
| 1409 | return icarsacrt_ioctl(perms, arg); | ||
| 1410 | case ZSECSENDCPRB: | ||
| 1411 | return zsecsendcprb_ioctl(perms, arg); | ||
| 1412 | case ZSENDEP11CPRB: | ||
| 1413 | return zsendep11cprb_ioctl(perms, arg); | ||
| 1394 | case ZCRYPT_DEVICE_STATUS: { | 1414 | case ZCRYPT_DEVICE_STATUS: { |
| 1395 | struct zcrypt_device_status_ext *device_status; | 1415 | struct zcrypt_device_status_ext *device_status; |
| 1396 | size_t total_size = MAX_ZDEV_ENTRIES_EXT | 1416 | size_t total_size = MAX_ZDEV_ENTRIES_EXT |
| @@ -205,9 +205,9 @@ static int alloc_and_prep_cprbmem(size_t paramblen, · 204 unmodified lines | |||
| 205 | preqcblk->rpl_msgbl = cprbplusparamblen; | 205 | preqcblk->rpl_msgbl = cprbplusparamblen; |
| 206 | if (paramblen) { | 206 | if (paramblen) { |
| 207 | preqcblk->req_parmb = | 207 | preqcblk->req_parmb = |
| 208 | ((u8 *) preqcblk) + sizeof(struct CPRBX); | 208 | ((u8 __user *) preqcblk) + sizeof(struct CPRBX); |
| 209 | preqcblk->rpl_parmb = | 209 | preqcblk->rpl_parmb = |
| 210 | ((u8 *) prepcblk) + sizeof(struct CPRBX); | 210 | ((u8 __user *) prepcblk) + sizeof(struct CPRBX); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | *pcprbmem = cprbmem; | 213 | *pcprbmem = cprbmem; |
| @@ -274,7 +274,7 @@ int cca_genseckey(u16 cardnr, u16 domain, · 60 unmodified lines | |||
| 274 | { | 274 | { |
| 275 | int i, rc, keysize; | 275 | int i, rc, keysize; |
| 276 | int seckeysize; | 276 | int seckeysize; |
| 277 | u8 *mem; | 277 | u8 *mem, *ptr; |
| 278 | struct CPRBX *preqcblk, *prepcblk; | 278 | struct CPRBX *preqcblk, *prepcblk; |
| 279 | struct ica_xcRB xcrb; | 279 | struct ica_xcRB xcrb; |
| 280 | struct kgreqparm { | 280 | struct kgreqparm { |
| @@ -320,7 +320,7 @@ int cca_genseckey(u16 cardnr, u16 domain, · 39 unmodified lines | |||
| 320 | preqcblk->domain = domain; | 320 | preqcblk->domain = domain; |
| 321 | 321 | ||
| 322 | /* fill request cprb param block with KG request */ | 322 | /* fill request cprb param block with KG request */ |
| 323 | preqparm = (struct kgreqparm *) preqcblk->req_parmb; | 323 | preqparm = (struct kgreqparm __force *) preqcblk->req_parmb; |
| 324 | memcpy(preqparm->subfunc_code, "KG", 2); | 324 | memcpy(preqparm->subfunc_code, "KG", 2); |
| 325 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); | 325 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); |
| 326 | preqparm->lv1.len = sizeof(struct lv1); | 326 | preqparm->lv1.len = sizeof(struct lv1); |
| @@ -377,8 +377,9 @@ int cca_genseckey(u16 cardnr, u16 domain, · 50 unmodified lines | |||
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | /* process response cprb param block */ | 379 | /* process response cprb param block */ |
| 380 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 380 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 381 | prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; | 381 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 382 | prepparm = (struct kgrepparm *) ptr; | ||
| 382 | 383 | ||
| 383 | /* check length of the returned secure key token */ | 384 | /* check length of the returned secure key token */ |
| 384 | seckeysize = prepparm->lv3.keyblock.toklen | 385 | seckeysize = prepparm->lv3.keyblock.toklen |
| @@ -415,7 +416,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, · 30 unmodified lines | |||
| 415 | const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) | 416 | const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) |
| 416 | { | 417 | { |
| 417 | int rc, keysize, seckeysize; | 418 | int rc, keysize, seckeysize; |
| 418 | u8 *mem; | 419 | u8 *mem, *ptr; |
| 419 | struct CPRBX *preqcblk, *prepcblk; | 420 | struct CPRBX *preqcblk, *prepcblk; |
| 420 | struct ica_xcRB xcrb; | 421 | struct ica_xcRB xcrb; |
| 421 | struct cmreqparm { | 422 | struct cmreqparm { |
| @@ -460,7 +461,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, · 38 unmodified lines | |||
| 460 | preqcblk->domain = domain; | 461 | preqcblk->domain = domain; |
| 461 | 462 | ||
| 462 | /* fill request cprb param block with CM request */ | 463 | /* fill request cprb param block with CM request */ |
| 463 | preqparm = (struct cmreqparm *) preqcblk->req_parmb; | 464 | preqparm = (struct cmreqparm __force *) preqcblk->req_parmb; |
| 464 | memcpy(preqparm->subfunc_code, "CM", 2); | 465 | memcpy(preqparm->subfunc_code, "CM", 2); |
| 465 | memcpy(preqparm->rule_array, "AES ", 8); | 466 | memcpy(preqparm->rule_array, "AES ", 8); |
| 466 | preqparm->rule_array_len = | 467 | preqparm->rule_array_len = |
| @@ -514,8 +515,9 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, · 47 unmodified lines | |||
| 514 | } | 515 | } |
| 515 | 516 | ||
| 516 | /* process response cprb param block */ | 517 | /* process response cprb param block */ |
| 517 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 518 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 518 | prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; | 519 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 520 | prepparm = (struct cmrepparm *) ptr; | ||
| 519 | 521 | ||
| 520 | /* check length of the returned secure key token */ | 522 | /* check length of the returned secure key token */ |
| 521 | seckeysize = prepparm->lv3.keyblock.toklen | 523 | seckeysize = prepparm->lv3.keyblock.toklen |
| @@ -554,7 +556,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, · 32 unmodified lines | |||
| 554 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | 556 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
| 555 | { | 557 | { |
| 556 | int rc; | 558 | int rc; |
| 557 | u8 *mem; | 559 | u8 *mem, *ptr; |
| 558 | struct CPRBX *preqcblk, *prepcblk; | 560 | struct CPRBX *preqcblk, *prepcblk; |
| 559 | struct ica_xcRB xcrb; | 561 | struct ica_xcRB xcrb; |
| 560 | struct uskreqparm { | 562 | struct uskreqparm { |
| @@ -605,7 +607,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, · 44 unmodified lines | |||
| 605 | preqcblk->domain = domain; | 607 | preqcblk->domain = domain; |
| 606 | 608 | ||
| 607 | /* fill request cprb param block with USK request */ | 609 | /* fill request cprb param block with USK request */ |
| 608 | preqparm = (struct uskreqparm *) preqcblk->req_parmb; | 610 | preqparm = (struct uskreqparm __force *) preqcblk->req_parmb; |
| 609 | memcpy(preqparm->subfunc_code, "US", 2); | 611 | memcpy(preqparm->subfunc_code, "US", 2); |
| 610 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); | 612 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); |
| 611 | preqparm->lv1.len = sizeof(struct lv1); | 613 | preqparm->lv1.len = sizeof(struct lv1); |
| @@ -646,8 +648,9 @@ int cca_sec2protkey(u16 cardnr, u16 domain, · 34 unmodified lines | |||
| 646 | } | 648 | } |
| 647 | 649 | ||
| 648 | /* process response cprb param block */ | 650 | /* process response cprb param block */ |
| 649 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 651 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 650 | prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; | 652 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 653 | prepparm = (struct uskrepparm *) ptr; | ||
| 651 | 654 | ||
| 652 | /* check the returned keyblock */ | 655 | /* check the returned keyblock */ |
| 653 | if (prepparm->lv3.ckb.version != 0x01 && | 656 | if (prepparm->lv3.ckb.version != 0x01 && |
| @@ -714,7 +717,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, · 60 unmodified lines | |||
| 714 | u8 *keybuf, size_t *keybufsize) | 717 | u8 *keybuf, size_t *keybufsize) |
| 715 | { | 718 | { |
| 716 | int rc; | 719 | int rc; |
| 717 | u8 *mem; | 720 | u8 *mem, *ptr; |
| 718 | struct CPRBX *preqcblk, *prepcblk; | 721 | struct CPRBX *preqcblk, *prepcblk; |
| 719 | struct ica_xcRB xcrb; | 722 | struct ica_xcRB xcrb; |
| 720 | struct gkreqparm { | 723 | struct gkreqparm { |
| @@ -796,7 +799,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, · 75 unmodified lines | |||
| 796 | preqcblk->req_parml = sizeof(struct gkreqparm); | 799 | preqcblk->req_parml = sizeof(struct gkreqparm); |
| 797 | 800 | ||
| 798 | /* prepare request param block with GK request */ | 801 | /* prepare request param block with GK request */ |
| 799 | preqparm = (struct gkreqparm *) preqcblk->req_parmb; | 802 | preqparm = (struct gkreqparm __force *) preqcblk->req_parmb; |
| 800 | memcpy(preqparm->subfunc_code, "GK", 2); | 803 | memcpy(preqparm->subfunc_code, "GK", 2); |
| 801 | preqparm->rule_array_len = sizeof(uint16_t) + 2 * 8; | 804 | preqparm->rule_array_len = sizeof(uint16_t) + 2 * 8; |
| 802 | memcpy(preqparm->rule_array, "AES OP ", 2*8); | 805 | memcpy(preqparm->rule_array, "AES OP ", 2*8); |
| @@ -867,8 +870,9 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, · 64 unmodified lines | |||
| 867 | } | 870 | } |
| 868 | 871 | ||
| 869 | /* process response cprb param block */ | 872 | /* process response cprb param block */ |
| 870 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 873 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 871 | prepparm = (struct gkrepparm *) prepcblk->rpl_parmb; | 874 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 875 | prepparm = (struct gkrepparm *) ptr; | ||
| 872 | 876 | ||
| 873 | /* do some plausibility checks on the key block */ | 877 | /* do some plausibility checks on the key block */ |
| 874 | if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) || | 878 | if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) || |
| @@ -917,7 +921,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain, · 42 unmodified lines | |||
| 917 | int *key_token_size) | 921 | int *key_token_size) |
| 918 | { | 922 | { |
| 919 | int rc, n; | 923 | int rc, n; |
| 920 | u8 *mem; | 924 | u8 *mem, *ptr; |
| 921 | struct CPRBX *preqcblk, *prepcblk; | 925 | struct CPRBX *preqcblk, *prepcblk; |
| 922 | struct ica_xcRB xcrb; | 926 | struct ica_xcRB xcrb; |
| 923 | struct rule_array_block { | 927 | struct rule_array_block { |
| @@ -974,7 +978,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain, · 50 unmodified lines | |||
| 974 | preqcblk->req_parml = 0; | 978 | preqcblk->req_parml = 0; |
| 975 | 979 | ||
| 976 | /* prepare request param block with IP request */ | 980 | /* prepare request param block with IP request */ |
| 977 | preq_ra_block = (struct rule_array_block *) preqcblk->req_parmb; | 981 | preq_ra_block = (struct rule_array_block __force *) preqcblk->req_parmb; |
| 978 | memcpy(preq_ra_block->subfunc_code, "IP", 2); | 982 | memcpy(preq_ra_block->subfunc_code, "IP", 2); |
| 979 | preq_ra_block->rule_array_len = sizeof(uint16_t) + 2 * 8; | 983 | preq_ra_block->rule_array_len = sizeof(uint16_t) + 2 * 8; |
| 980 | memcpy(preq_ra_block->rule_array, rule_array_1, 8); | 984 | memcpy(preq_ra_block->rule_array, rule_array_1, 8); |
| @@ -987,7 +991,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain, · 6 unmodified lines | |||
| 987 | } | 991 | } |
| 988 | 992 | ||
| 989 | /* prepare vud block */ | 993 | /* prepare vud block */ |
| 990 | preq_vud_block = (struct vud_block *) | 994 | preq_vud_block = (struct vud_block __force *) |
| 991 | (preqcblk->req_parmb + preqcblk->req_parml); | 995 | (preqcblk->req_parmb + preqcblk->req_parml); |
| 992 | n = complete ? 0 : (clr_key_bit_size + 7) / 8; | 996 | n = complete ? 0 : (clr_key_bit_size + 7) / 8; |
| 993 | preq_vud_block->len = sizeof(struct vud_block) + n; | 997 | preq_vud_block->len = sizeof(struct vud_block) + n; |
| @@ -1001,7 +1005,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain, · 7 unmodified lines | |||
| 1001 | preqcblk->req_parml += preq_vud_block->len; | 1005 | preqcblk->req_parml += preq_vud_block->len; |
| 1002 | 1006 | ||
| 1003 | /* prepare key block */ | 1007 | /* prepare key block */ |
| 1004 | preq_key_block = (struct key_block *) | 1008 | preq_key_block = (struct key_block __force *) |
| 1005 | (preqcblk->req_parmb + preqcblk->req_parml); | 1009 | (preqcblk->req_parmb + preqcblk->req_parml); |
| 1006 | n = *key_token_size; | 1010 | n = *key_token_size; |
| 1007 | preq_key_block->len = sizeof(struct key_block) + n; | 1011 | preq_key_block->len = sizeof(struct key_block) + n; |
| @@ -1034,8 +1038,9 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain, · 26 unmodified lines | |||
| 1034 | } | 1038 | } |
| 1035 | 1039 | ||
| 1036 | /* process response cprb param block */ | 1040 | /* process response cprb param block */ |
| 1037 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 1041 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 1038 | prepparm = (struct iprepparm *) prepcblk->rpl_parmb; | 1042 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 1043 | prepparm = (struct iprepparm *) ptr; | ||
| 1039 | 1044 | ||
| 1040 | /* do some plausibility checks on the key block */ | 1045 | /* do some plausibility checks on the key block */ |
| 1041 | if (prepparm->kb.len < 120 + 3 * sizeof(uint16_t) || | 1046 | if (prepparm->kb.len < 120 + 3 * sizeof(uint16_t) || |
| @@ -1151,7 +1156,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, · 109 unmodified lines | |||
| 1151 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | 1156 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
| 1152 | { | 1157 | { |
| 1153 | int rc; | 1158 | int rc; |
| 1154 | u8 *mem; | 1159 | u8 *mem, *ptr; |
| 1155 | struct CPRBX *preqcblk, *prepcblk; | 1160 | struct CPRBX *preqcblk, *prepcblk; |
| 1156 | struct ica_xcRB xcrb; | 1161 | struct ica_xcRB xcrb; |
| 1157 | struct aureqparm { | 1162 | struct aureqparm { |
| @@ -1208,7 +1213,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, · 50 unmodified lines | |||
| 1208 | preqcblk->domain = domain; | 1213 | preqcblk->domain = domain; |
| 1209 | 1214 | ||
| 1210 | /* fill request cprb param block with AU request */ | 1215 | /* fill request cprb param block with AU request */ |
| 1211 | preqparm = (struct aureqparm *) preqcblk->req_parmb; | 1216 | preqparm = (struct aureqparm __force *) preqcblk->req_parmb; |
| 1212 | memcpy(preqparm->subfunc_code, "AU", 2); | 1217 | memcpy(preqparm->subfunc_code, "AU", 2); |
| 1213 | preqparm->rule_array_len = | 1218 | preqparm->rule_array_len = |
| 1214 | sizeof(preqparm->rule_array_len) | 1219 | sizeof(preqparm->rule_array_len) |
| @@ -1257,8 +1262,9 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, · 42 unmodified lines | |||
| 1257 | } | 1262 | } |
| 1258 | 1263 | ||
| 1259 | /* process response cprb param block */ | 1264 | /* process response cprb param block */ |
| 1260 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 1265 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 1261 | prepparm = (struct aurepparm *) prepcblk->rpl_parmb; | 1266 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 1267 | prepparm = (struct aurepparm *) ptr; | ||
| 1262 | 1268 | ||
| 1263 | /* check the returned keyblock */ | 1269 | /* check the returned keyblock */ |
| 1264 | if (prepparm->vud.ckb.version != 0x01 && | 1270 | if (prepparm->vud.ckb.version != 0x01 && |
| @@ -1347,7 +1353,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, · 82 unmodified lines | |||
| 1347 | preqcblk->domain = domain; | 1353 | preqcblk->domain = domain; |
| 1348 | 1354 | ||
| 1349 | /* fill request cprb param block with FQ request */ | 1355 | /* fill request cprb param block with FQ request */ |
| 1350 | preqparm = (struct fqreqparm *) preqcblk->req_parmb; | 1356 | preqparm = (struct fqreqparm __force *) preqcblk->req_parmb; |
| 1351 | memcpy(preqparm->subfunc_code, "FQ", 2); | 1357 | memcpy(preqparm->subfunc_code, "FQ", 2); |
| 1352 | memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); | 1358 | memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); |
| 1353 | preqparm->rule_array_len = | 1359 | preqparm->rule_array_len = |
| @@ -1378,8 +1384,9 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, · 24 unmodified lines | |||
| 1378 | } | 1384 | } |
| 1379 | 1385 | ||
| 1380 | /* process response cprb param block */ | 1386 | /* process response cprb param block */ |
| 1381 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 1387 | ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
| 1382 | prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; | 1388 | prepcblk->rpl_parmb = (u8 __user *) ptr; |
| 1389 | prepparm = (struct fqrepparm *) ptr; | ||
| 1383 | ptr = prepparm->lvdata; | 1390 | ptr = prepparm->lvdata; |
| 1384 | 1391 | ||
| 1385 | /* check and possibly copy reply rule array */ | 1392 | /* check and possibly copy reply rule array */ |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | #include "zcrypt_msgtype6.h" | 25 | #include "zcrypt_msgtype6.h" |
| 26 | #include "zcrypt_cex2c.h" | 26 | #include "zcrypt_cex2c.h" |
| 27 | #include "zcrypt_cca_key.h" | 27 | #include "zcrypt_cca_key.h" |
| 28 | #include "zcrypt_ccamisc.h" | ||
| 28 | 29 | ||
| 29 | #define CEX2C_MIN_MOD_SIZE 16 /* 128 bits */ | 30 | #define CEX2C_MIN_MOD_SIZE 16 /* 128 bits */ |
| 30 | #define CEX2C_MAX_MOD_SIZE 256 /* 2048 bits */ | 31 | #define CEX2C_MAX_MOD_SIZE 256 /* 2048 bits */ |
| @@ -58,6 +59,91 @@ static struct ap_device_id zcrypt_cex2c_queue_ids[] = { · 27 unmodified lines | |||
| 58 | 59 | ||
| 59 | MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_queue_ids); | 60 | MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_queue_ids); |
| 60 | 61 | ||
| 62 | /* | ||
| 63 | * CCA card additional device attributes | ||
| 64 | */ | ||
| 65 | static ssize_t cca_serialnr_show(struct device *dev, | ||
| 66 | struct device_attribute *attr, | ||
| 67 | char *buf) | ||
| 68 | { | ||
| 69 | struct cca_info ci; | ||
| 70 | struct ap_card *ac = to_ap_card(dev); | ||
| 71 | struct zcrypt_card *zc = ac->private; | ||
| 72 | |||
| 73 | memset(&ci, 0, sizeof(ci)); | ||
| 74 | |||
| 75 | if (ap_domain_index >= 0) | ||
| 76 | cca_get_info(ac->id, ap_domain_index, &ci, zc->online); | ||
| 77 | |||
| 78 | return scnprintf(buf, PAGE_SIZE, "%s\n", ci.serial); | ||
| 79 | } | ||
| 80 | |||
| 81 | static struct device_attribute dev_attr_cca_serialnr = | ||
| 82 | __ATTR(serialnr, 0444, cca_serialnr_show, NULL); | ||
| 83 | |||
| 84 | static struct attribute *cca_card_attrs[] = { | ||
| 85 | &dev_attr_cca_serialnr.attr, | ||
| 86 | NULL, | ||
| 87 | }; | ||
| 88 | |||
| 89 | static const struct attribute_group cca_card_attr_grp = { | ||
| 90 | .attrs = cca_card_attrs, | ||
| 91 | }; | ||
| 92 | |||
| 93 | /* | ||
| 94 | * CCA queue additional device attributes | ||
| 95 | */ | ||
| 96 | static ssize_t cca_mkvps_show(struct device *dev, | ||
| 97 | struct device_attribute *attr, | ||
| 98 | char *buf) | ||
| 99 | { | ||
| 100 | int n = 0; | ||
| 101 | struct cca_info ci; | ||
| 102 | struct zcrypt_queue *zq = to_ap_queue(dev)->private; | ||
| 103 | static const char * const cao_state[] = { "invalid", "valid" }; | ||
| 104 | static const char * const new_state[] = { "empty", "partial", "full" }; | ||
| 105 | |||
| 106 | memset(&ci, 0, sizeof(ci)); | ||
| 107 | |||
| 108 | cca_get_info(AP_QID_CARD(zq->queue->qid), | ||
| 109 | AP_QID_QUEUE(zq->queue->qid), | ||
| 110 | &ci, zq->online); | ||
| 111 | |||
| 112 | if (ci.new_mk_state >= '1' && ci.new_mk_state <= '3') | ||
| 113 | n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n", | ||
| 114 | new_state[ci.new_mk_state - '1'], ci.new_mkvp); | ||
| 115 | else | ||
| 116 | n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n"); | ||
| 117 | |||
| 118 | if (ci.cur_mk_state >= '1' && ci.cur_mk_state <= '2') | ||
| 119 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 120 | "AES CUR: %s 0x%016llx\n", | ||
| 121 | cao_state[ci.cur_mk_state - '1'], ci.cur_mkvp); | ||
| 122 | else | ||
| 123 | n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n"); | ||
| 124 | |||
| 125 | if (ci.old_mk_state >= '1' && ci.old_mk_state <= '2') | ||
| 126 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
| 127 | "AES OLD: %s 0x%016llx\n", | ||
| 128 | cao_state[ci.old_mk_state - '1'], ci.old_mkvp); | ||
| 129 | else | ||
| 130 | n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n"); | ||
| 131 | |||
| 132 | return n; | ||
| 133 | } | ||
| 134 | |||
| 135 | static struct device_attribute dev_attr_cca_mkvps = | ||
| 136 | __ATTR(mkvps, 0444, cca_mkvps_show, NULL); | ||
| 137 | |||
| 138 | static struct attribute *cca_queue_attrs[] = { | ||
| 139 | &dev_attr_cca_mkvps.attr, | ||
| 140 | NULL, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static const struct attribute_group cca_queue_attr_grp = { | ||
| 144 | .attrs = cca_queue_attrs, | ||
| 145 | }; | ||
| 146 | |||
| 61 | /** | 147 | /** |
| 62 | * Large random number detection function. Its sends a message to a CEX2C/CEX3C | 148 | * Large random number detection function. Its sends a message to a CEX2C/CEX3C |
| 63 | * card to find out if large random numbers are supported. | 149 | * card to find out if large random numbers are supported. |
| @@ -87,24 +173,23 @@ static int zcrypt_cex2c_rng_supported(struct ap_queue *aq) · 23 unmodified lines | |||
| 87 | int rc, i; | 173 | int rc, i; |
| 88 | 174 | ||
| 89 | ap_init_message(&ap_msg); | 175 | ap_init_message(&ap_msg); |
| 90 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 176 | ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); |
| 91 | if (!ap_msg.message) | 177 | if (!ap_msg.msg) |
| 92 | return -ENOMEM; | 178 | return -ENOMEM; |
| 93 | 179 | ||
| 94 | rng_type6CPRB_msgX(&ap_msg, 4, &domain); | 180 | rng_type6CPRB_msgX(&ap_msg, 4, &domain); |
| 95 | 181 | ||
| 96 | msg = ap_msg.message; | 182 | msg = ap_msg.msg; |
| 97 | msg->cprbx.domain = AP_QID_QUEUE(aq->qid); | 183 | msg->cprbx.domain = AP_QID_QUEUE(aq->qid); |
| 98 | 184 | ||
| 99 | rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.message, | 185 | rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.msg, ap_msg.len); |
| 100 | ap_msg.length); | ||
| 101 | if (rc) | 186 | if (rc) |
| 102 | goto out_free; | 187 | goto out_free; |
| 103 | 188 | ||
| 104 | /* Wait for the test message to complete. */ | 189 | /* Wait for the test message to complete. */ |
| 105 | for (i = 0; i < 2 * HZ; i++) { | 190 | for (i = 0; i < 2 * HZ; i++) { |
| 106 | msleep(1000 / HZ); | 191 | msleep(1000 / HZ); |
| 107 | rc = ap_recv(aq->qid, &psmid, ap_msg.message, 4096); | 192 | rc = ap_recv(aq->qid, &psmid, ap_msg.msg, 4096); |
| 108 | if (rc == 0 && psmid == 0x0102030405060708ULL) | 193 | if (rc == 0 && psmid == 0x0102030405060708ULL) |
| 109 | break; | 194 | break; |
| 110 | } | 195 | } |
| @@ -115,13 +200,13 @@ static int zcrypt_cex2c_rng_supported(struct ap_queue *aq) · 4 unmodified lines | |||
| 115 | goto out_free; | 200 | goto out_free; |
| 116 | } | 201 | } |
| 117 | 202 | ||
| 118 | reply = ap_msg.message; | 203 | reply = ap_msg.msg; |
| 119 | if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0) | 204 | if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0) |
| 120 | rc = 1; | 205 | rc = 1; |
| 121 | else | 206 | else |
| 122 | rc = 0; | 207 | rc = 0; |
| 123 | out_free: | 208 | out_free: |
| 124 | free_page((unsigned long) ap_msg.message); | 209 | free_page((unsigned long) ap_msg.msg); |
| 125 | return rc; | 210 | return rc; |
| 126 | } | 211 | } |
| 127 | 212 | ||
| @@ -179,6 +264,17 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) · 51 unmodified lines | |||
| 179 | if (rc) { | 264 | if (rc) { |
| 180 | ac->private = NULL; | 265 | ac->private = NULL; |
| 181 | zcrypt_card_free(zc); | 266 | zcrypt_card_free(zc); |
| 267 | return rc; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { | ||
| 271 | rc = sysfs_create_group(&ap_dev->device.kobj, | ||
| 272 | &cca_card_attr_grp); | ||
| 273 | if (rc) { | ||
| 274 | zcrypt_card_unregister(zc); | ||
| 275 | ac->private = NULL; | ||
| 276 | zcrypt_card_free(zc); | ||
| 277 | } | ||
| 182 | } | 278 | } |
| 183 | 279 | ||
| 184 | return rc; | 280 | return rc; |
| @@ -190,8 +286,11 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) · 5 unmodified lines | |||
| 190 | */ | 286 | */ |
| 191 | static void zcrypt_cex2c_card_remove(struct ap_device *ap_dev) | 287 | static void zcrypt_cex2c_card_remove(struct ap_device *ap_dev) |
| 192 | { | 288 | { |
| 289 | struct ap_card *ac = to_ap_card(&ap_dev->device); | ||
| 193 | struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private; | 290 | struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private; |
| 194 | 291 | ||
| 292 | if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) | ||
| 293 | sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp); | ||
| 195 | if (zc) | 294 | if (zc) |
| 196 | zcrypt_card_unregister(zc); | 295 | zcrypt_card_unregister(zc); |
| 197 | } | 296 | } |
| @@ -240,7 +339,19 @@ static int zcrypt_cex2c_queue_probe(struct ap_device *ap_dev) · 42 unmodified lines | |||
| 240 | if (rc) { | 339 | if (rc) { |
| 241 | aq->private = NULL; | 340 | aq->private = NULL; |
| 242 | zcrypt_queue_free(zq); | 341 | zcrypt_queue_free(zq); |
| 342 | return rc; | ||
| 343 | } | ||
| 344 | |||
| 345 | if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { | ||
| 346 | rc = sysfs_create_group(&ap_dev->device.kobj, | ||
| 347 | &cca_queue_attr_grp); | ||
| 348 | if (rc) { | ||
| 349 | zcrypt_queue_unregister(zq); | ||
| 350 | aq->private = NULL; | ||
| 351 | zcrypt_queue_free(zq); | ||
| 352 | } | ||
| 243 | } | 353 | } |
| 354 | |||
| 244 | return rc; | 355 | return rc; |
| 245 | } | 356 | } |
| 246 | 357 | ||
| @@ -253,6 +364,8 @@ static void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev) · 6 unmodified lines | |||
| 253 | struct ap_queue *aq = to_ap_queue(&ap_dev->device); | 364 | struct ap_queue *aq = to_ap_queue(&ap_dev->device); |
| 254 | struct zcrypt_queue *zq = aq->private; | 365 | struct zcrypt_queue *zq = aq->private; |
| 255 | 366 | ||
| 367 | if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) | ||
| 368 | sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp); | ||
| 256 | if (zq) | 369 | if (zq) |
| 257 | zcrypt_queue_unregister(zq); | 370 | zcrypt_queue_unregister(zq); |
| 258 | } | 371 | } |
| @@ -250,7 +250,7 @@ static ssize_t ep11_card_op_modes_show(struct device *dev, · 249 unmodified lines | |||
| 250 | ep11_get_card_info(ac->id, &ci, zc->online); | 250 | ep11_get_card_info(ac->id, &ci, zc->online); |
| 251 | 251 | ||
| 252 | for (i = 0; ep11_op_modes[i].mode_txt; i++) { | 252 | for (i = 0; ep11_op_modes[i].mode_txt; i++) { |
| 253 | if (ci.op_mode & (1 << ep11_op_modes[i].mode_bit)) { | 253 | if (ci.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) { |
| 254 | if (n > 0) | 254 | if (n > 0) |
| 255 | buf[n++] = ' '; | 255 | buf[n++] = ' '; |
| 256 | n += scnprintf(buf + n, PAGE_SIZE - n, | 256 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| @@ -345,7 +345,7 @@ static ssize_t ep11_queue_op_modes_show(struct device *dev, · 88 unmodified lines | |||
| 345 | &di); | 345 | &di); |
| 346 | 346 | ||
| 347 | for (i = 0; ep11_op_modes[i].mode_txt; i++) { | 347 | for (i = 0; ep11_op_modes[i].mode_txt; i++) { |
| 348 | if (di.op_mode & (1 << ep11_op_modes[i].mode_bit)) { | 348 | if (di.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) { |
| 349 | if (n > 0) | 349 | if (n > 0) |
| 350 | buf[n++] = ' '; | 350 | buf[n++] = ' '; |
| 351 | n += scnprintf(buf + n, PAGE_SIZE - n, | 351 | n += scnprintf(buf + n, PAGE_SIZE - n, |
| @@ -529,22 +529,27 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) · 177 unmodified lines | |||
| 529 | if (rc) { | 529 | if (rc) { |
| 530 | ac->private = NULL; | 530 | ac->private = NULL; |
| 531 | zcrypt_card_free(zc); | 531 | zcrypt_card_free(zc); |
| 532 | goto out; | 532 | return rc; |
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { | 535 | if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { |
| 536 | rc = sysfs_create_group(&ap_dev->device.kobj, | 536 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 537 | &cca_card_attr_grp); | 537 | &cca_card_attr_grp); |
| 538 | if (rc) | 538 | if (rc) { |
| 539 | zcrypt_card_unregister(zc); | 539 | zcrypt_card_unregister(zc); |
| 540 | ac->private = NULL; | ||
| 541 | zcrypt_card_free(zc); | ||
| 542 | } | ||
| 540 | } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) { | 543 | } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) { |
| 541 | rc = sysfs_create_group(&ap_dev->device.kobj, | 544 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 542 | &ep11_card_attr_grp); | 545 | &ep11_card_attr_grp); |
| 543 | if (rc) | 546 | if (rc) { |
| 544 | zcrypt_card_unregister(zc); | 547 | zcrypt_card_unregister(zc); |
| 548 | ac->private = NULL; | ||
| 549 | zcrypt_card_free(zc); | ||
| 550 | } | ||
| 545 | } | 551 | } |
| 546 | 552 | ||
| 547 | out: | ||
| 548 | return rc; | 553 | return rc; |
| 549 | } | 554 | } |
| 550 | 555 | ||
| @@ -617,22 +622,27 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev) · 66 unmodified lines | |||
| 617 | if (rc) { | 622 | if (rc) { |
| 618 | aq->private = NULL; | 623 | aq->private = NULL; |
| 619 | zcrypt_queue_free(zq); | 624 | zcrypt_queue_free(zq); |
| 620 | goto out; | 625 | return rc; |
| 621 | } | 626 | } |
| 622 | 627 | ||
| 623 | if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { | 628 | if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { |
| 624 | rc = sysfs_create_group(&ap_dev->device.kobj, | 629 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 625 | &cca_queue_attr_grp); | 630 | &cca_queue_attr_grp); |
| 626 | if (rc) | 631 | if (rc) { |
| 627 | zcrypt_queue_unregister(zq); | 632 | zcrypt_queue_unregister(zq); |
| 633 | aq->private = NULL; | ||
| 634 | zcrypt_queue_free(zq); | ||
| 635 | } | ||
| 628 | } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) { | 636 | } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) { |
| 629 | rc = sysfs_create_group(&ap_dev->device.kobj, | 637 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 630 | &ep11_queue_attr_grp); | 638 | &ep11_queue_attr_grp); |
| 631 | if (rc) | 639 | if (rc) { |
| 632 | zcrypt_queue_unregister(zq); | 640 | zcrypt_queue_unregister(zq); |
| 641 | aq->private = NULL; | ||
| 642 | zcrypt_queue_free(zq); | ||
| 643 | } | ||
| 633 | } | 644 | } |
| 634 | 645 | ||
| 635 | out: | ||
| 636 | return rc; | 646 | return rc; |
| 637 | } | 647 | } |
| 638 | 648 | ||
| @@ -80,7 +80,7 @@ struct error_hdr { · 79 unmodified lines | |||
| 80 | static inline int convert_error(struct zcrypt_queue *zq, | 80 | static inline int convert_error(struct zcrypt_queue *zq, |
| 81 | struct ap_message *reply) | 81 | struct ap_message *reply) |
| 82 | { | 82 | { |
| 83 | struct error_hdr *ehdr = reply->message; | 83 | struct error_hdr *ehdr = reply->msg; |
| 84 | int card = AP_QID_CARD(zq->queue->qid); | 84 | int card = AP_QID_CARD(zq->queue->qid); |
| 85 | int queue = AP_QID_QUEUE(zq->queue->qid); | 85 | int queue = AP_QID_QUEUE(zq->queue->qid); |
| 86 | 86 | ||
| @@ -127,7 +127,7 @@ static inline int convert_error(struct zcrypt_queue *zq, · 40 unmodified lines | |||
| 127 | struct { | 127 | struct { |
| 128 | struct type86_hdr hdr; | 128 | struct type86_hdr hdr; |
| 129 | struct type86_fmt2_ext fmt2; | 129 | struct type86_fmt2_ext fmt2; |
| 130 | } __packed * head = reply->message; | 130 | } __packed * head = reply->msg; |
| 131 | unsigned int apfs = *((u32 *)head->fmt2.apfs); | 131 | unsigned int apfs = *((u32 *)head->fmt2.apfs); |
| 132 | 132 | ||
| 133 | ZCRYPT_DBF(DBF_ERR, | 133 | ZCRYPT_DBF(DBF_ERR, |
| @@ -207,10 +207,10 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq, · 206 unmodified lines | |||
| 207 | mod_len = mex->inputdatalength; | 207 | mod_len = mex->inputdatalength; |
| 208 | 208 | ||
| 209 | if (mod_len <= 128) { | 209 | if (mod_len <= 128) { |
| 210 | struct type50_meb1_msg *meb1 = ap_msg->message; | 210 | struct type50_meb1_msg *meb1 = ap_msg->msg; |
| 211 | 211 | ||
| 212 | memset(meb1, 0, sizeof(*meb1)); | 212 | memset(meb1, 0, sizeof(*meb1)); |
| 213 | ap_msg->length = sizeof(*meb1); | 213 | ap_msg->len = sizeof(*meb1); |
| 214 | meb1->header.msg_type_code = TYPE50_TYPE_CODE; | 214 | meb1->header.msg_type_code = TYPE50_TYPE_CODE; |
| 215 | meb1->header.msg_len = sizeof(*meb1); | 215 | meb1->header.msg_len = sizeof(*meb1); |
| 216 | meb1->keyblock_type = TYPE50_MEB1_FMT; | 216 | meb1->keyblock_type = TYPE50_MEB1_FMT; |
| @@ -218,10 +218,10 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq, · 1 unmodified line | |||
| 218 | exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; | 218 | exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; |
| 219 | inp = meb1->message + sizeof(meb1->message) - mod_len; | 219 | inp = meb1->message + sizeof(meb1->message) - mod_len; |
| 220 | } else if (mod_len <= 256) { | 220 | } else if (mod_len <= 256) { |
| 221 | struct type50_meb2_msg *meb2 = ap_msg->message; | 221 | struct type50_meb2_msg *meb2 = ap_msg->msg; |
| 222 | 222 | ||
| 223 | memset(meb2, 0, sizeof(*meb2)); | 223 | memset(meb2, 0, sizeof(*meb2)); |
| 224 | ap_msg->length = sizeof(*meb2); | 224 | ap_msg->len = sizeof(*meb2); |
| 225 | meb2->header.msg_type_code = TYPE50_TYPE_CODE; | 225 | meb2->header.msg_type_code = TYPE50_TYPE_CODE; |
| 226 | meb2->header.msg_len = sizeof(*meb2); | 226 | meb2->header.msg_len = sizeof(*meb2); |
| 227 | meb2->keyblock_type = TYPE50_MEB2_FMT; | 227 | meb2->keyblock_type = TYPE50_MEB2_FMT; |
| @@ -229,10 +229,10 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq, · 1 unmodified line | |||
| 229 | exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; | 229 | exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; |
| 230 | inp = meb2->message + sizeof(meb2->message) - mod_len; | 230 | inp = meb2->message + sizeof(meb2->message) - mod_len; |
| 231 | } else if (mod_len <= 512) { | 231 | } else if (mod_len <= 512) { |
| 232 | struct type50_meb3_msg *meb3 = ap_msg->message; | 232 | struct type50_meb3_msg *meb3 = ap_msg->msg; |
| 233 | 233 | ||
| 234 | memset(meb3, 0, sizeof(*meb3)); | 234 | memset(meb3, 0, sizeof(*meb3)); |
| 235 | ap_msg->length = sizeof(*meb3); | 235 | ap_msg->len = sizeof(*meb3); |
| 236 | meb3->header.msg_type_code = TYPE50_TYPE_CODE; | 236 | meb3->header.msg_type_code = TYPE50_TYPE_CODE; |
| 237 | meb3->header.msg_len = sizeof(*meb3); | 237 | meb3->header.msg_len = sizeof(*meb3); |
| 238 | meb3->keyblock_type = TYPE50_MEB3_FMT; | 238 | meb3->keyblock_type = TYPE50_MEB3_FMT; |
| @@ -275,10 +275,10 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq, · 36 unmodified lines | |||
| 275 | * 512 byte modulus (4k keys). | 275 | * 512 byte modulus (4k keys). |
| 276 | */ | 276 | */ |
| 277 | if (mod_len <= 128) { /* up to 1024 bit key size */ | 277 | if (mod_len <= 128) { /* up to 1024 bit key size */ |
| 278 | struct type50_crb1_msg *crb1 = ap_msg->message; | 278 | struct type50_crb1_msg *crb1 = ap_msg->msg; |
| 279 | 279 | ||
| 280 | memset(crb1, 0, sizeof(*crb1)); | 280 | memset(crb1, 0, sizeof(*crb1)); |
| 281 | ap_msg->length = sizeof(*crb1); | 281 | ap_msg->len = sizeof(*crb1); |
| 282 | crb1->header.msg_type_code = TYPE50_TYPE_CODE; | 282 | crb1->header.msg_type_code = TYPE50_TYPE_CODE; |
| 283 | crb1->header.msg_len = sizeof(*crb1); | 283 | crb1->header.msg_len = sizeof(*crb1); |
| 284 | crb1->keyblock_type = TYPE50_CRB1_FMT; | 284 | crb1->keyblock_type = TYPE50_CRB1_FMT; |
| @@ -289,10 +289,10 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq, · 4 unmodified lines | |||
| 289 | u = crb1->u + sizeof(crb1->u) - short_len; | 289 | u = crb1->u + sizeof(crb1->u) - short_len; |
| 290 | inp = crb1->message + sizeof(crb1->message) - mod_len; | 290 | inp = crb1->message + sizeof(crb1->message) - mod_len; |
| 291 | } else if (mod_len <= 256) { /* up to 2048 bit key size */ | 291 | } else if (mod_len <= 256) { /* up to 2048 bit key size */ |
| 292 | struct type50_crb2_msg *crb2 = ap_msg->message; | 292 | struct type50_crb2_msg *crb2 = ap_msg->msg; |
| 293 | 293 | ||
| 294 | memset(crb2, 0, sizeof(*crb2)); | 294 | memset(crb2, 0, sizeof(*crb2)); |
| 295 | ap_msg->length = sizeof(*crb2); | 295 | ap_msg->len = sizeof(*crb2); |
| 296 | crb2->header.msg_type_code = TYPE50_TYPE_CODE; | 296 | crb2->header.msg_type_code = TYPE50_TYPE_CODE; |
| 297 | crb2->header.msg_len = sizeof(*crb2); | 297 | crb2->header.msg_len = sizeof(*crb2); |
| 298 | crb2->keyblock_type = TYPE50_CRB2_FMT; | 298 | crb2->keyblock_type = TYPE50_CRB2_FMT; |
| @@ -304,10 +304,10 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq, · 5 unmodified lines | |||
| 304 | inp = crb2->message + sizeof(crb2->message) - mod_len; | 304 | inp = crb2->message + sizeof(crb2->message) - mod_len; |
| 305 | } else if ((mod_len <= 512) && /* up to 4096 bit key size */ | 305 | } else if ((mod_len <= 512) && /* up to 4096 bit key size */ |
| 306 | (zq->zcard->max_mod_size == CEX3A_MAX_MOD_SIZE)) { | 306 | (zq->zcard->max_mod_size == CEX3A_MAX_MOD_SIZE)) { |
| 307 | struct type50_crb3_msg *crb3 = ap_msg->message; | 307 | struct type50_crb3_msg *crb3 = ap_msg->msg; |
| 308 | 308 | ||
| 309 | memset(crb3, 0, sizeof(*crb3)); | 309 | memset(crb3, 0, sizeof(*crb3)); |
| 310 | ap_msg->length = sizeof(*crb3); | 310 | ap_msg->len = sizeof(*crb3); |
| 311 | crb3->header.msg_type_code = TYPE50_TYPE_CODE; | 311 | crb3->header.msg_type_code = TYPE50_TYPE_CODE; |
| 312 | crb3->header.msg_len = sizeof(*crb3); | 312 | crb3->header.msg_len = sizeof(*crb3); |
| 313 | crb3->keyblock_type = TYPE50_CRB3_FMT; | 313 | crb3->keyblock_type = TYPE50_CRB3_FMT; |
| @@ -350,7 +350,7 @@ static int convert_type80(struct zcrypt_queue *zq, · 36 unmodified lines | |||
| 350 | char __user *outputdata, | 350 | char __user *outputdata, |
| 351 | unsigned int outputdatalength) | 351 | unsigned int outputdatalength) |
| 352 | { | 352 | { |
| 353 | struct type80_hdr *t80h = reply->message; | 353 | struct type80_hdr *t80h = reply->msg; |
| 354 | unsigned char *data; | 354 | unsigned char *data; |
| 355 | 355 | ||
| 356 | if (t80h->len < sizeof(*t80h) + outputdatalength) { | 356 | if (t80h->len < sizeof(*t80h) + outputdatalength) { |
| @@ -370,7 +370,7 @@ static int convert_type80(struct zcrypt_queue *zq, · 13 unmodified lines | |||
| 370 | BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); | 370 | BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); |
| 371 | else | 371 | else |
| 372 | BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); | 372 | BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); |
| 373 | data = reply->message + t80h->len - outputdatalength; | 373 | data = reply->msg + t80h->len - outputdatalength; |
| 374 | if (copy_to_user(outputdata, data, outputdatalength)) | 374 | if (copy_to_user(outputdata, data, outputdatalength)) |
| 375 | return -EFAULT; | 375 | return -EFAULT; |
| 376 | return 0; | 376 | return 0; |
| @@ -382,7 +382,7 @@ static int convert_response(struct zcrypt_queue *zq, · 5 unmodified lines | |||
| 382 | unsigned int outputdatalength) | 382 | unsigned int outputdatalength) |
| 383 | { | 383 | { |
| 384 | /* Response type byte is the second byte in the response. */ | 384 | /* Response type byte is the second byte in the response. */ |
| 385 | unsigned char rtype = ((unsigned char *) reply->message)[1]; | 385 | unsigned char rtype = ((unsigned char *) reply->msg)[1]; |
| 386 | 386 | ||
| 387 | switch (rtype) { | 387 | switch (rtype) { |
| 388 | case TYPE82_RSP_CODE: | 388 | case TYPE82_RSP_CODE: |
| @@ -422,22 +422,20 @@ static void zcrypt_cex2a_receive(struct ap_queue *aq, · 33 unmodified lines | |||
| 422 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | 422 | .reply_code = REP82_ERROR_MACHINE_FAILURE, |
| 423 | }; | 423 | }; |
| 424 | struct type80_hdr *t80h; | 424 | struct type80_hdr *t80h; |
| 425 | int length; | 425 | int len; |
| 426 | 426 | ||
| 427 | /* Copy the reply message to the request message buffer. */ | 427 | /* Copy the reply message to the request message buffer. */ |
| 428 | if (!reply) | 428 | if (!reply) |
| 429 | goto out; /* ap_msg->rc indicates the error */ | 429 | goto out; /* ap_msg->rc indicates the error */ |
| 430 | t80h = reply->message; | 430 | t80h = reply->msg; |
| 431 | if (t80h->type == TYPE80_RSP_CODE) { | 431 | if (t80h->type == TYPE80_RSP_CODE) { |
| 432 | if (aq->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) | 432 | if (aq->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) |
| 433 | length = min_t(int, | 433 | len = min_t(int, CEX2A_MAX_RESPONSE_SIZE, t80h->len); |
| 434 | CEX2A_MAX_RESPONSE_SIZE, t80h->len); | ||
| 435 | else | 434 | else |
| 436 | length = min_t(int, | 435 | len = min_t(int, CEX3A_MAX_RESPONSE_SIZE, t80h->len); |
| 437 | CEX3A_MAX_RESPONSE_SIZE, t80h->len); | 436 | memcpy(msg->msg, reply->msg, len); |
| 438 | memcpy(msg->message, reply->message, length); | ||
| 439 | } else | 437 | } else |
| 440 | memcpy(msg->message, reply->message, sizeof(error_reply)); | 438 | memcpy(msg->msg, reply->msg, sizeof(error_reply)); |
| 441 | out: | 439 | out: |
| 442 | complete((struct completion *) msg->private); | 440 | complete((struct completion *) msg->private); |
| 443 | } | 441 | } |
| @@ -460,12 +458,10 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq, · 16 unmodified lines | |||
| 460 | 458 | ||
| 461 | ap_init_message(&ap_msg); | 459 | ap_init_message(&ap_msg); |
| 462 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) | 460 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
| 463 | ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, | 461 | ap_msg.msg = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, GFP_KERNEL); |
| 464 | GFP_KERNEL); | ||
| 465 | else | 462 | else |
| 466 | ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | 463 | ap_msg.msg = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, GFP_KERNEL); |
| 467 | GFP_KERNEL); | 464 | if (!ap_msg.msg) |
| 468 | if (!ap_msg.message) | ||
| 469 | return -ENOMEM; | 465 | return -ENOMEM; |
| 470 | ap_msg.receive = zcrypt_cex2a_receive; | 466 | ap_msg.receive = zcrypt_cex2a_receive; |
| 471 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 467 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -486,7 +482,7 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq, · 14 unmodified lines | |||
| 486 | /* Signal pending. */ | 482 | /* Signal pending. */ |
| 487 | ap_cancel_message(zq->queue, &ap_msg); | 483 | ap_cancel_message(zq->queue, &ap_msg); |
| 488 | out_free: | 484 | out_free: |
| 489 | kfree(ap_msg.message); | 485 | kfree(ap_msg.msg); |
| 490 | return rc; | 486 | return rc; |
| 491 | } | 487 | } |
| 492 | 488 | ||
| @@ -506,12 +502,10 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq, · 13 unmodified lines | |||
| 506 | 502 | ||
| 507 | ap_init_message(&ap_msg); | 503 | ap_init_message(&ap_msg); |
| 508 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) | 504 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
| 509 | ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, | 505 | ap_msg.msg = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, GFP_KERNEL); |
| 510 | GFP_KERNEL); | ||
| 511 | else | 506 | else |
| 512 | ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | 507 | ap_msg.msg = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, GFP_KERNEL); |
| 513 | GFP_KERNEL); | 508 | if (!ap_msg.msg) |
| 514 | if (!ap_msg.message) | ||
| 515 | return -ENOMEM; | 509 | return -ENOMEM; |
| 516 | ap_msg.receive = zcrypt_cex2a_receive; | 510 | ap_msg.receive = zcrypt_cex2a_receive; |
| 517 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 511 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -532,7 +526,7 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq, · 14 unmodified lines | |||
| 532 | /* Signal pending. */ | 526 | /* Signal pending. */ |
| 533 | ap_cancel_message(zq->queue, &ap_msg); | 527 | ap_cancel_message(zq->queue, &ap_msg); |
| 534 | out_free: | 528 | out_free: |
| 535 | kfree(ap_msg.message); | 529 | kfree(ap_msg.msg); |
| 536 | return rc; | 530 | return rc; |
| 537 | } | 531 | } |
| 538 | 532 | ||
| @@ -266,7 +266,7 @@ static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_queue *zq, · 265 unmodified lines | |||
| 266 | struct function_and_rules_block fr; | 266 | struct function_and_rules_block fr; |
| 267 | unsigned short length; | 267 | unsigned short length; |
| 268 | char text[0]; | 268 | char text[0]; |
| 269 | } __packed * msg = ap_msg->message; | 269 | } __packed * msg = ap_msg->msg; |
| 270 | int size; | 270 | int size; |
| 271 | 271 | ||
| 272 | /* | 272 | /* |
| @@ -301,7 +301,7 @@ static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_queue *zq, · 28 unmodified lines | |||
| 301 | 301 | ||
| 302 | msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); | 302 | msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); |
| 303 | 303 | ||
| 304 | ap_msg->length = size; | 304 | ap_msg->len = size; |
| 305 | return 0; | 305 | return 0; |
| 306 | } | 306 | } |
| 307 | 307 | ||
| @@ -336,7 +336,7 @@ static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_queue *zq, · 28 unmodified lines | |||
| 336 | struct function_and_rules_block fr; | 336 | struct function_and_rules_block fr; |
| 337 | unsigned short length; | 337 | unsigned short length; |
| 338 | char text[0]; | 338 | char text[0]; |
| 339 | } __packed * msg = ap_msg->message; | 339 | } __packed * msg = ap_msg->msg; |
| 340 | int size; | 340 | int size; |
| 341 | 341 | ||
| 342 | /* | 342 | /* |
| @@ -370,7 +370,7 @@ static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_queue *zq, · 27 unmodified lines | |||
| 370 | 370 | ||
| 371 | msg->fr = static_pkd_fnr; | 371 | msg->fr = static_pkd_fnr; |
| 372 | 372 | ||
| 373 | ap_msg->length = size; | 373 | ap_msg->len = size; |
| 374 | return 0; | 374 | return 0; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| @@ -400,11 +400,11 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg, · 23 unmodified lines | |||
| 400 | struct { | 400 | struct { |
| 401 | struct type6_hdr hdr; | 401 | struct type6_hdr hdr; |
| 402 | struct CPRBX cprbx; | 402 | struct CPRBX cprbx; |
| 403 | } __packed * msg = ap_msg->message; | 403 | } __packed * msg = ap_msg->msg; |
| 404 | 404 | ||
| 405 | int rcblen = CEIL4(xcRB->request_control_blk_length); | 405 | int rcblen = CEIL4(xcRB->request_control_blk_length); |
| 406 | int replylen, req_sumlen, resp_sumlen; | 406 | int replylen, req_sumlen, resp_sumlen; |
| 407 | char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; | 407 | char *req_data = ap_msg->msg + sizeof(struct type6_hdr) + rcblen; |
| 408 | char *function_code; | 408 | char *function_code; |
| 409 | 409 | ||
| 410 | if (CEIL4(xcRB->request_control_blk_length) < | 410 | if (CEIL4(xcRB->request_control_blk_length) < |
| @@ -412,10 +412,10 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg, · 1 unmodified line | |||
| 412 | return -EINVAL; /* overflow after alignment*/ | 412 | return -EINVAL; /* overflow after alignment*/ |
| 413 | 413 | ||
| 414 | /* length checks */ | 414 | /* length checks */ |
| 415 | ap_msg->length = sizeof(struct type6_hdr) + | 415 | ap_msg->len = sizeof(struct type6_hdr) + |
| 416 | CEIL4(xcRB->request_control_blk_length) + | 416 | CEIL4(xcRB->request_control_blk_length) + |
| 417 | xcRB->request_data_length; | 417 | xcRB->request_data_length; |
| 418 | if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE) | 418 | if (ap_msg->len > MSGTYPE06_MAX_MSG_SIZE) |
| 419 | return -EINVAL; | 419 | return -EINVAL; |
| 420 | 420 | ||
| 421 | /* | 421 | /* |
| @@ -480,9 +480,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg, · 58 unmodified lines | |||
| 480 | 480 | ||
| 481 | if (memcmp(function_code, "US", 2) == 0 | 481 | if (memcmp(function_code, "US", 2) == 0 |
| 482 | || memcmp(function_code, "AU", 2) == 0) | 482 | || memcmp(function_code, "AU", 2) == 0) |
| 483 | ap_msg->special = 1; | 483 | ap_msg->flags |= AP_MSG_FLAG_SPECIAL; |
| 484 | else | ||
| 485 | ap_msg->special = 0; | ||
| 486 | 484 | ||
| 487 | /* copy data block */ | 485 | /* copy data block */ |
| 488 | if (xcRB->request_data_length && | 486 | if (xcRB->request_data_length && |
| @@ -512,7 +510,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct ap_message *ap_msg, · 23 unmodified lines | |||
| 512 | struct ep11_cprb cprbx; | 510 | struct ep11_cprb cprbx; |
| 513 | unsigned char pld_tag; /* fixed value 0x30 */ | 511 | unsigned char pld_tag; /* fixed value 0x30 */ |
| 514 | unsigned char pld_lenfmt; /* payload length format */ | 512 | unsigned char pld_lenfmt; /* payload length format */ |
| 515 | } __packed * msg = ap_msg->message; | 513 | } __packed * msg = ap_msg->msg; |
| 516 | 514 | ||
| 517 | struct pld_hdr { | 515 | struct pld_hdr { |
| 518 | unsigned char func_tag; /* fixed value 0x4 */ | 516 | unsigned char func_tag; /* fixed value 0x4 */ |
| @@ -527,7 +525,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct ap_message *ap_msg, · 8 unmodified lines | |||
| 527 | return -EINVAL; /* overflow after alignment*/ | 525 | return -EINVAL; /* overflow after alignment*/ |
| 528 | 526 | ||
| 529 | /* length checks */ | 527 | /* length checks */ |
| 530 | ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len; | 528 | ap_msg->len = sizeof(struct type6_hdr) + xcRB->req_len; |
| 531 | if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE - | 529 | if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE - |
| 532 | (sizeof(struct type6_hdr))) | 530 | (sizeof(struct type6_hdr))) |
| 533 | return -EINVAL; | 531 | return -EINVAL; |
| @@ -569,7 +567,7 @@ static int xcrb_msg_to_type6_ep11cprb_msgx(struct ap_message *ap_msg, · 35 unmodified lines | |||
| 569 | 567 | ||
| 570 | /* enable special processing based on the cprbs flags special bit */ | 568 | /* enable special processing based on the cprbs flags special bit */ |
| 571 | if (msg->cprbx.flags & 0x20) | 569 | if (msg->cprbx.flags & 0x20) |
| 572 | ap_msg->special = 1; | 570 | ap_msg->flags |= AP_MSG_FLAG_SPECIAL; |
| 573 | 571 | ||
| 574 | return 0; | 572 | return 0; |
| 575 | } | 573 | } |
| @@ -639,7 +637,7 @@ static int convert_type86_ica(struct zcrypt_queue *zq, · 63 unmodified lines | |||
| 639 | 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41, | 637 | 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41, |
| 640 | 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09 | 638 | 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09 |
| 641 | }; | 639 | }; |
| 642 | struct type86x_reply *msg = reply->message; | 640 | struct type86x_reply *msg = reply->msg; |
| 643 | unsigned short service_rc, service_rs; | 641 | unsigned short service_rc, service_rs; |
| 644 | unsigned int reply_len, pad_len; | 642 | unsigned int reply_len, pad_len; |
| 645 | char *data; | 643 | char *data; |
| @@ -713,8 +711,8 @@ static int convert_type86_xcrb(struct zcrypt_queue *zq, · 67 unmodified lines | |||
| 713 | struct ap_message *reply, | 711 | struct ap_message *reply, |
| 714 | struct ica_xcRB *xcRB) | 712 | struct ica_xcRB *xcRB) |
| 715 | { | 713 | { |
| 716 | struct type86_fmt2_msg *msg = reply->message; | 714 | struct type86_fmt2_msg *msg = reply->msg; |
| 717 | char *data = reply->message; | 715 | char *data = reply->msg; |
| 718 | 716 | ||
| 719 | /* Copy CPRB to user */ | 717 | /* Copy CPRB to user */ |
| 720 | if (copy_to_user(xcRB->reply_control_blk_addr, | 718 | if (copy_to_user(xcRB->reply_control_blk_addr, |
| @@ -744,8 +742,8 @@ static int convert_type86_ep11_xcrb(struct zcrypt_queue *zq, · 23 unmodified lines | |||
| 744 | struct ap_message *reply, | 742 | struct ap_message *reply, |
| 745 | struct ep11_urb *xcRB) | 743 | struct ep11_urb *xcRB) |
| 746 | { | 744 | { |
| 747 | struct type86_fmt2_msg *msg = reply->message; | 745 | struct type86_fmt2_msg *msg = reply->msg; |
| 748 | char *data = reply->message; | 746 | char *data = reply->msg; |
| 749 | 747 | ||
| 750 | if (xcRB->resp_len < msg->fmt2.count1) | 748 | if (xcRB->resp_len < msg->fmt2.count1) |
| 751 | return -EINVAL; | 749 | return -EINVAL; |
| @@ -766,8 +764,8 @@ static int convert_type86_rng(struct zcrypt_queue *zq, · 14 unmodified lines | |||
| 766 | struct type86_hdr hdr; | 764 | struct type86_hdr hdr; |
| 767 | struct type86_fmt2_ext fmt2; | 765 | struct type86_fmt2_ext fmt2; |
| 768 | struct CPRBX cprbx; | 766 | struct CPRBX cprbx; |
| 769 | } __packed * msg = reply->message; | 767 | } __packed * msg = reply->msg; |
| 770 | char *data = reply->message; | 768 | char *data = reply->msg; |
| 771 | 769 | ||
| 772 | if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) | 770 | if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) |
| 773 | return -EINVAL; | 771 | return -EINVAL; |
| @@ -780,7 +778,7 @@ static int convert_response_ica(struct zcrypt_queue *zq, · 6 unmodified lines | |||
| 780 | char __user *outputdata, | 778 | char __user *outputdata, |
| 781 | unsigned int outputdatalength) | 779 | unsigned int outputdatalength) |
| 782 | { | 780 | { |
| 783 | struct type86x_reply *msg = reply->message; | 781 | struct type86x_reply *msg = reply->msg; |
| 784 | 782 | ||
| 785 | switch (msg->hdr.type) { | 783 | switch (msg->hdr.type) { |
| 786 | case TYPE82_RSP_CODE: | 784 | case TYPE82_RSP_CODE: |
| @@ -820,7 +818,7 @@ static int convert_response_xcrb(struct zcrypt_queue *zq, · 33 unmodified lines | |||
| 820 | struct ap_message *reply, | 818 | struct ap_message *reply, |
| 821 | struct ica_xcRB *xcRB) | 819 | struct ica_xcRB *xcRB) |
| 822 | { | 820 | { |
| 823 | struct type86x_reply *msg = reply->message; | 821 | struct type86x_reply *msg = reply->msg; |
| 824 | 822 | ||
| 825 | switch (msg->hdr.type) { | 823 | switch (msg->hdr.type) { |
| 826 | case TYPE82_RSP_CODE: | 824 | case TYPE82_RSP_CODE: |
| @@ -853,7 +851,7 @@ static int convert_response_xcrb(struct zcrypt_queue *zq, · 26 unmodified lines | |||
| 853 | static int convert_response_ep11_xcrb(struct zcrypt_queue *zq, | 851 | static int convert_response_ep11_xcrb(struct zcrypt_queue *zq, |
| 854 | struct ap_message *reply, struct ep11_urb *xcRB) | 852 | struct ap_message *reply, struct ep11_urb *xcRB) |
| 855 | { | 853 | { |
| 856 | struct type86_ep11_reply *msg = reply->message; | 854 | struct type86_ep11_reply *msg = reply->msg; |
| 857 | 855 | ||
| 858 | switch (msg->hdr.type) { | 856 | switch (msg->hdr.type) { |
| 859 | case TYPE82_RSP_CODE: | 857 | case TYPE82_RSP_CODE: |
| @@ -883,7 +881,7 @@ static int convert_response_rng(struct zcrypt_queue *zq, · 23 unmodified lines | |||
| 883 | struct ap_message *reply, | 881 | struct ap_message *reply, |
| 884 | char *data) | 882 | char *data) |
| 885 | { | 883 | { |
| 886 | struct type86x_reply *msg = reply->message; | 884 | struct type86x_reply *msg = reply->msg; |
| 887 | 885 | ||
| 888 | switch (msg->hdr.type) { | 886 | switch (msg->hdr.type) { |
| 889 | case TYPE82_RSP_CODE: | 887 | case TYPE82_RSP_CODE: |
| @@ -928,32 +926,30 @@ static void zcrypt_msgtype6_receive(struct ap_queue *aq, · 38 unmodified lines | |||
| 928 | struct response_type *resp_type = | 926 | struct response_type *resp_type = |
| 929 | (struct response_type *) msg->private; | 927 | (struct response_type *) msg->private; |
| 930 | struct type86x_reply *t86r; | 928 | struct type86x_reply *t86r; |
| 931 | int length; | 929 | int len; |
| 932 | 930 | ||
| 933 | /* Copy the reply message to the request message buffer. */ | 931 | /* Copy the reply message to the request message buffer. */ |
| 934 | if (!reply) | 932 | if (!reply) |
| 935 | goto out; /* ap_msg->rc indicates the error */ | 933 | goto out; /* ap_msg->rc indicates the error */ |
| 936 | t86r = reply->message; | 934 | t86r = reply->msg; |
| 937 | if (t86r->hdr.type == TYPE86_RSP_CODE && | 935 | if (t86r->hdr.type == TYPE86_RSP_CODE && |
| 938 | t86r->cprbx.cprb_ver_id == 0x02) { | 936 | t86r->cprbx.cprb_ver_id == 0x02) { |
| 939 | switch (resp_type->type) { | 937 | switch (resp_type->type) { |
| 940 | case CEXXC_RESPONSE_TYPE_ICA: | 938 | case CEXXC_RESPONSE_TYPE_ICA: |
| 941 | length = sizeof(struct type86x_reply) | 939 | len = sizeof(struct type86x_reply) + t86r->length - 2; |
| 942 | + t86r->length - 2; | 940 | len = min_t(int, CEXXC_MAX_ICA_RESPONSE_SIZE, len); |
| 943 | length = min(CEXXC_MAX_ICA_RESPONSE_SIZE, length); | 941 | memcpy(msg->msg, reply->msg, len); |
| 944 | memcpy(msg->message, reply->message, length); | ||
| 945 | break; | 942 | break; |
| 946 | case CEXXC_RESPONSE_TYPE_XCRB: | 943 | case CEXXC_RESPONSE_TYPE_XCRB: |
| 947 | length = t86r->fmt2.offset2 + t86r->fmt2.count2; | 944 | len = t86r->fmt2.offset2 + t86r->fmt2.count2; |
| 948 | length = min(MSGTYPE06_MAX_MSG_SIZE, length); | 945 | len = min_t(int, MSGTYPE06_MAX_MSG_SIZE, len); |
| 949 | memcpy(msg->message, reply->message, length); | 946 | memcpy(msg->msg, reply->msg, len); |
| 950 | break; | 947 | break; |
| 951 | default: | 948 | default: |
| 952 | memcpy(msg->message, &error_reply, | 949 | memcpy(msg->msg, &error_reply, sizeof(error_reply)); |
| 953 | sizeof(error_reply)); | ||
| 954 | } | 950 | } |
| 955 | } else | 951 | } else |
| 956 | memcpy(msg->message, reply->message, sizeof(error_reply)); | 952 | memcpy(msg->msg, reply->msg, sizeof(error_reply)); |
| 957 | out: | 953 | out: |
| 958 | complete(&(resp_type->work)); | 954 | complete(&(resp_type->work)); |
| 959 | } | 955 | } |
| @@ -977,25 +973,25 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_queue *aq, · 17 unmodified lines | |||
| 977 | struct response_type *resp_type = | 973 | struct response_type *resp_type = |
| 978 | (struct response_type *)msg->private; | 974 | (struct response_type *)msg->private; |
| 979 | struct type86_ep11_reply *t86r; | 975 | struct type86_ep11_reply *t86r; |
| 980 | int length; | 976 | int len; |
| 981 | 977 | ||
| 982 | /* Copy the reply message to the request message buffer. */ | 978 | /* Copy the reply message to the request message buffer. */ |
| 983 | if (!reply) | 979 | if (!reply) |
| 984 | goto out; /* ap_msg->rc indicates the error */ | 980 | goto out; /* ap_msg->rc indicates the error */ |
| 985 | t86r = reply->message; | 981 | t86r = reply->msg; |
| 986 | if (t86r->hdr.type == TYPE86_RSP_CODE && | 982 | if (t86r->hdr.type == TYPE86_RSP_CODE && |
| 987 | t86r->cprbx.cprb_ver_id == 0x04) { | 983 | t86r->cprbx.cprb_ver_id == 0x04) { |
| 988 | switch (resp_type->type) { | 984 | switch (resp_type->type) { |
| 989 | case CEXXC_RESPONSE_TYPE_EP11: | 985 | case CEXXC_RESPONSE_TYPE_EP11: |
| 990 | length = t86r->fmt2.offset1 + t86r->fmt2.count1; | 986 | len = t86r->fmt2.offset1 + t86r->fmt2.count1; |
| 991 | length = min(MSGTYPE06_MAX_MSG_SIZE, length); | 987 | len = min_t(int, MSGTYPE06_MAX_MSG_SIZE, len); |
| 992 | memcpy(msg->message, reply->message, length); | 988 | memcpy(msg->msg, reply->msg, len); |
| 993 | break; | 989 | break; |
| 994 | default: | 990 | default: |
| 995 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | 991 | memcpy(msg->msg, &error_reply, sizeof(error_reply)); |
| 996 | } | 992 | } |
| 997 | } else { | 993 | } else { |
| 998 | memcpy(msg->message, reply->message, sizeof(error_reply)); | 994 | memcpy(msg->msg, reply->msg, sizeof(error_reply)); |
| 999 | } | 995 | } |
| 1000 | out: | 996 | out: |
| 1001 | complete(&(resp_type->work)); | 997 | complete(&(resp_type->work)); |
| @@ -1020,8 +1016,8 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq, · 18 unmodified lines | |||
| 1020 | int rc; | 1016 | int rc; |
| 1021 | 1017 | ||
| 1022 | ap_init_message(&ap_msg); | 1018 | ap_init_message(&ap_msg); |
| 1023 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 1019 | ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); |
| 1024 | if (!ap_msg.message) | 1020 | if (!ap_msg.msg) |
| 1025 | return -ENOMEM; | 1021 | return -ENOMEM; |
| 1026 | ap_msg.receive = zcrypt_msgtype6_receive; | 1022 | ap_msg.receive = zcrypt_msgtype6_receive; |
| 1027 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 1023 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -1043,7 +1039,7 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq, · 15 unmodified lines | |||
| 1043 | /* Signal pending. */ | 1039 | /* Signal pending. */ |
| 1044 | ap_cancel_message(zq->queue, &ap_msg); | 1040 | ap_cancel_message(zq->queue, &ap_msg); |
| 1045 | out_free: | 1041 | out_free: |
| 1046 | free_page((unsigned long) ap_msg.message); | 1042 | free_page((unsigned long) ap_msg.msg); |
| 1047 | return rc; | 1043 | return rc; |
| 1048 | } | 1044 | } |
| 1049 | 1045 | ||
| @@ -1064,8 +1060,8 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq, · 14 unmodified lines | |||
| 1064 | int rc; | 1060 | int rc; |
| 1065 | 1061 | ||
| 1066 | ap_init_message(&ap_msg); | 1062 | ap_init_message(&ap_msg); |
| 1067 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 1063 | ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); |
| 1068 | if (!ap_msg.message) | 1064 | if (!ap_msg.msg) |
| 1069 | return -ENOMEM; | 1065 | return -ENOMEM; |
| 1070 | ap_msg.receive = zcrypt_msgtype6_receive; | 1066 | ap_msg.receive = zcrypt_msgtype6_receive; |
| 1071 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 1067 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -1088,7 +1084,7 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq, · 16 unmodified lines | |||
| 1088 | ap_cancel_message(zq->queue, &ap_msg); | 1084 | ap_cancel_message(zq->queue, &ap_msg); |
| 1089 | } | 1085 | } |
| 1090 | out_free: | 1086 | out_free: |
| 1091 | free_page((unsigned long) ap_msg.message); | 1087 | free_page((unsigned long) ap_msg.msg); |
| 1092 | return rc; | 1088 | return rc; |
| 1093 | } | 1089 | } |
| 1094 | 1090 | ||
| @@ -1107,8 +1103,8 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, · 12 unmodified lines | |||
| 1107 | .type = CEXXC_RESPONSE_TYPE_XCRB, | 1103 | .type = CEXXC_RESPONSE_TYPE_XCRB, |
| 1108 | }; | 1104 | }; |
| 1109 | 1105 | ||
| 1110 | ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | 1106 | ap_msg->msg = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); |
| 1111 | if (!ap_msg->message) | 1107 | if (!ap_msg->msg) |
| 1112 | return -ENOMEM; | 1108 | return -ENOMEM; |
| 1113 | ap_msg->receive = zcrypt_msgtype6_receive; | 1109 | ap_msg->receive = zcrypt_msgtype6_receive; |
| 1114 | ap_msg->psmid = (((unsigned long long) current->pid) << 32) + | 1110 | ap_msg->psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -1162,8 +1158,8 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, · 47 unmodified lines | |||
| 1162 | .type = CEXXC_RESPONSE_TYPE_EP11, | 1158 | .type = CEXXC_RESPONSE_TYPE_EP11, |
| 1163 | }; | 1159 | }; |
| 1164 | 1160 | ||
| 1165 | ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | 1161 | ap_msg->msg = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); |
| 1166 | if (!ap_msg->message) | 1162 | if (!ap_msg->msg) |
| 1167 | return -ENOMEM; | 1163 | return -ENOMEM; |
| 1168 | ap_msg->receive = zcrypt_msgtype6_receive_ep11; | 1164 | ap_msg->receive = zcrypt_msgtype6_receive_ep11; |
| 1169 | ap_msg->psmid = (((unsigned long long) current->pid) << 32) + | 1165 | ap_msg->psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -1193,7 +1189,7 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue *zq, · 23 unmodified lines | |||
| 1193 | struct ep11_cprb cprbx; | 1189 | struct ep11_cprb cprbx; |
| 1194 | unsigned char pld_tag; /* fixed value 0x30 */ | 1190 | unsigned char pld_tag; /* fixed value 0x30 */ |
| 1195 | unsigned char pld_lenfmt; /* payload length format */ | 1191 | unsigned char pld_lenfmt; /* payload length format */ |
| 1196 | } __packed * msg = ap_msg->message; | 1192 | } __packed * msg = ap_msg->msg; |
| 1197 | struct pld_hdr { | 1193 | struct pld_hdr { |
| 1198 | unsigned char func_tag; /* fixed value 0x4 */ | 1194 | unsigned char func_tag; /* fixed value 0x4 */ |
| 1199 | unsigned char func_len; /* fixed value 0x4 */ | 1195 | unsigned char func_len; /* fixed value 0x4 */ |
| @@ -1256,8 +1252,8 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, · 56 unmodified lines | |||
| 1256 | .type = CEXXC_RESPONSE_TYPE_XCRB, | 1252 | .type = CEXXC_RESPONSE_TYPE_XCRB, |
| 1257 | }; | 1253 | }; |
| 1258 | 1254 | ||
| 1259 | ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | 1255 | ap_msg->msg = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); |
| 1260 | if (!ap_msg->message) | 1256 | if (!ap_msg->msg) |
| 1261 | return -ENOMEM; | 1257 | return -ENOMEM; |
| 1262 | ap_msg->receive = zcrypt_msgtype6_receive; | 1258 | ap_msg->receive = zcrypt_msgtype6_receive; |
| 1263 | ap_msg->psmid = (((unsigned long long) current->pid) << 32) + | 1259 | ap_msg->psmid = (((unsigned long long) current->pid) << 32) + |
| @@ -1290,7 +1286,7 @@ static long zcrypt_msgtype6_rng(struct zcrypt_queue *zq, · 26 unmodified lines | |||
| 1290 | char rule[8]; | 1286 | char rule[8]; |
| 1291 | short int verb_length; | 1287 | short int verb_length; |
| 1292 | short int key_length; | 1288 | short int key_length; |
| 1293 | } __packed * msg = ap_msg->message; | 1289 | } __packed * msg = ap_msg->msg; |
| 1294 | struct response_type *rtype = (struct response_type *)(ap_msg->private); | 1290 | struct response_type *rtype = (struct response_type *)(ap_msg->private); |
| 1295 | int rc; | 1291 | int rc; |
| 1296 | 1292 | ||
| @@ -127,7 +127,7 @@ static inline void rng_type6CPRB_msgX(struct ap_message *ap_msg, · 126 unmodified lines | |||
| 127 | char rule[8]; | 127 | char rule[8]; |
| 128 | short int verb_length; | 128 | short int verb_length; |
| 129 | short int key_length; | 129 | short int key_length; |
| 130 | } __packed * msg = ap_msg->message; | 130 | } __packed * msg = ap_msg->msg; |
| 131 | static struct type6_hdr static_type6_hdrX = { | 131 | static struct type6_hdr static_type6_hdrX = { |
| 132 | .type = 0x06, | 132 | .type = 0x06, |
| 133 | .offset1 = 0x00000058, | 133 | .offset1 = 0x00000058, |
| @@ -154,7 +154,7 @@ static inline void rng_type6CPRB_msgX(struct ap_message *ap_msg, · 20 unmodified lines | |||
| 154 | memcpy(msg->rule, "RANDOM ", 8); | 154 | memcpy(msg->rule, "RANDOM ", 8); |
| 155 | msg->verb_length = 0x02; | 155 | msg->verb_length = 0x02; |
| 156 | msg->key_length = 0x02; | 156 | msg->key_length = 0x02; |
| 157 | ap_msg->length = sizeof(*msg); | 157 | ap_msg->len = sizeof(*msg); |
| 158 | *domain = (unsigned short)msg->cprbx.domain; | 158 | *domain = (unsigned short)msg->cprbx.domain; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| @@ -107,10 +107,10 @@ struct zcrypt_queue *zcrypt_queue_alloc(size_t max_response_size) · 106 unmodified lines | |||
| 107 | zq = kzalloc(sizeof(struct zcrypt_queue), GFP_KERNEL); | 107 | zq = kzalloc(sizeof(struct zcrypt_queue), GFP_KERNEL); |
| 108 | if (!zq) | 108 | if (!zq) |
| 109 | return NULL; | 109 | return NULL; |
| 110 | zq->reply.message = kmalloc(max_response_size, GFP_KERNEL); | 110 | zq->reply.msg = kmalloc(max_response_size, GFP_KERNEL); |
| 111 | if (!zq->reply.message) | 111 | if (!zq->reply.msg) |
| 112 | goto out_free; | 112 | goto out_free; |
| 113 | zq->reply.length = max_response_size; | 113 | zq->reply.len = max_response_size; |
| 114 | INIT_LIST_HEAD(&zq->list); | 114 | INIT_LIST_HEAD(&zq->list); |
| 115 | kref_init(&zq->refcount); | 115 | kref_init(&zq->refcount); |
| 116 | return zq; | 116 | return zq; |
| @@ -123,7 +123,7 @@ EXPORT_SYMBOL(zcrypt_queue_alloc); · 6 unmodified lines | |||
| 123 | 123 | ||
| 124 | void zcrypt_queue_free(struct zcrypt_queue *zq) | 124 | void zcrypt_queue_free(struct zcrypt_queue *zq) |
| 125 | { | 125 | { |
| 126 | kfree(zq->reply.message); | 126 | kfree(zq->reply.msg); |
| 127 | kfree(zq); | 127 | kfree(zq); |
| 128 | } | 128 | } |
| 129 | EXPORT_SYMBOL(zcrypt_queue_free); | 129 | EXPORT_SYMBOL(zcrypt_queue_free); |
| @@ -77,16 +77,12 @@ struct memblock_type { · 76 unmodified lines | |||
| 77 | * @current_limit: physical address of the current allocation limit | 77 | * @current_limit: physical address of the current allocation limit |
| 78 | * @memory: usable memory regions | 78 | * @memory: usable memory regions |
| 79 | * @reserved: reserved memory regions | 79 | * @reserved: reserved memory regions |
| 80 | * @physmem: all physical memory | ||
| 81 | */ | 80 | */ |
| 82 | struct memblock { | 81 | struct memblock { |
| 83 | bool bottom_up; /* is bottom up direction? */ | 82 | bool bottom_up; /* is bottom up direction? */ |
| 84 | phys_addr_t current_limit; | 83 | phys_addr_t current_limit; |
| 85 | struct memblock_type memory; | 84 | struct memblock_type memory; |
| 86 | struct memblock_type reserved; | 85 | struct memblock_type reserved; |
| 87 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | ||
| 88 | struct memblock_type physmem; | ||
| 89 | #endif | ||
| 90 | }; | 86 | }; |
| 91 | 87 | ||
| 92 | extern struct memblock memblock; | 88 | extern struct memblock memblock; |
| @@ -145,6 +141,30 @@ void __next_reserved_mem_region(u64 *idx, phys_addr_t *out_start, · 52 unmodified lines | |||
| 145 | 141 | ||
| 146 | void __memblock_free_late(phys_addr_t base, phys_addr_t size); | 142 | void __memblock_free_late(phys_addr_t base, phys_addr_t size); |
| 147 | 143 | ||
| 144 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | ||
| 145 | static inline void __next_physmem_range(u64 *idx, struct memblock_type *type, | ||
| 146 | phys_addr_t *out_start, | ||
| 147 | phys_addr_t *out_end) | ||
| 148 | { | ||
| 149 | extern struct memblock_type physmem; | ||
| 150 | |||
| 151 | __next_mem_range(idx, NUMA_NO_NODE, MEMBLOCK_NONE, &physmem, type, | ||
| 152 | out_start, out_end, NULL); | ||
| 153 | } | ||
| 154 | |||
| 155 | /** | ||
| 156 | * for_each_physmem_range - iterate through physmem areas not included in type. | ||
| 157 | * @i: u64 used as loop variable | ||
| 158 | * @type: ptr to memblock_type which excludes from the iteration, can be %NULL | ||
| 159 | * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL | ||
| 160 | * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL | ||
| 161 | */ | ||
| 162 | #define for_each_physmem_range(i, type, p_start, p_end) \ | ||
| 163 | for (i = 0, __next_physmem_range(&i, type, p_start, p_end); \ | ||
| 164 | i != (u64)ULLONG_MAX; \ | ||
| 165 | __next_physmem_range(&i, type, p_start, p_end)) | ||
| 166 | #endif /* CONFIG_HAVE_MEMBLOCK_PHYS_MAP */ | ||
| 167 | |||
| 148 | /** | 168 | /** |
| 149 | * for_each_mem_range - iterate through memblock areas from type_a and not | 169 | * for_each_mem_range - iterate through memblock areas from type_a and not |
| 150 | * included in type_b. Or just type_a if type_b is NULL. | 170 | * included in type_b. Or just type_a if type_b is NULL. |
| @@ -44,19 +44,20 @@ · 43 unmodified lines | |||
| 44 | * in the system, for instance when the memory is restricted with | 44 | * in the system, for instance when the memory is restricted with |
| 45 | * ``mem=`` command line parameter | 45 | * ``mem=`` command line parameter |
| 46 | * * ``reserved`` - describes the regions that were allocated | 46 | * * ``reserved`` - describes the regions that were allocated |
| 47 | * * ``physmap`` - describes the actual physical memory regardless of | 47 | * * ``physmem`` - describes the actual physical memory available during |
| 48 | * the possible restrictions; the ``physmap`` type is only available | 48 | * boot regardless of the possible restrictions and memory hot(un)plug; |
| 49 | * on some architectures. | 49 | * the ``physmem`` type is only available on some architectures. |
| 50 | * | 50 | * |
| 51 | * Each region is represented by :c:type:`struct memblock_region` that | 51 | * Each region is represented by :c:type:`struct memblock_region` that |
| 52 | * defines the region extents, its attributes and NUMA node id on NUMA | 52 | * defines the region extents, its attributes and NUMA node id on NUMA |
| 53 | * systems. Every memory type is described by the :c:type:`struct | 53 | * systems. Every memory type is described by the :c:type:`struct |
| 54 | * memblock_type` which contains an array of memory regions along with | 54 | * memblock_type` which contains an array of memory regions along with |
| 55 | * the allocator metadata. The memory types are nicely wrapped with | 55 | * the allocator metadata. The "memory" and "reserved" types are nicely |
| 56 | * :c:type:`struct memblock`. This structure is statically initialzed | 56 | * wrapped with :c:type:`struct memblock`. This structure is statically |
| 57 | * at build time. The region arrays for the "memory" and "reserved" | 57 | * initialized at build time. The region arrays are initially sized to |
| 58 | * types are initially sized to %INIT_MEMBLOCK_REGIONS and for the | 58 | * %INIT_MEMBLOCK_REGIONS for "memory" and %INIT_MEMBLOCK_RESERVED_REGIONS |
| 59 | * "physmap" type to %INIT_PHYSMEM_REGIONS. | 59 | * for "reserved". The region array for "physmem" is initially sized to |
| 60 | * %INIT_PHYSMEM_REGIONS. | ||
| 60 | * The memblock_allow_resize() enables automatic resizing of the region | 61 | * The memblock_allow_resize() enables automatic resizing of the region |
| 61 | * arrays during addition of new regions. This feature should be used | 62 | * arrays during addition of new regions. This feature should be used |
| 62 | * with care so that memory allocated for the region array will not | 63 | * with care so that memory allocated for the region array will not |
| @@ -87,8 +88,8 @@ · 24 unmodified lines | |||
| 87 | * function frees all the memory to the buddy page allocator. | 88 | * function frees all the memory to the buddy page allocator. |
| 88 | * | 89 | * |
| 89 | * Unless an architecture enables %CONFIG_ARCH_KEEP_MEMBLOCK, the | 90 | * Unless an architecture enables %CONFIG_ARCH_KEEP_MEMBLOCK, the |
| 90 | * memblock data structures will be discarded after the system | 91 | * memblock data structures (except "physmem") will be discarded after the |
| 91 | * initialization completes. | 92 | * system initialization completes. |
| 92 | */ | 93 | */ |
| 93 | 94 | ||
| 94 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 95 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
| @@ -104,7 +105,7 @@ unsigned long long max_possible_pfn; · 9 unmodified lines | |||
| 104 | static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; | 105 | static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; |
| 105 | static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock; | 106 | static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock; |
| 106 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | 107 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP |
| 107 | static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock; | 108 | static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS]; |
| 108 | #endif | 109 | #endif |
| 109 | 110 | ||
| 110 | struct memblock memblock __initdata_memblock = { | 111 | struct memblock memblock __initdata_memblock = { |
| @@ -118,17 +119,19 @@ struct memblock memblock __initdata_memblock = { · 7 unmodified lines | |||
| 118 | .reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS, | 119 | .reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS, |
| 119 | .reserved.name = "reserved", | 120 | .reserved.name = "reserved", |
| 120 | 121 | ||
| 121 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | ||
| 122 | .physmem.regions = memblock_physmem_init_regions, | ||
| 123 | .physmem.cnt = 1, /* empty dummy entry */ | ||
| 124 | .physmem.max = INIT_PHYSMEM_REGIONS, | ||
| 125 | .physmem.name = "physmem", | ||
| 126 | #endif | ||
| 127 | |||
| 128 | .bottom_up = false, | 122 | .bottom_up = false, |
| 129 | .current_limit = MEMBLOCK_ALLOC_ANYWHERE, | 123 | .current_limit = MEMBLOCK_ALLOC_ANYWHERE, |
| 130 | }; | 124 | }; |
| 131 | 125 | ||
| 126 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | ||
| 127 | struct memblock_type physmem = { | ||
| 128 | .regions = memblock_physmem_init_regions, | ||
| 129 | .cnt = 1, /* empty dummy entry */ | ||
| 130 | .max = INIT_PHYSMEM_REGIONS, | ||
| 131 | .name = "physmem", | ||
| 132 | }; | ||
| 133 | #endif | ||
| 134 | |||
| 132 | int memblock_debug __initdata_memblock; | 135 | int memblock_debug __initdata_memblock; |
| 133 | static bool system_has_some_mirror __initdata_memblock = false; | 136 | static bool system_has_some_mirror __initdata_memblock = false; |
| 134 | static int memblock_can_resize __initdata_memblock; | 137 | static int memblock_can_resize __initdata_memblock; |
| @@ -838,7 +841,7 @@ int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size) · 703 unmodified lines | |||
| 838 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, | 841 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, |
| 839 | &base, &end, (void *)_RET_IP_); | 842 | &base, &end, (void *)_RET_IP_); |
| 840 | 843 | ||
| 841 | return memblock_add_range(&memblock.physmem, base, size, MAX_NUMNODES, 0); | 844 | return memblock_add_range(&physmem, base, size, MAX_NUMNODES, 0); |
| 842 | } | 845 | } |
| 843 | #endif | 846 | #endif |
| 844 | 847 | ||
| @@ -1019,12 +1022,10 @@ static bool should_skip_region(struct memblock_region *m, int nid, int flags) · 174 unmodified lines | |||
| 1019 | * As both region arrays are sorted, the function advances the two indices | 1022 | * As both region arrays are sorted, the function advances the two indices |
| 1020 | * in lockstep and returns each intersection. | 1023 | * in lockstep and returns each intersection. |
| 1021 | */ | 1024 | */ |
| 1022 | void __init_memblock __next_mem_range(u64 *idx, int nid, | 1025 | void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, |
| 1023 | enum memblock_flags flags, | 1026 | struct memblock_type *type_a, |
| 1024 | struct memblock_type *type_a, | 1027 | struct memblock_type *type_b, phys_addr_t *out_start, |
| 1025 | struct memblock_type *type_b, | 1028 | phys_addr_t *out_end, int *out_nid) |
| 1026 | phys_addr_t *out_start, | ||
| 1027 | phys_addr_t *out_end, int *out_nid) | ||
| 1028 | { | 1029 | { |
| 1029 | int idx_a = *idx & 0xffffffff; | 1030 | int idx_a = *idx & 0xffffffff; |
| 1030 | int idx_b = *idx >> 32; | 1031 | int idx_b = *idx >> 32; |
| @@ -1924,7 +1925,7 @@ void __init_memblock __memblock_dump_all(void) · 893 unmodified lines | |||
| 1924 | memblock_dump(&memblock.memory); | 1925 | memblock_dump(&memblock.memory); |
| 1925 | memblock_dump(&memblock.reserved); | 1926 | memblock_dump(&memblock.reserved); |
| 1926 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | 1927 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP |
| 1927 | memblock_dump(&memblock.physmem); | 1928 | memblock_dump(&physmem); |
| 1928 | #endif | 1929 | #endif |
| 1929 | } | 1930 | } |
| 1930 | 1931 | ||
| @@ -2064,8 +2065,8 @@ static int __init memblock_init_debugfs(void) · 133 unmodified lines | |||
| 2064 | debugfs_create_file("reserved", 0444, root, | 2065 | debugfs_create_file("reserved", 0444, root, |
| 2065 | &memblock.reserved, &memblock_debug_fops); | 2066 | &memblock.reserved, &memblock_debug_fops); |
| 2066 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | 2067 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP |
| 2067 | debugfs_create_file("physmem", 0444, root, | 2068 | debugfs_create_file("physmem", 0444, root, &physmem, |
| 2068 | &memblock.physmem, &memblock_debug_fops); | 2069 | &memblock_debug_fops); |
| 2069 | #endif | 2070 | #endif |
| 2070 | 2071 | ||
| 2071 | return 0; | 2072 | return 0; |
| @@ -255,6 +255,45 @@ static void x86_sort_relative_table(char *extab_image, int image_size) · 254 unmodified lines | |||
| 255 | } | 255 | } |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | static void s390_sort_relative_table(char *extab_image, int image_size) | ||
| 259 | { | ||
| 260 | int i; | ||
| 261 | |||
| 262 | for (i = 0; i < image_size; i += 16) { | ||
| 263 | char *loc = extab_image + i; | ||
| 264 | uint64_t handler; | ||
| 265 | |||
| 266 | w(r((uint32_t *)loc) + i, (uint32_t *)loc); | ||
| 267 | w(r((uint32_t *)(loc + 4)) + (i + 4), (uint32_t *)(loc + 4)); | ||
| 268 | /* | ||
| 269 | * 0 is a special self-relative handler value, which means that | ||
| 270 | * handler should be ignored. It is safe, because it means that | ||
| 271 | * handler field points to itself, which should never happen. | ||
| 272 | * When creating extable-relative values, keep it as 0, since | ||
| 273 | * this should never occur either: it would mean that handler | ||
| 274 | * field points to the first extable entry. | ||
| 275 | */ | ||
| 276 | handler = r8((uint64_t *)(loc + 8)); | ||
| 277 | if (handler) | ||
| 278 | handler += i + 8; | ||
| 279 | w8(handler, (uint64_t *)(loc + 8)); | ||
| 280 | } | ||
| 281 | |||
| 282 | qsort(extab_image, image_size / 16, 16, compare_relative_table); | ||
| 283 | |||
| 284 | for (i = 0; i < image_size; i += 16) { | ||
| 285 | char *loc = extab_image + i; | ||
| 286 | uint64_t handler; | ||
| 287 | |||
| 288 | w(r((uint32_t *)loc) - i, (uint32_t *)loc); | ||
| 289 | w(r((uint32_t *)(loc + 4)) - (i + 4), (uint32_t *)(loc + 4)); | ||
| 290 | handler = r8((uint64_t *)(loc + 8)); | ||
| 291 | if (handler) | ||
| 292 | handler -= i + 8; | ||
| 293 | w8(handler, (uint64_t *)(loc + 8)); | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 258 | static int do_file(char const *const fname, void *addr) | 297 | static int do_file(char const *const fname, void *addr) |
| 259 | { | 298 | { |
| 260 | int rc = -1; | 299 | int rc = -1; |
| @@ -297,6 +336,8 @@ static int do_file(char const *const fname, void *addr) · 36 unmodified lines | |||
| 297 | custom_sort = x86_sort_relative_table; | 336 | custom_sort = x86_sort_relative_table; |
| 298 | break; | 337 | break; |
| 299 | case EM_S390: | 338 | case EM_S390: |
| 339 | custom_sort = s390_sort_relative_table; | ||
| 340 | break; | ||
| 300 | case EM_AARCH64: | 341 | case EM_AARCH64: |
| 301 | case EM_PARISC: | 342 | case EM_PARISC: |
| 302 | case EM_PPC: | 343 | case EM_PPC: |