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 | 67 | The content of the directories are files which represent different views |
| 68 | 68 | to the debug log. Each component can decide which views should be |
| 69 | 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 | 71 | It is also possible to define other views. The content of |
| 72 | 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 | 120 | extern struct debug_view debug_hex_ascii_view; |
| 121 | 121 | |
| 122 | − extern struct debug_view debug_raw_view; | |
| 123 | − | |
| 124 | 122 | extern struct debug_view debug_sprintf_view; |
| 125 | 123 | |
| 126 | 124 | Examples |
| @@ -129,7 +127,7 @@ Examples · 2 unmodified lines | ||
| 129 | 127 | .. code-block:: c |
| 130 | 128 | |
| 131 | 129 | /* |
| 132 | − * hex_ascii- + raw-view Example | |
| 130 | + * hex_ascii-view Example | |
| 133 | 131 | */ |
| 134 | 132 | |
| 135 | 133 | #include <linux/init.h> |
| @@ -143,7 +141,6 @@ Examples · 7 unmodified lines | ||
| 143 | 141 | |
| 144 | 142 | debug_info = debug_register("test", 1, 4, 4 ); |
| 145 | 143 | debug_register_view(debug_info, &debug_hex_ascii_view); |
| 146 | − debug_register_view(debug_info, &debug_raw_view); | |
| 147 | 144 | |
| 148 | 145 | debug_text_event(debug_info, 4 , "one "); |
| 149 | 146 | debug_int_exception(debug_info, 4, 4711); |
| @@ -201,7 +198,7 @@ debugfs-files: · 51 unmodified lines | ||
| 201 | 198 | Example:: |
| 202 | 199 | |
| 203 | 200 | > ls /sys/kernel/debug/s390dbf/dasd |
| 204 | − flush hex_ascii level pages raw | |
| 201 | + flush hex_ascii level pages | |
| 205 | 202 | > cat /sys/kernel/debug/s390dbf/dasd/hex_ascii | sort -k2,2 -s |
| 206 | 203 | 00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | .... |
| 207 | 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 | 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 | 299 | The hex_ascii view shows the data field in hex and ascii representation |
| 303 | 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 | 302 | The sprintf view formats the debug entries in the same way as the sprintf |
| 307 | 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 | 330 | - Return Address to caller |
| 335 | 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 | 333 | A typical line of the hex_ascii view will look like the following (first line |
| 343 | 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 | 102 | select ARCH_INLINE_WRITE_UNLOCK_BH |
| 103 | 103 | select ARCH_INLINE_WRITE_UNLOCK_IRQ |
| 104 | 104 | select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE |
| 105 | − select ARCH_KEEP_MEMBLOCK | |
| 106 | 105 | select ARCH_STACKWALK |
| 107 | 106 | select ARCH_SUPPORTS_ATOMIC_RMW |
| 108 | 107 | select ARCH_SUPPORTS_NUMA_BALANCING |
| @@ -126,6 +125,7 @@ config S390 · 17 unmodified lines | ||
| 126 | 125 | select HAVE_ARCH_JUMP_LABEL_RELATIVE |
| 127 | 126 | select HAVE_ARCH_KASAN |
| 128 | 127 | select HAVE_ARCH_KASAN_VMALLOC |
| 128 | + select CLOCKSOURCE_VALIDATE_LAST_CYCLE | |
| 129 | 129 | select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES |
| 130 | 130 | select HAVE_ARCH_SECCOMP_FILTER |
| 131 | 131 | select HAVE_ARCH_SOFT_DIRTY |
| @@ -145,6 +145,7 @@ config S390 · 13 unmodified lines | ||
| 145 | 145 | select HAVE_EFFICIENT_UNALIGNED_ACCESS |
| 146 | 146 | select HAVE_FENTRY |
| 147 | 147 | select HAVE_FTRACE_MCOUNT_RECORD |
| 148 | + select HAVE_FUNCTION_ERROR_INJECTION | |
| 148 | 149 | select HAVE_FUNCTION_GRAPH_TRACER |
| 149 | 150 | select HAVE_FUNCTION_TRACER |
| 150 | 151 | select HAVE_FUTEX_CMPXCHG if FUTEX |
| @@ -626,10 +627,6 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE · 475 unmodified lines | ||
| 626 | 627 | config ARCH_ENABLE_SPLIT_PMD_PTLOCK |
| 627 | 628 | def_bool y |
| 628 | 629 | |
| 629 | −config FORCE_MAX_ZONEORDER | |
| 630 | − int | |
| 631 | − default "9" | |
| 632 | − | |
| 633 | 630 | config MAX_PHYSMEM_BITS |
| 634 | 631 | int "Maximum size of supported physical memory in bits (42-53)" |
| 635 | 632 | range 42 53 |
| @@ -129,8 +129,7 @@ static void appldata_get_os_data(void *data) · 128 unmodified lines | ||
| 129 | 129 | |
| 130 | 130 | os_data->nr_cpus = j; |
| 131 | 131 | |
| 132 | − new_size = sizeof(struct appldata_os_data) + | |
| 133 | − (os_data->nr_cpus * sizeof(struct appldata_os_per_cpu)); | |
| 132 | + new_size = struct_size(os_data, os_cpu, os_data->nr_cpus); | |
| 134 | 133 | if (ops.size != new_size) { |
| 135 | 134 | if (ops.active) { |
| 136 | 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 | 165 | int rc, max_size; |
| 167 | 166 | |
| 168 | − max_size = sizeof(struct appldata_os_data) + | |
| 169 | − (num_possible_cpus() * sizeof(struct appldata_os_per_cpu)); | |
| 167 | + max_size = struct_size(appldata_os_data, os_cpu, num_possible_cpus()); | |
| 170 | 168 | if (max_size > APPLDATA_MAX_REC_SIZE) { |
| 171 | 169 | pr_err("Maximum OS record size %i exceeds the maximum " |
| 172 | 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 | 12 | #include <linux/kernel.h> |
| 13 | 13 | #include <linux/time.h> |
| 14 | 14 | #include <linux/refcount.h> |
| 15 | −#include <uapi/asm/debug.h> | |
| 15 | +#include <linux/fs.h> | |
| 16 | 16 | |
| 17 | 17 | #define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */ |
| 18 | 18 | #define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */ |
| @@ -26,6 +26,21 @@ · 7 unmodified lines | ||
| 26 | 26 | #define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */ |
| 27 | 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 | 44 | typedef struct __debug_entry debug_entry_t; |
| 30 | 45 | |
| 31 | 46 | struct debug_view; |
| @@ -82,7 +97,6 @@ struct debug_view { · 50 unmodified lines | ||
| 82 | 97 | }; |
| 83 | 98 | |
| 84 | 99 | extern struct debug_view debug_hex_ascii_view; |
| 85 | −extern struct debug_view debug_raw_view; | |
| 86 | 100 | extern struct debug_view debug_sprintf_view; |
| 87 | 101 | |
| 88 | 102 | /* do NOT use the _common functions */ |
| @@ -1,12 +1,20 @@ | ||
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | 2 | #ifndef __S390_EXTABLE_H |
| 3 | 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 | |
| 6 | − * address of an instruction that is allowed to fault, and the second is | |
| 7 | − * the address at which the program should continue. No registers are | |
| 8 | − * modified, so it is entirely up to the continuation code to figure out | |
| 9 | − * what to do. | |
| 9 | + * The exception table consists of three addresses: | |
| 10 | + * | |
| 11 | + * - Address of an instruction that is allowed to fault. | |
| 12 | + * - Address at which the program should continue. | |
| 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 | 19 | * All the routines below use bits of fixup code that are out of line |
| 12 | 20 | * with the main instruction path. This means when everything is well, |
| @@ -17,6 +25,7 @@ · 4 unmodified lines | ||
| 17 | 25 | struct exception_table_entry |
| 18 | 26 | { |
| 19 | 27 | int insn, fixup; |
| 28 | + long handler; | |
| 20 | 29 | }; |
| 21 | 30 | |
| 22 | 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 | 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 | 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 | 76 | #endif |
| @@ -2,38 +2,27 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef __ASM_LINKAGE_H |
| 3 | 3 | #define __ASM_LINKAGE_H |
| 4 | 4 | |
| 5 | +#include <asm/asm-const.h> | |
| 5 | 6 | #include <linux/stringify.h> |
| 6 | 7 | |
| 7 | 8 | #define __ALIGN .align 4, 0x07 |
| 8 | 9 | #define __ALIGN_STR __stringify(__ALIGN) |
| 9 | 10 | |
| 10 | −#ifndef __ASSEMBLY__ | |
| 11 | − | |
| 12 | 11 | /* |
| 13 | 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) \ | |
| 25 | − .section __ex_table,"a" ; \ | |
| 26 | − .align 4 ; \ | |
| 27 | − .long (_fault) - . ; \ | |
| 28 | − .long (_target) - . ; \ | |
| 29 | − .previous | |
| 15 | +#define __EX_TABLE(_section, _fault, _target) \ | |
| 16 | + stringify_in_c(.section _section,"a";) \ | |
| 17 | + stringify_in_c(.align 8;) \ | |
| 18 | + stringify_in_c(.long (_fault) - .;) \ | |
| 19 | + stringify_in_c(.long (_target) - .;) \ | |
| 20 | + stringify_in_c(.quad 0;) \ | |
| 21 | + stringify_in_c(.previous) | |
| 30 | 22 | |
| 31 | −#define EX_TABLE_DMA(_fault, _target) \ | |
| 32 | − .section .dma.ex_table, "a" ; \ | |
| 33 | − .align 4 ; \ | |
| 34 | − .long (_fault) - . ; \ | |
| 35 | − .long (_target) - . ; \ | |
| 36 | − .previous | |
| 23 | +#define EX_TABLE(_fault, _target) \ | |
| 24 | + __EX_TABLE(__ex_table, _fault, _target) | |
| 25 | +#define EX_TABLE_DMA(_fault, _target) \ | |
| 26 | + __EX_TABLE(.dma.ex_table, _fault, _target) | |
| 37 | 27 | |
| 38 | −#endif /* __ASSEMBLY__ */ | |
| 39 | 28 | #endif |
| @@ -131,12 +131,6 @@ static inline void validate_st_entry(unsigned long *entry) · 130 unmodified lines | ||
| 131 | 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 | 134 | static inline void invalidate_pt_entry(unsigned long *entry) |
| 141 | 135 | { |
| 142 | 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 | 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 | 170 | static inline unsigned long *get_rt_sto(unsigned long entry) |
| 182 | 171 | { |
| 183 | 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 | 1669 | #define kern_addr_valid(addr) (1) |
| 1670 | 1670 | |
| 1671 | 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 | 1673 | extern int s390_enable_sie(void); |
| 1674 | 1674 | extern int s390_enable_skey(void); |
| 1675 | 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 | 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 | 192 | #endif /* __ASSEMBLY__ */ |
| 188 | 193 | #endif /* _S390_PTRACE_H */ |
| @@ -54,6 +54,10 @@ static inline int smp_get_base_cpu(int cpu) · 53 unmodified lines | ||
| 54 | 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 | 61 | extern int smp_rescan_cpus(void); |
| 58 | 62 | extern void __noreturn cpu_die(void); |
| 59 | 63 | extern void __cpu_die(unsigned int cpu); |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | }) |
| 31 | 31 | |
| 32 | 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 | 34 | ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \ |
| 35 | 35 | asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))\ |
| 36 | 36 | { \ |
| @@ -46,7 +46,7 @@ · 9 unmodified lines | ||
| 46 | 46 | #define COMPAT_SYSCALL_DEFINE0(sname) \ |
| 47 | 47 | SYSCALL_METADATA(_##sname, 0); \ |
| 48 | 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 | 50 | asmlinkage long __s390_compat_sys_##sname(void) |
| 51 | 51 | |
| 52 | 52 | #define SYSCALL_DEFINE0(sname) \ |
| @@ -72,7 +72,7 @@ · 19 unmodified lines | ||
| 72 | 72 | asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ |
| 73 | 73 | asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ |
| 74 | 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 | 76 | static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ |
| 77 | 77 | asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ |
| 78 | 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 | 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 | 52 | void clock_comparator_work(void); |
| 58 | 53 | |
| 59 | 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 | 36 | * - length(n_modulus) = inputdatalength |
| 37 | 37 | */ |
| 38 | 38 | struct ica_rsa_modexpo { |
| 39 | − char __user *inputdata; | |
| 40 | − unsigned int inputdatalength; | |
| 41 | − char __user *outputdata; | |
| 42 | − unsigned int outputdatalength; | |
| 43 | − char __user *b_key; | |
| 44 | − char __user *n_modulus; | |
| 39 | + __u8 __user *inputdata; | |
| 40 | + __u32 inputdatalength; | |
| 41 | + __u8 __user *outputdata; | |
| 42 | + __u32 outputdatalength; | |
| 43 | + __u8 __user *b_key; | |
| 44 | + __u8 __user *n_modulus; | |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | 47 | /** |
| @@ -59,15 +59,15 @@ struct ica_rsa_modexpo { · 11 unmodified lines | ||
| 59 | 59 | * - length(u_mult_inv) = inputdatalength/2 + 8 |
| 60 | 60 | */ |
| 61 | 61 | struct ica_rsa_modexpo_crt { |
| 62 | − char __user *inputdata; | |
| 63 | − unsigned int inputdatalength; | |
| 64 | − char __user *outputdata; | |
| 65 | − unsigned int outputdatalength; | |
| 66 | − char __user *bp_key; | |
| 67 | − char __user *bq_key; | |
| 68 | − char __user *np_prime; | |
| 69 | − char __user *nq_prime; | |
| 70 | − char __user *u_mult_inv; | |
| 62 | + __u8 __user *inputdata; | |
| 63 | + __u32 inputdatalength; | |
| 64 | + __u8 __user *outputdata; | |
| 65 | + __u32 outputdatalength; | |
| 66 | + __u8 __user *bp_key; | |
| 67 | + __u8 __user *bq_key; | |
| 68 | + __u8 __user *np_prime; | |
| 69 | + __u8 __user *nq_prime; | |
| 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 | 83 | * key block |
| 84 | 84 | */ |
| 85 | 85 | struct CPRBX { |
| 86 | − unsigned short cprb_len; /* CPRB length 220 */ | |
| 87 | − unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ | |
| 88 | − unsigned char pad_000[3]; /* Alignment pad bytes */ | |
| 89 | − unsigned char func_id[2]; /* function id 0x5432 */ | |
| 90 | − unsigned char cprb_flags[4]; /* Flags */ | |
| 91 | − unsigned int req_parml; /* request parameter buffer len */ | |
| 92 | − unsigned int req_datal; /* request data buffer */ | |
| 93 | − unsigned int rpl_msgbl; /* reply message block length */ | |
| 94 | − unsigned int rpld_parml; /* replied parameter block len */ | |
| 95 | − unsigned int rpl_datal; /* reply data block len */ | |
| 96 | − unsigned int rpld_datal; /* replied data block len */ | |
| 97 | − unsigned int req_extbl; /* request extension block len */ | |
| 98 | − unsigned char pad_001[4]; /* reserved */ | |
| 99 | − unsigned int rpld_extbl; /* replied extension block len */ | |
| 100 | − unsigned char padx000[16 - sizeof(char *)]; | |
| 101 | − unsigned char *req_parmb; /* request parm block 'address' */ | |
| 102 | − unsigned char padx001[16 - sizeof(char *)]; | |
| 103 | − unsigned char *req_datab; /* request data block 'address' */ | |
| 104 | − unsigned char padx002[16 - sizeof(char *)]; | |
| 105 | − unsigned char *rpl_parmb; /* reply parm block 'address' */ | |
| 106 | − unsigned char padx003[16 - sizeof(char *)]; | |
| 107 | − unsigned char *rpl_datab; /* reply data block 'address' */ | |
| 108 | − unsigned char padx004[16 - sizeof(char *)]; | |
| 109 | − unsigned char *req_extb; /* request extension block 'addr'*/ | |
| 110 | − unsigned char padx005[16 - sizeof(char *)]; | |
| 111 | − unsigned char *rpl_extb; /* reply extension block 'address'*/ | |
| 112 | − unsigned short ccp_rtcode; /* server return code */ | |
| 113 | − unsigned short ccp_rscode; /* server reason code */ | |
| 114 | − unsigned int mac_data_len; /* Mac Data Length */ | |
| 115 | − unsigned char logon_id[8]; /* Logon Identifier */ | |
| 116 | − unsigned char mac_value[8]; /* Mac Value */ | |
| 117 | − unsigned char mac_content_flgs;/* Mac content flag byte */ | |
| 118 | − unsigned char pad_002; /* Alignment */ | |
| 119 | − unsigned short domain; /* Domain */ | |
| 120 | − unsigned char usage_domain[4];/* Usage domain */ | |
| 121 | − unsigned char cntrl_domain[4];/* Control domain */ | |
| 122 | − unsigned char S390enf_mask[4];/* S/390 enforcement mask */ | |
| 123 | − unsigned char pad_004[36]; /* reserved */ | |
| 86 | + __u16 cprb_len; /* CPRB length 220 */ | |
| 87 | + __u8 cprb_ver_id; /* CPRB version id. 0x02 */ | |
| 88 | + __u8 pad_000[3]; /* Alignment pad bytes */ | |
| 89 | + __u8 func_id[2]; /* function id 0x5432 */ | |
| 90 | + __u8 cprb_flags[4]; /* Flags */ | |
| 91 | + __u32 req_parml; /* request parameter buffer len */ | |
| 92 | + __u32 req_datal; /* request data buffer */ | |
| 93 | + __u32 rpl_msgbl; /* reply message block length */ | |
| 94 | + __u32 rpld_parml; /* replied parameter block len */ | |
| 95 | + __u32 rpl_datal; /* reply data block len */ | |
| 96 | + __u32 rpld_datal; /* replied data block len */ | |
| 97 | + __u32 req_extbl; /* request extension block len */ | |
| 98 | + __u8 pad_001[4]; /* reserved */ | |
| 99 | + __u32 rpld_extbl; /* replied extension block len */ | |
| 100 | + __u8 padx000[16 - sizeof(__u8 *)]; | |
| 101 | + __u8 __user *req_parmb; /* request parm block 'address' */ | |
| 102 | + __u8 padx001[16 - sizeof(__u8 *)]; | |
| 103 | + __u8 __user *req_datab; /* request data block 'address' */ | |
| 104 | + __u8 padx002[16 - sizeof(__u8 *)]; | |
| 105 | + __u8 __user *rpl_parmb; /* reply parm block 'address' */ | |
| 106 | + __u8 padx003[16 - sizeof(__u8 *)]; | |
| 107 | + __u8 __user *rpl_datab; /* reply data block 'address' */ | |
| 108 | + __u8 padx004[16 - sizeof(__u8 *)]; | |
| 109 | + __u8 __user *req_extb; /* request extension block 'addr'*/ | |
| 110 | + __u8 padx005[16 - sizeof(__u8 *)]; | |
| 111 | + __u8 __user *rpl_extb; /* reply extension block 'address'*/ | |
| 112 | + __u16 ccp_rtcode; /* server return code */ | |
| 113 | + __u16 ccp_rscode; /* server reason code */ | |
| 114 | + __u32 mac_data_len; /* Mac Data Length */ | |
| 115 | + __u8 logon_id[8]; /* Logon Identifier */ | |
| 116 | + __u8 mac_value[8]; /* Mac Value */ | |
| 117 | + __u8 mac_content_flgs; /* Mac content flag byte */ | |
| 118 | + __u8 pad_002; /* Alignment */ | |
| 119 | + __u16 domain; /* Domain */ | |
| 120 | + __u8 usage_domain[4]; /* Usage domain */ | |
| 121 | + __u8 cntrl_domain[4]; /* Control domain */ | |
| 122 | + __u8 S390enf_mask[4]; /* S/390 enforcement mask */ | |
| 123 | + __u8 pad_004[36]; /* reserved */ | |
| 124 | 124 | } __attribute__((packed)); |
| 125 | 125 | |
| 126 | 126 | /** |
| 127 | 127 | * xcRB |
| 128 | 128 | */ |
| 129 | 129 | struct ica_xcRB { |
| 130 | − unsigned short agent_ID; | |
| 131 | − unsigned int user_defined; | |
| 132 | − unsigned short request_ID; | |
| 133 | − unsigned int request_control_blk_length; | |
| 134 | − unsigned char padding1[16 - sizeof(char *)]; | |
| 135 | − char __user *request_control_blk_addr; | |
| 136 | − unsigned int request_data_length; | |
| 137 | − char padding2[16 - sizeof(char *)]; | |
| 138 | − char __user *request_data_address; | |
| 139 | − unsigned int reply_control_blk_length; | |
| 140 | − char padding3[16 - sizeof(char *)]; | |
| 141 | − char __user *reply_control_blk_addr; | |
| 142 | − unsigned int reply_data_length; | |
| 143 | − char padding4[16 - sizeof(char *)]; | |
| 144 | − char __user *reply_data_addr; | |
| 145 | − unsigned short priority_window; | |
| 146 | − unsigned int status; | |
| 130 | + __u16 agent_ID; | |
| 131 | + __u32 user_defined; | |
| 132 | + __u16 request_ID; | |
| 133 | + __u32 request_control_blk_length; | |
| 134 | + __u8 _padding1[16 - sizeof(__u8 *)]; | |
| 135 | + __u8 __user *request_control_blk_addr; | |
| 136 | + __u32 request_data_length; | |
| 137 | + __u8 _padding2[16 - sizeof(__u8 *)]; | |
| 138 | + __u8 __user *request_data_address; | |
| 139 | + __u32 reply_control_blk_length; | |
| 140 | + __u8 _padding3[16 - sizeof(__u8 *)]; | |
| 141 | + __u8 __user *reply_control_blk_addr; | |
| 142 | + __u32 reply_data_length; | |
| 143 | + __u8 __padding4[16 - sizeof(__u8 *)]; | |
| 144 | + __u8 __user *reply_data_addr; | |
| 145 | + __u16 priority_window; | |
| 146 | + __u32 status; | |
| 147 | 147 | } __attribute__((packed)); |
| 148 | 148 | |
| 149 | 149 | /** |
| @@ -549,8 +549,7 @@ static int get_mem_chunk_cnt(void) · 548 unmodified lines | ||
| 549 | 549 | int cnt = 0; |
| 550 | 550 | u64 idx; |
| 551 | 551 | |
| 552 | − for_each_mem_range(idx, &memblock.physmem, &oldmem_type, NUMA_NO_NODE, | |
| 553 | − MEMBLOCK_NONE, NULL, NULL, NULL) | |
| 552 | + for_each_physmem_range(idx, &oldmem_type, NULL, NULL) | |
| 554 | 553 | cnt++; |
| 555 | 554 | return cnt; |
| 556 | 555 | } |
| @@ -563,8 +562,7 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset) · 6 unmodified lines | ||
| 563 | 562 | phys_addr_t start, end; |
| 564 | 563 | u64 idx; |
| 565 | 564 | |
| 566 | − for_each_mem_range(idx, &memblock.physmem, &oldmem_type, NUMA_NO_NODE, | |
| 567 | − MEMBLOCK_NONE, &start, &end, NULL) { | |
| 565 | + for_each_physmem_range(idx, &oldmem_type, &start, &end) { | |
| 568 | 566 | phdr->p_filesz = end - start; |
| 569 | 567 | phdr->p_type = PT_LOAD; |
| 570 | 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 | 90 | size_t user_buf_size, loff_t *offset); |
| 91 | 91 | static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view, |
| 92 | 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 | 93 | static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view, |
| 100 | 94 | char *out_buf, debug_sprintf_entry_t *curr_event); |
| 101 | 95 | |
| 102 | 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 | 98 | struct debug_view debug_hex_ascii_view = { |
| 115 | 99 | "hex_ascii", |
| 116 | 100 | NULL, |
| @@ -1385,32 +1369,6 @@ out: · 1268 unmodified lines | ||
| 1385 | 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 | 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 | 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 | 376 | ENTRY(system_call) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/init.h> |
| 15 | 15 | #include <linux/cpu.h> |
| 16 | 16 | #include <linux/sched/cputime.h> |
| 17 | +#include <trace/events/power.h> | |
| 17 | 18 | #include <asm/nmi.h> |
| 18 | 19 | #include <asm/smp.h> |
| 19 | 20 | #include "entry.h" |
| @@ -32,11 +33,12 @@ void enabled_wait(void) · 12 unmodified lines | ||
| 32 | 33 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; |
| 33 | 34 | clear_cpu_flag(CIF_NOHZ_DELAY); |
| 34 | 35 | |
| 36 | + trace_cpu_idle_rcuidle(1, smp_processor_id()); | |
| 35 | 37 | local_irq_save(flags); |
| 36 | 38 | /* Call the assembler magic in entry.S */ |
| 37 | 39 | psw_idle(idle, psw_mask); |
| 38 | 40 | local_irq_restore(flags); |
| 39 | − | |
| 41 | + trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); | |
| 40 | 42 | |
| 41 | 43 | /* Account time spent with enabled wait psw loaded as idle time. */ |
| 42 | 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 | 523 | * zero, try to fix up. |
| 524 | 524 | */ |
| 525 | 525 | entry = s390_search_extables(regs->psw.addr); |
| 526 | − if (entry) { | |
| 527 | − regs->psw.addr = extable_fixup(entry); | |
| 526 | + if (entry && ex_handle(entry, regs)) | |
| 528 | 527 | return 1; |
| 529 | − } | |
| 530 | 528 | |
| 531 | 529 | /* |
| 532 | 530 | * fixup_exception() could not handle it, |
| @@ -167,7 +167,7 @@ static struct timer_list lgr_timer; · 166 unmodified lines | ||
| 167 | 167 | */ |
| 168 | 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 | 1127 | free_mem_detect_info(); |
| 1128 | 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 | 1130 | if (is_prot_virt_host()) |
| 1139 | 1131 | setup_uv(); |
| 1140 | 1132 | setup_memory_end(); |
| @@ -1012,10 +1012,6 @@ void __init smp_prepare_boot_cpu(void) · 1011 unmodified lines | ||
| 1012 | 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 | 1015 | void __init smp_setup_processor_id(void) |
| 1020 | 1016 | { |
| 1021 | 1017 | pcpu_devices[0].address = stap(); |
| @@ -1145,6 +1141,7 @@ static int smp_cpu_online(unsigned int cpu) · 123 unmodified lines | ||
| 1145 | 1141 | |
| 1146 | 1142 | return sysfs_create_group(&s->kobj, &cpu_online_attr_group); |
| 1147 | 1143 | } |
| 1144 | + | |
| 1148 | 1145 | static int smp_cpu_pre_down(unsigned int cpu) |
| 1149 | 1146 | { |
| 1150 | 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 | 237 | preempt_disable(); /* protect from changes to steering parameters */ |
| 238 | 238 | now = get_tod_clock(); |
| 239 | 239 | adj = tod_steering_end - now; |
| 240 | − if (unlikely((s64) adj >= 0)) | |
| 240 | + if (unlikely((s64) adj > 0)) | |
| 241 | 241 | /* |
| 242 | 242 | * manually steer by 1 cycle every 2^16 cycles. This |
| 243 | 243 | * corresponds to shifting the tod delta by 15. 1s is |
| @@ -253,7 +253,7 @@ static struct clocksource clocksource_tod = { · 9 unmodified lines | ||
| 253 | 253 | .name = "tod", |
| 254 | 254 | .rating = 400, |
| 255 | 255 | .read = read_tod_clock, |
| 256 | − .mask = -1ULL, | |
| 256 | + .mask = CLOCKSOURCE_MASK(64), | |
| 257 | 257 | .mult = 1000, |
| 258 | 258 | .shift = 12, |
| 259 | 259 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| @@ -669,7 +669,7 @@ static void stp_work_fn(struct work_struct *work) · 409 unmodified lines | ||
| 669 | 669 | * There is a usable clock but the synchonization failed. |
| 670 | 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 | 674 | out_unlock: |
| 675 | 675 | mutex_unlock(&stp_work_mutex); |
| @@ -683,7 +683,7 @@ static struct bus_type stp_subsys = { · 7 unmodified lines | ||
| 683 | 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 | 687 | struct device_attribute *attr, |
| 688 | 688 | char *buf) |
| 689 | 689 | { |
| @@ -693,9 +693,9 @@ static ssize_t stp_ctn_id_show(struct device *dev, · 3 unmodified lines | ||
| 693 | 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 | 699 | struct device_attribute *attr, |
| 700 | 700 | char *buf) |
| 701 | 701 | { |
| @@ -704,9 +704,9 @@ static ssize_t stp_ctn_type_show(struct device *dev, · 2 unmodified lines | ||
| 704 | 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 | 710 | struct device_attribute *attr, |
| 711 | 711 | char *buf) |
| 712 | 712 | { |
| @@ -715,9 +715,9 @@ static ssize_t stp_dst_offset_show(struct device *dev, · 2 unmodified lines | ||
| 715 | 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 | 721 | struct device_attribute *attr, |
| 722 | 722 | char *buf) |
| 723 | 723 | { |
| @@ -726,9 +726,9 @@ static ssize_t stp_leap_seconds_show(struct device *dev, · 2 unmodified lines | ||
| 726 | 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 | 732 | struct device_attribute *attr, |
| 733 | 733 | char *buf) |
| 734 | 734 | { |
| @@ -737,9 +737,9 @@ static ssize_t stp_stratum_show(struct device *dev, · 2 unmodified lines | ||
| 737 | 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 | 743 | struct device_attribute *attr, |
| 744 | 744 | char *buf) |
| 745 | 745 | { |
| @@ -748,9 +748,9 @@ static ssize_t stp_time_offset_show(struct device *dev, · 2 unmodified lines | ||
| 748 | 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 | 754 | struct device_attribute *attr, |
| 755 | 755 | char *buf) |
| 756 | 756 | { |
| @@ -759,10 +759,9 @@ static ssize_t stp_time_zone_offset_show(struct device *dev, · 2 unmodified lines | ||
| 759 | 759 | return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); |
| 760 | 760 | } |
| 761 | 761 | |
| 762 | −static DEVICE_ATTR(time_zone_offset, 0400, | |
| 763 | − stp_time_zone_offset_show, NULL); | |
| 762 | +static DEVICE_ATTR_RO(time_zone_offset); | |
| 764 | 763 | |
| 765 | −static ssize_t stp_timing_mode_show(struct device *dev, | |
| 764 | +static ssize_t timing_mode_show(struct device *dev, | |
| 766 | 765 | struct device_attribute *attr, |
| 767 | 766 | char *buf) |
| 768 | 767 | { |
| @@ -771,9 +770,9 @@ static ssize_t stp_timing_mode_show(struct device *dev, · 2 unmodified lines | ||
| 771 | 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 | 776 | struct device_attribute *attr, |
| 778 | 777 | char *buf) |
| 779 | 778 | { |
| @@ -782,16 +781,16 @@ static ssize_t stp_timing_state_show(struct device *dev, · 2 unmodified lines | ||
| 782 | 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 | 787 | struct device_attribute *attr, |
| 789 | 788 | char *buf) |
| 790 | 789 | { |
| 791 | 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 | 794 | struct device_attribute *attr, |
| 796 | 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 | 816 | * Can't use DEVICE_ATTR because the attribute should be named |
| 818 | 817 | * stp/online but dev_attr_online already exists in this file .. |
| 819 | 818 | */ |
| 820 | −static struct device_attribute dev_attr_stp_online = { | |
| 821 | − .attr = { .name = "online", .mode = 0600 }, | |
| 822 | − .show = stp_online_show, | |
| 823 | − .store = stp_online_store, | |
| 824 | −}; | |
| 819 | +static DEVICE_ATTR_RW(online); | |
| 825 | 820 | |
| 826 | 821 | static struct device_attribute *stp_attributes[] = { |
| 827 | 822 | &dev_attr_ctn_id, |
| 828 | 823 | &dev_attr_ctn_type, |
| 829 | 824 | &dev_attr_dst_offset, |
| 830 | 825 | &dev_attr_leap_seconds, |
| 831 | − &dev_attr_stp_online, | |
| 826 | + &dev_attr_online, | |
| 832 | 827 | &dev_attr_stratum, |
| 833 | 828 | &dev_attr_time_offset, |
| 834 | 829 | &dev_attr_time_zone_offset, |
| @@ -356,9 +356,9 @@ static atomic_t topology_poll = ATOMIC_INIT(0); · 355 unmodified lines | ||
| 356 | 356 | static void set_topology_timer(void) |
| 357 | 357 | { |
| 358 | 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 | 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 | 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 | 50 | } else { |
| 51 | 51 | const struct exception_table_entry *fixup; |
| 52 | 52 | fixup = s390_search_extables(regs->psw.addr); |
| 53 | − if (fixup) | |
| 54 | − regs->psw.addr = extable_fixup(fixup); | |
| 55 | − else { | |
| 53 | + if (!fixup || !ex_handle(fixup, regs)) | |
| 56 | 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 | 248 | case BUG_TRAP_TYPE_NONE: |
| 252 | 249 | fixup = s390_search_extables(regs->psw.addr); |
| 253 | 250 | if (fixup) |
| 254 | − regs->psw.addr = extable_fixup(fixup); | |
| 251 | + ex_handle(fixup, regs); | |
| 255 | 252 | break; |
| 256 | 253 | case BUG_TRAP_TYPE_WARN: |
| 257 | 254 | break; |
| @@ -14,3 +14,5 @@ KASAN_SANITIZE_uaccess.o := n · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | obj-$(CONFIG_S390_UNWIND_SELFTEST) += test_unwind.o |
| 16 | 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 | 189 | del_timer(&cmm_timer); |
| 190 | 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 | 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 | 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 | 316 | seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL); |
| 322 | 317 | if (seg->res == NULL) { |
| 323 | 318 | rc = -ENOMEM; |
| 324 | − goto out_shared; | |
| 319 | + goto out_free; | |
| 325 | 320 | } |
| 326 | 321 | seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; |
| 327 | 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 | 330 | if (rc == SEG_TYPE_SC || |
| 336 | 331 | ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared)) |
| 337 | 332 | seg->res->flags |= IORESOURCE_READONLY; |
| 333 | + | |
| 334 | + /* Check for overlapping resources before adding the mapping. */ | |
| 338 | 335 | if (request_resource(&iomem_resource, seg->res)) { |
| 339 | 336 | rc = -EBUSY; |
| 340 | − kfree(seg->res); | |
| 341 | − goto out_shared; | |
| 337 | + goto out_free_resource; | |
| 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 | 344 | if (do_nonshared) |
| 345 | 345 | diag_cc = dcss_diag(&loadnsr_scode, seg->dcss_name, |
| 346 | 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 | 351 | dcss_diag(&purgeseg_scode, seg->dcss_name, |
| 352 | 352 | &dummy, &dummy); |
| 353 | 353 | rc = diag_cc; |
| 354 | − goto out_resource; | |
| 354 | + goto out_mapping; | |
| 355 | 355 | } |
| 356 | 356 | if (diag_cc > 1) { |
| 357 | 357 | pr_warn("Loading DCSS %s failed with rc=%ld\n", name, end_addr); |
| 358 | 358 | rc = dcss_diag_translate_rc(end_addr); |
| 359 | 359 | dcss_diag(&purgeseg_scode, seg->dcss_name, |
| 360 | 360 | &dummy, &dummy); |
| 361 | − goto out_resource; | |
| 361 | + goto out_mapping; | |
| 362 | 362 | } |
| 363 | 363 | seg->start_addr = start_addr; |
| 364 | 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 | 377 | (void*) seg->end, segtype_string[seg->vm_segtype]); |
| 378 | 378 | } |
| 379 | 379 | goto out; |
| 380 | + out_mapping: | |
| 381 | + vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); | |
| 380 | 382 | out_resource: |
| 381 | 383 | release_resource(seg->res); |
| 384 | + out_free_resource: | |
| 382 | 385 | kfree(seg->res); |
| 383 | − out_shared: | |
| 384 | − vmem_remove_mapping(seg->start_addr, seg->end - seg->start_addr + 1); | |
| 385 | 386 | out_free: |
| 386 | 387 | kfree(seg); |
| 387 | 388 | out: |
| @@ -400,8 +401,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long · 12 unmodified lines | ||
| 400 | 401 | * -EIO : could not perform query or load diagnose |
| 401 | 402 | * -ENOENT : no such segment |
| 402 | 403 | * -EOPNOTSUPP: multi-part segment cannot be used with linux |
| 403 | − * -ENOSPC : segment cannot be used (overlaps with storage) | |
| 404 | − * -EBUSY : segment can temporarily not be used (overlaps with dcss) | |
| 404 | + * -EBUSY : segment cannot be used (overlaps with dcss or storage) | |
| 405 | 405 | * -ERANGE : segment cannot be used (exceeds kernel mapping range) |
| 406 | 406 | * -EPERM : segment is currently loaded with incompatible permissions |
| 407 | 407 | * -ENOMEM : out of memory |
| @@ -626,10 +626,6 @@ void segment_warning(int rc, char *seg_name) · 218 unmodified lines | ||
| 626 | 626 | pr_err("DCSS %s has multiple page ranges and cannot be " |
| 627 | 627 | "loaded or queried\n", seg_name); |
| 628 | 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 | 629 | case -EBUSY: |
| 634 | 630 | pr_err("%s needs used memory resources and cannot be " |
| 635 | 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 | 256 | /* Are we prepared to handle this kernel fault? */ |
| 257 | 257 | fixup = s390_search_extables(regs->psw.addr); |
| 258 | − if (fixup) { | |
| 259 | − regs->psw.addr = extable_fixup(fixup); | |
| 258 | + if (fixup && ex_handle(fixup, regs)) | |
| 260 | 259 | return; |
| 261 | − } | |
| 262 | 260 | |
| 263 | 261 | /* |
| 264 | 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 | 374 | * routines. |
| 377 | 375 | * |
| 378 | 376 | * interruption code (int_code): |
| 379 | − * 04 Protection -> Write-Protection (suprression) | |
| 377 | + * 04 Protection -> Write-Protection (suppression) | |
| 380 | 378 | * 10 Segment translation -> Not present (nullification) |
| 381 | 379 | * 11 Page translation -> Not present (nullification) |
| 382 | 380 | * 3b Region third trans. -> Not present (nullification) |
| @@ -20,14 +20,6 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 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 | 23 | static void __ref *vmem_alloc_pages(unsigned int order) |
| 32 | 24 | { |
| 33 | 25 | unsigned long size = PAGE_SIZE << order; |
| @@ -37,6 +29,15 @@ static void __ref *vmem_alloc_pages(unsigned int order) · 3 unmodified lines | ||
| 37 | 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 | 41 | void *vmem_crst_alloc(unsigned long val) |
| 41 | 42 | { |
| 42 | 43 | unsigned long *table; |
| @@ -62,332 +63,486 @@ pte_t __ref *vmem_pte_alloc(void) · 19 unmodified lines | ||
| 62 | 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; | |
| 71 | − unsigned long pages4k, pages1m, pages2g; | |
| 72 | − unsigned long end = start + size; | |
| 73 | − unsigned long address = start; | |
| 74 | − pgd_t *pg_dir; | |
| 75 | − p4d_t *p4_dir; | |
| 76 | − pud_t *pu_dir; | |
| 77 | − pmd_t *pm_dir; | |
| 78 | − pte_t *pt_dir; | |
| 79 | − int ret = -ENOMEM; | |
| 85 | + if (!unused_pmd_start) | |
| 86 | + return; | |
| 87 | + memset(__va(unused_pmd_start), PAGE_UNUSED, | |
| 88 | + ALIGN(unused_pmd_start, PMD_SIZE) - unused_pmd_start); | |
| 89 | + unused_pmd_start = 0; | |
| 90 | +} | |
| 91 | + | |
| 92 | +static void __vmemmap_use_sub_pmd(unsigned long start, unsigned long end) | |
| 93 | +{ | |
| 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); | |
| 82 | − sgt_prot = pgprot_val(SEGMENT_KERNEL); | |
| 83 | − r3_prot = pgprot_val(REGION3_KERNEL); | |
| 84 | − if (!MACHINE_HAS_NX) { | |
| 85 | − pgt_prot &= ~_PAGE_NOEXEC; | |
| 86 | − sgt_prot &= ~_SEGMENT_ENTRY_NOEXEC; | |
| 87 | − r3_prot &= ~_REGION_ENTRY_NOEXEC; | |
| 103 | +static void vmemmap_use_sub_pmd(unsigned long start, unsigned long end) | |
| 104 | +{ | |
| 105 | + /* | |
| 106 | + * We only optimize if the new used range directly follows the | |
| 107 | + * previously unused range (esp., when populating consecutive sections). | |
| 108 | + */ | |
| 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; | |
| 90 | − while (address < end) { | |
| 91 | − pg_dir = pgd_offset_k(address); | |
| 92 | − if (pgd_none(*pg_dir)) { | |
| 93 | − p4_dir = vmem_crst_alloc(_REGION2_ENTRY_EMPTY); | |
| 94 | − if (!p4_dir) | |
| 95 | − goto out; | |
| 96 | − pgd_populate(&init_mm, pg_dir, p4_dir); | |
| 97 | − } | |
| 98 | − p4_dir = p4d_offset(pg_dir, address); | |
| 99 | − if (p4d_none(*p4_dir)) { | |
| 100 | − pu_dir = vmem_crst_alloc(_REGION3_ENTRY_EMPTY); | |
| 101 | − if (!pu_dir) | |
| 102 | − goto out; | |
| 103 | − p4d_populate(&init_mm, p4_dir, pu_dir); | |
| 104 | − } | |
| 105 | − pu_dir = pud_offset(p4_dir, address); | |
| 106 | − if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address && | |
| 107 | − !(address & ~PUD_MASK) && (address + PUD_SIZE <= end) && | |
| 108 | − !debug_pagealloc_enabled()) { | |
| 109 | − pud_val(*pu_dir) = address | r3_prot; | |
| 110 | − address += PUD_SIZE; | |
| 111 | − pages2g++; | |
| 112 | − continue; | |
| 113 | − } | |
| 114 | − if (pud_none(*pu_dir)) { | |
| 115 | − pm_dir = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY); | |
| 116 | − if (!pm_dir) | |
| 117 | − goto out; | |
| 118 | − pud_populate(&init_mm, pu_dir, pm_dir); | |
| 119 | − } | |
| 120 | − pm_dir = pmd_offset(pu_dir, address); | |
| 121 | − if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address && | |
| 122 | − !(address & ~PMD_MASK) && (address + PMD_SIZE <= end) && | |
| 123 | − !debug_pagealloc_enabled()) { | |
| 124 | − pmd_val(*pm_dir) = address | sgt_prot; | |
| 125 | − address += PMD_SIZE; | |
| 126 | − pages1m++; | |
| 115 | + vmemmap_flush_unused_pmd(); | |
| 116 | + __vmemmap_use_sub_pmd(start, end); | |
| 117 | +} | |
| 118 | + | |
| 119 | +static void vmemmap_use_new_sub_pmd(unsigned long start, unsigned long end) | |
| 120 | +{ | |
| 121 | + void *page = __va(ALIGN_DOWN(start, PMD_SIZE)); | |
| 122 | + | |
| 123 | + vmemmap_flush_unused_pmd(); | |
| 124 | + | |
| 125 | + /* Could be our memmap page is filled with PAGE_UNUSED already ... */ | |
| 126 | + __vmemmap_use_sub_pmd(start, end); | |
| 127 | + | |
| 128 | + /* Mark the unused parts of the new memmap page PAGE_UNUSED. */ | |
| 129 | + if (!IS_ALIGNED(start, PMD_SIZE)) | |
| 130 | + memset(page, PAGE_UNUSED, start - __pa(page)); | |
| 131 | + /* | |
| 132 | + * We want to avoid memset(PAGE_UNUSED) when populating the vmemmap of | |
| 133 | + * consecutive sections. Remember for the last added PMD the last | |
| 134 | + * unused range in the populated PMD. | |
| 135 | + */ | |
| 136 | + if (!IS_ALIGNED(end, PMD_SIZE)) | |
| 137 | + unused_pmd_start = end; | |
| 138 | +} | |
| 139 | + | |
| 140 | +/* Returns true if the PMD is completely unused and can be freed. */ | |
| 141 | +static bool vmemmap_unuse_sub_pmd(unsigned long start, unsigned long end) | |
| 142 | +{ | |
| 143 | + void *page = __va(ALIGN_DOWN(start, PMD_SIZE)); | |
| 144 | + | |
| 145 | + vmemmap_flush_unused_pmd(); | |
| 146 | + memset(__va(start), PAGE_UNUSED, end - start); | |
| 147 | + return !memchr_inv(page, PAGE_UNUSED, PMD_SIZE); | |
| 148 | +} | |
| 149 | + | |
| 150 | +/* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */ | |
| 151 | +static int __ref modify_pte_table(pmd_t *pmd, unsigned long addr, | |
| 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 | 181 | continue; |
| 128 | 182 | } |
| 129 | − if (pmd_none(*pm_dir)) { | |
| 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++; | |
| 183 | + pages++; | |
| 140 | 184 | } |
| 141 | 185 | ret = 0; |
| 142 | 186 | out: |
| 143 | − update_page_count(PG_DIRECT_MAP_4K, pages4k); | |
| 144 | − update_page_count(PG_DIRECT_MAP_1M, pages1m); | |
| 145 | − update_page_count(PG_DIRECT_MAP_2G, pages2g); | |
| 187 | + if (direct) | |
| 188 | + update_page_count(PG_DIRECT_MAP_4K, add ? pages : -pages); | |
| 146 | 189 | return ret; |
| 147 | 190 | } |
| 148 | 191 | |
| 149 | −/* | |
| 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) | |
| 192 | +static void try_free_pte_table(pmd_t *pmd, unsigned long start) | |
| 154 | 193 | { |
| 155 | − unsigned long pages4k, pages1m, pages2g; | |
| 156 | − unsigned long end = start + size; | |
| 157 | − unsigned long address = start; | |
| 158 | − pgd_t *pg_dir; | |
| 159 | − p4d_t *p4_dir; | |
| 160 | − pud_t *pu_dir; | |
| 161 | − pmd_t *pm_dir; | |
| 162 | − pte_t *pt_dir; | |
| 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++; | |
| 194 | + pte_t *pte; | |
| 195 | + int i; | |
| 196 | + | |
| 197 | + /* We can safely assume this is fully in 1:1 mapping & vmemmap area */ | |
| 198 | + pte = pte_offset_kernel(pmd, start); | |
| 199 | + for (i = 0; i < PTRS_PER_PTE; i++, pte++) { | |
| 200 | + if (!pte_none(*pte)) | |
| 201 | + return; | |
| 202 | 202 | } |
| 203 | − flush_tlb_kernel_range(start, end); | |
| 204 | − update_page_count(PG_DIRECT_MAP_4K, -pages4k); | |
| 205 | − update_page_count(PG_DIRECT_MAP_1M, -pages1m); | |
| 206 | − update_page_count(PG_DIRECT_MAP_2G, -pages2g); | |
| 203 | + vmem_pte_free(__va(pmd_deref(*pmd))); | |
| 204 | + pmd_clear(pmd); | |
| 207 | 205 | } |
| 208 | 206 | |
| 209 | −/* | |
| 210 | − * Add a backed mem_map array to the virtual mem_map array. | |
| 211 | − */ | |
| 212 | −int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, | |
| 213 | − struct vmem_altmap *altmap) | |
| 207 | +/* __ref: we'll only call vmemmap_alloc_block() via vmemmap_populate() */ | |
| 208 | +static int __ref modify_pmd_table(pud_t *pud, unsigned long addr, | |
| 209 | + unsigned long end, bool add, bool direct) | |
| 214 | 210 | { |
| 215 | − unsigned long pgt_prot, sgt_prot; | |
| 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; | |
| 211 | + unsigned long next, prot, pages = 0; | |
| 222 | 212 | int ret = -ENOMEM; |
| 213 | + pmd_t *pmd; | |
| 214 | + pte_t *pte; | |
| 223 | 215 | |
| 224 | − pgt_prot = pgprot_val(PAGE_KERNEL); | |
| 225 | − sgt_prot = pgprot_val(SEGMENT_KERNEL); | |
| 226 | − if (!MACHINE_HAS_NX) { | |
| 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 | − } | |
| 216 | + prot = pgprot_val(SEGMENT_KERNEL); | |
| 217 | + if (!MACHINE_HAS_NX) | |
| 218 | + prot &= ~_SEGMENT_ENTRY_NOEXEC; | |
| 238 | 219 | |
| 239 | − p4_dir = p4d_offset(pg_dir, address); | |
| 240 | − if (p4d_none(*p4_dir)) { | |
| 241 | − pu_dir = vmem_crst_alloc(_REGION3_ENTRY_EMPTY); | |
| 242 | − if (!pu_dir) | |
| 243 | − goto out; | |
| 244 | − p4d_populate(&init_mm, p4_dir, pu_dir); | |
| 245 | − } | |
| 220 | + pmd = pmd_offset(pud, addr); | |
| 221 | + for (; addr < end; addr = next, pmd++) { | |
| 222 | + next = pmd_addr_end(addr, end); | |
| 223 | + if (!add) { | |
| 224 | + if (pmd_none(*pmd)) | |
| 225 | + continue; | |
| 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); | |
| 248 | − if (pud_none(*pu_dir)) { | |
| 249 | − pm_dir = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY); | |
| 250 | − if (!pm_dir) | |
| 250 | + /* | |
| 251 | + * Use 1MB frames for vmemmap if available. We | |
| 252 | + * always use large frames even if they are only | |
| 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 | 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); | |
| 256 | − if (pmd_none(*pm_dir)) { | |
| 257 | − /* Use 1MB frames for vmemmap if available. We always | |
| 258 | − * use large frames even if they are only partially | |
| 259 | − * used. | |
| 260 | − * Otherwise we would have also page tables since | |
| 261 | − * vmemmap_populate gets called for each section | |
| 262 | − * separately. */ | |
| 263 | − if (MACHINE_HAS_EDAT1) { | |
| 264 | − void *new_page; | |
| 289 | +static void try_free_pmd_table(pud_t *pud, unsigned long start) | |
| 290 | +{ | |
| 291 | + const unsigned long end = start + PUD_SIZE; | |
| 292 | + pmd_t *pmd; | |
| 293 | + int i; | |
| 294 | + | |
| 295 | + /* Don't mess with any tables not fully in 1:1 mapping & vmemmap area */ | |
| 296 | + if (end > VMALLOC_START) | |
| 297 | + return; | |
| 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); | |
| 267 | − if (!new_page) | |
| 268 | − goto out; | |
| 269 | − pmd_val(*pm_dir) = __pa(new_page) | sgt_prot; | |
| 270 | − address = (address + PMD_SIZE) & PMD_MASK; | |
| 310 | +static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end, | |
| 311 | + bool add, bool direct) | |
| 312 | +{ | |
| 313 | + unsigned long next, prot, pages = 0; | |
| 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 | 342 | continue; |
| 272 | 343 | } |
| 273 | − pt_dir = vmem_pte_alloc(); | |
| 274 | − if (!pt_dir) | |
| 344 | + pmd = vmem_crst_alloc(_SEGMENT_ENTRY_EMPTY); | |
| 345 | + if (!pmd) | |
| 275 | 346 | goto out; |
| 276 | − pmd_populate(&init_mm, pm_dir, pt_dir); | |
| 277 | − } else if (pmd_large(*pm_dir)) { | |
| 278 | − address = (address + PMD_SIZE) & PMD_MASK; | |
| 347 | + pud_populate(&init_mm, pud, pmd); | |
| 348 | + } else if (pud_large(*pud)) { | |
| 279 | 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); | |
| 283 | − if (pte_none(*pt_dir)) { | |
| 284 | − void *new_page; | |
| 364 | +static void try_free_pud_table(p4d_t *p4d, unsigned long start) | |
| 365 | +{ | |
| 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); | |
| 287 | − if (!new_page) | |
| 387 | +static int modify_p4d_table(pgd_t *pgd, unsigned long addr, unsigned long end, | |
| 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 | 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 | 412 | ret = 0; |
| 294 | 413 | out: |
| 295 | 414 | return ret; |
| 296 | 415 | } |
| 297 | 416 | |
| 298 | −void vmemmap_free(unsigned long start, unsigned long end, | |
| 299 | − struct vmem_altmap *altmap) | |
| 417 | +static void try_free_p4d_table(pgd_t *pgd, unsigned long start) | |
| 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 | −/* | |
| 304 | − * Add memory segment to the segment list if it doesn't overlap with | |
| 305 | − * an already present segment. | |
| 306 | − */ | |
| 307 | −static int insert_memory_segment(struct memory_segment *seg) | |
| 440 | +static int modify_pagetable(unsigned long start, unsigned long end, bool add, | |
| 441 | + bool direct) | |
| 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 || | |
| 312 | − seg->start + seg->size < seg->start) | |
| 313 | − return -ERANGE; | |
| 448 | + if (WARN_ON_ONCE(!PAGE_ALIGNED(start | end))) | |
| 449 | + return -EINVAL; | |
| 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) { | |
| 316 | − if (seg->start >= tmp->start + tmp->size) | |
| 317 | − continue; | |
| 318 | − if (seg->start + seg->size <= tmp->start) | |
| 319 | − continue; | |
| 320 | − return -ENOSPC; | |
| 454 | + if (!add) { | |
| 455 | + if (pgd_none(*pgd)) | |
| 456 | + continue; | |
| 457 | + } else if (pgd_none(*pgd)) { | |
| 458 | + p4d = vmem_crst_alloc(_REGION2_ENTRY_EMPTY); | |
| 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); | |
| 323 | − return 0; | |
| 469 | + ret = 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); | |
| 337 | − vmem_remove_range(seg->start, seg->size); | |
| 499 | + remove_pagetable(start, start + size, true); | |
| 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 | 508 | int ret; |
| 344 | 509 | |
| 345 | 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; | |
| 348 | − list_for_each_entry(seg, &mem_segs, list) { | |
| 349 | − if (seg->start == start && seg->size == size) | |
| 350 | − break; | |
| 351 | − } | |
| 352 | − | |
| 353 | − if (seg->start != start || seg->size != size) | |
| 354 | − goto out; | |
| 519 | +void vmemmap_free(unsigned long start, unsigned long end, | |
| 520 | + struct vmem_altmap *altmap) | |
| 521 | +{ | |
| 522 | + mutex_lock(&vmem_mutex); | |
| 523 | + remove_pagetable(start, end, false); | |
| 524 | + mutex_unlock(&vmem_mutex); | |
| 525 | +} | |
| 355 | 526 | |
| 356 | − ret = 0; | |
| 357 | − __remove_shared_memory(seg); | |
| 358 | − kfree(seg); | |
| 359 | −out: | |
| 527 | +void vmem_remove_mapping(unsigned long start, unsigned long size) | |
| 528 | +{ | |
| 529 | + mutex_lock(&vmem_mutex); | |
| 530 | + vmem_remove_range(start, size); | |
| 360 | 531 | mutex_unlock(&vmem_mutex); |
| 361 | − return ret; | |
| 362 | 532 | } |
| 363 | 533 | |
| 364 | 534 | int vmem_add_mapping(unsigned long start, unsigned long size) |
| 365 | 535 | { |
| 366 | − struct memory_segment *seg; | |
| 367 | 536 | int ret; |
| 368 | 537 | |
| 369 | − mutex_lock(&vmem_mutex); | |
| 370 | − ret = -ENOMEM; | |
| 371 | − seg = kzalloc(sizeof(*seg), GFP_KERNEL); | |
| 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; | |
| 538 | + if (start + size > VMEM_MAX_PHYS || | |
| 539 | + start + size < start) | |
| 540 | + return -ERANGE; | |
| 380 | 541 | |
| 381 | − ret = vmem_add_mem(start, size); | |
| 542 | + mutex_lock(&vmem_mutex); | |
| 543 | + ret = vmem_add_range(start, size); | |
| 382 | 544 | if (ret) |
| 383 | − goto out_remove; | |
| 384 | − goto out; | |
| 385 | − | |
| 386 | −out_remove: | |
| 387 | − __remove_shared_memory(seg); | |
| 388 | −out_free: | |
| 389 | − kfree(seg); | |
| 390 | −out: | |
| 545 | + vmem_remove_range(start, size); | |
| 391 | 546 | mutex_unlock(&vmem_mutex); |
| 392 | 547 | return ret; |
| 393 | 548 | } |
| @@ -402,7 +557,7 @@ void __init vmem_map_init(void) · 8 unmodified lines | ||
| 402 | 557 | struct memblock_region *reg; |
| 403 | 558 | |
| 404 | 559 | for_each_memblock(memory, reg) |
| 405 | − vmem_add_mem(reg->base, reg->size); | |
| 560 | + vmem_add_range(reg->base, reg->size); | |
| 406 | 561 | __set_memory((unsigned long)_stext, |
| 407 | 562 | (unsigned long)(_etext - _stext) >> PAGE_SHIFT, |
| 408 | 563 | SET_MEMORY_RO | SET_MEMORY_X); |
| @@ -421,27 +576,3 @@ void __init vmem_map_init(void) · 12 unmodified lines | ||
| 421 | 576 | pr_info("Write protected kernel read-only data: %luk\n", |
| 422 | 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 | 49 | int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */ |
| 50 | 50 | int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */ |
| 51 | 51 | int tail_call_start; /* Tail call start offset */ |
| 52 | + int excnt; /* Number of exception table entries */ | |
| 52 | 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 | 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 | 683 | u32 *addrs = jit->addrs; |
| 605 | 684 | s32 imm = insn->imm; |
| 606 | 685 | s16 off = insn->off; |
| 686 | + int probe_prg = -1; | |
| 607 | 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 | 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 | 1205 | * BPF_LDX |
| 1120 | 1206 | */ |
| 1121 | 1207 | case BPF_LDX | BPF_MEM | BPF_B: /* dst = *(u8 *)(ul) (src + off) */ |
| 1208 | + case BPF_LDX | BPF_PROBE_MEM | BPF_B: | |
| 1122 | 1209 | /* llgc %dst,0(off,%src) */ |
| 1123 | 1210 | EMIT6_DISP_LH(0xe3000000, 0x0090, dst_reg, src_reg, REG_0, off); |
| 1124 | 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 | 1213 | insn_count = 2; |
| 1127 | 1214 | break; |
| 1128 | 1215 | case BPF_LDX | BPF_MEM | BPF_H: /* dst = *(u16 *)(ul) (src + off) */ |
| 1216 | + case BPF_LDX | BPF_PROBE_MEM | BPF_H: | |
| 1129 | 1217 | /* llgh %dst,0(off,%src) */ |
| 1130 | 1218 | EMIT6_DISP_LH(0xe3000000, 0x0091, dst_reg, src_reg, REG_0, off); |
| 1131 | 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 | 1221 | insn_count = 2; |
| 1134 | 1222 | break; |
| 1135 | 1223 | case BPF_LDX | BPF_MEM | BPF_W: /* dst = *(u32 *)(ul) (src + off) */ |
| 1224 | + case BPF_LDX | BPF_PROBE_MEM | BPF_W: | |
| 1136 | 1225 | /* llgf %dst,off(%src) */ |
| 1137 | 1226 | jit->seen |= SEEN_MEM; |
| 1138 | 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 | 1229 | insn_count = 2; |
| 1141 | 1230 | break; |
| 1142 | 1231 | case BPF_LDX | BPF_MEM | BPF_DW: /* dst = *(u64 *)(ul) (src + off) */ |
| 1232 | + case BPF_LDX | BPF_PROBE_MEM | BPF_DW: | |
| 1143 | 1233 | /* lg %dst,0(off,%src) */ |
| 1144 | 1234 | jit->seen |= SEEN_MEM; |
| 1145 | 1235 | EMIT6_DISP_LH(0xe3000000, 0x0004, dst_reg, src_reg, REG_0, off); |
| @@ -1485,6 +1575,23 @@ branch_oc: · 339 unmodified lines | ||
| 1485 | 1575 | pr_err("Unknown opcode %02x\n", insn->code); |
| 1486 | 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 | 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 | 1634 | jit->lit32 = jit->lit32_start; |
| 1528 | 1635 | jit->lit64 = jit->lit64_start; |
| 1529 | 1636 | jit->prg = 0; |
| 1637 | + jit->excnt = 0; | |
| 1530 | 1638 | |
| 1531 | 1639 | bpf_jit_prologue(jit, stack_depth); |
| 1532 | 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 | 1659 | jit->lit64_start = ALIGN(jit->lit64_start, 8); |
| 1552 | 1660 | jit->size = jit->lit64_start + lit64_size; |
| 1553 | 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 | 1668 | return 0; |
| 1555 | 1669 | } |
| 1556 | 1670 | |
| @@ -1565,6 +1679,29 @@ struct s390_jit_data { · 8 unmodified lines | ||
| 1565 | 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 | 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 | 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 | 1772 | if (!header) { |
| 1636 | 1773 | fp = orig_fp; |
| 1637 | 1774 | goto free_addrs; |
| @@ -155,10 +155,12 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, · 154 unmodified lines | ||
| 155 | 155 | return -EINVAL; |
| 156 | 156 | |
| 157 | 157 | /* |
| 158 | − * Only support read access to MIO capable devices on a MIO enabled | |
| 159 | − * system. Otherwise we would have to check for every address if it is | |
| 160 | − * a special ZPCI_ADDR and we would have to do a get_pfn() which we | |
| 161 | − * don't need for MIO capable devices. | |
| 158 | + * We only support write access to MIO capable devices if we are on | |
| 159 | + * a MIO enabled system. Otherwise we would have to check for every | |
| 160 | + * address if it is a special ZPCI_ADDR and would have to do | |
| 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 | 165 | if (static_branch_likely(&have_mio)) { |
| 164 | 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 | 284 | return -EINVAL; |
| 283 | 285 | |
| 284 | 286 | /* |
| 285 | − * Only support write access to MIO capable devices on a MIO enabled | |
| 286 | − * system. Otherwise we would have to check for every address if it is | |
| 287 | − * a special ZPCI_ADDR and we would have to do a get_pfn() which we | |
| 288 | − * don't need for MIO capable devices. | |
| 287 | + * We only support read access to MIO capable devices if we are on | |
| 288 | + * a MIO enabled system. Otherwise we would have to check for every | |
| 289 | + * address if it is a special ZPCI_ADDR and would have to do | |
| 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 | 294 | if (static_branch_likely(&have_mio)) { |
| 291 | 295 | ret = __memcpy_fromio_inuser( |
| @@ -556,8 +556,9 @@ tty3270_scroll_backward(struct kbd_data *kbd) · 555 unmodified lines | ||
| 556 | 556 | * Pass input line to tty. |
| 557 | 557 | */ |
| 558 | 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 | 562 | static char kreset_data = TW_KR; |
| 562 | 563 | struct tty3270 *tp = container_of(rrq->view, struct tty3270, view); |
| 563 | 564 | char *input; |
| @@ -652,8 +653,9 @@ tty3270_issue_read(struct tty3270 *tp, int lock) · 88 unmodified lines | ||
| 652 | 653 | * Hang up the tty |
| 653 | 654 | */ |
| 654 | 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 | 659 | tty_port_tty_hangup(&tp->port, true); |
| 658 | 660 | raw3270_put_view(&tp->view); |
| 659 | 661 | } |
| @@ -752,11 +754,9 @@ tty3270_alloc_view(void) · 92 unmodified lines | ||
| 752 | 754 | |
| 753 | 755 | tty_port_init(&tp->port); |
| 754 | 756 | timer_setup(&tp->timer, tty3270_update, 0); |
| 755 | − tasklet_init(&tp->readlet, | |
| 756 | − (void (*)(unsigned long)) tty3270_read_tasklet, | |
| 757 | + tasklet_init(&tp->readlet, tty3270_read_tasklet, | |
| 757 | 758 | (unsigned long) tp->read); |
| 758 | − tasklet_init(&tp->hanglet, | |
| 759 | − (void (*)(unsigned long)) tty3270_hangup_tasklet, | |
| 759 | + tasklet_init(&tp->hanglet, tty3270_hangup_tasklet, | |
| 760 | 760 | (unsigned long) tp); |
| 761 | 761 | INIT_WORK(&tp->resize_work, tty3270_resize_work); |
| 762 | 762 | |
| @@ -1,8 +1,7 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-1.0+ |
| 2 | 2 | /* |
| 3 | 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 | |
| 5 | − * dump format as s390 standalone dumps. | |
| 4 | + * dumps on SCSI disks (zfcpdump). | |
| 6 | 5 | * |
| 7 | 6 | * For more information please refer to Documentation/s390/zfcpdump.rst |
| 8 | 7 | * |
| @@ -16,7 +15,6 @@ · 7 unmodified lines | ||
| 16 | 15 | #include <linux/init.h> |
| 17 | 16 | #include <linux/slab.h> |
| 18 | 17 | #include <linux/debugfs.h> |
| 19 | −#include <linux/memblock.h> | |
| 20 | 18 | |
| 21 | 19 | #include <asm/asm-offsets.h> |
| 22 | 20 | #include <asm/ipl.h> |
| @@ -33,8 +31,6 @@ · 10 unmodified lines | ||
| 33 | 31 | |
| 34 | 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 | 34 | enum arch_id { |
| 39 | 35 | ARCH_S390 = 0, |
| 40 | 36 | ARCH_S390X = 1, |
| @@ -48,7 +44,6 @@ struct ipib_info { · 7 unmodified lines | ||
| 48 | 44 | static struct debug_info *zcore_dbf; |
| 49 | 45 | static int hsa_available; |
| 50 | 46 | static struct dentry *zcore_dir; |
| 51 | −static struct dentry *zcore_memmap_file; | |
| 52 | 47 | static struct dentry *zcore_reipl_file; |
| 53 | 48 | static struct dentry *zcore_hsa_file; |
| 54 | 49 | static struct ipl_parameter_block *zcore_ipl_block; |
| @@ -139,46 +134,6 @@ static void release_hsa(void) · 84 unmodified lines | ||
| 139 | 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 | 137 | static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, |
| 183 | 138 | size_t count, loff_t *ppos) |
| 184 | 139 | { |
| @@ -335,17 +290,11 @@ static int __init zcore_init(void) · 150 unmodified lines | ||
| 335 | 290 | rc = -ENOMEM; |
| 336 | 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 | 293 | zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, |
| 345 | 294 | NULL, &zcore_reipl_fops); |
| 346 | 295 | if (!zcore_reipl_file) { |
| 347 | 296 | rc = -ENOMEM; |
| 348 | − goto fail_memmap_file; | |
| 297 | + goto fail_dir; | |
| 349 | 298 | } |
| 350 | 299 | zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir, |
| 351 | 300 | NULL, &zcore_hsa_fops); |
| @@ -357,8 +306,6 @@ static int __init zcore_init(void) · 5 unmodified lines | ||
| 357 | 306 | |
| 358 | 307 | fail_reipl_file: |
| 359 | 308 | debugfs_remove(zcore_reipl_file); |
| 360 | −fail_memmap_file: | |
| 361 | − debugfs_remove(zcore_memmap_file); | |
| 362 | 309 | fail_dir: |
| 363 | 310 | debugfs_remove(zcore_dir); |
| 364 | 311 | fail: |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
| 16 | 16 | #define QDIO_BUSY_BIT_RETRY_DELAY 10 /* 10 milliseconds */ |
| 17 | 17 | #define QDIO_BUSY_BIT_RETRIES 1000 /* = 10s retry time */ |
| 18 | −#define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ | |
| 19 | 18 | |
| 20 | 19 | enum qdio_irq_states { |
| 21 | 20 | QDIO_IRQ_STATE_INACTIVE, |
| @@ -166,11 +165,7 @@ struct qdio_dev_perf_stat { · 144 unmodified lines | ||
| 166 | 165 | } ____cacheline_aligned; |
| 167 | 166 | |
| 168 | 167 | struct qdio_queue_perf_stat { |
| 169 | − /* | |
| 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 | − */ | |
| 168 | + /* Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128. */ | |
| 174 | 169 | unsigned int nr_sbals[8]; |
| 175 | 170 | unsigned int nr_sbal_error; |
| 176 | 171 | unsigned int nr_sbal_nop; |
| @@ -185,8 +180,6 @@ struct qdio_input_q { · 8 unmodified lines | ||
| 185 | 180 | /* Batch of SBALs that we processed while polling the queue: */ |
| 186 | 181 | unsigned int batch_start; |
| 187 | 182 | unsigned int batch_count; |
| 188 | − /* last time of noticing incoming data */ | |
| 189 | − u64 timestamp; | |
| 190 | 183 | }; |
| 191 | 184 | |
| 192 | 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 | 167 | seq_printf(m, "\n1 2.. 4.. 8.. " |
| 168 | − "16.. 32.. 64.. 127\n"); | |
| 168 | + "16.. 32.. 64.. 128\n"); | |
| 169 | 169 | for (i = 0; i < ARRAY_SIZE(q->q_stats.nr_sbals); i++) |
| 170 | 170 | seq_printf(m, "%-10u ", q->q_stats.nr_sbals[i]); |
| 171 | 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 | 414 | static inline void account_sbals(struct qdio_q *q, unsigned int count) |
| 415 | 415 | { |
| 416 | − int pos; | |
| 417 | − | |
| 418 | 416 | q->q_stats.nr_sbal_total += count; |
| 419 | − if (count == QDIO_MAX_BUFFERS_MASK) { | |
| 420 | − q->q_stats.nr_sbals[7]++; | |
| 421 | − return; | |
| 422 | − } | |
| 423 | − pos = ilog2(count); | |
| 424 | − q->q_stats.nr_sbals[pos]++; | |
| 417 | + q->q_stats.nr_sbals[ilog2(count)]++; | |
| 425 | 418 | } |
| 426 | 419 | |
| 427 | 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 | 458 | q->timestamp = get_tod_clock_fast(); |
| 466 | 459 | |
| 467 | − /* | |
| 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); | |
| 460 | + count = atomic_read(&q->nr_buf_used); | |
| 472 | 461 | if (!count) |
| 473 | 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 | 511 | static int qdio_inbound_q_moved(struct qdio_q *q, unsigned int start) |
| 523 | 512 | { |
| 524 | − int count; | |
| 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; | |
| 513 | + return get_inbound_buffer_frontier(q, start); | |
| 532 | 514 | } |
| 533 | 515 | |
| 534 | 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 | 528 | /* more work coming */ |
| 547 | 529 | return 0; |
| 548 | 530 | |
| 549 | − if (is_thinint_irq(q->irq_ptr)) | |
| 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; | |
| 531 | + return 1; | |
| 565 | 532 | } |
| 566 | 533 | |
| 567 | 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 | 73 | DEFINE_MUTEX(ap_perms_mutex); |
| 74 | 74 | EXPORT_SYMBOL(ap_perms_mutex); |
| 75 | 75 | |
| 76 | −static struct ap_config_info *ap_configuration; | |
| 77 | −static bool initialised; | |
| 76 | +static struct ap_config_info *ap_qci_info; | |
| 78 | 77 | |
| 79 | 78 | /* |
| 80 | 79 | * AP bus related debug feature things. |
| @@ -105,8 +104,10 @@ static struct hrtimer ap_poll_timer; · 24 unmodified lines | ||
| 105 | 104 | */ |
| 106 | 105 | static unsigned long long poll_timeout = 250000; |
| 107 | 106 | |
| 108 | −/* Maximum domain id */ | |
| 109 | −static int ap_max_domain_id; | |
| 107 | +/* Maximum domain id, if not given via qci */ | |
| 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 | 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 | − * information is available. | |
| 158 | + * ap_qci_available(): Test if AP configuration | |
| 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 | 165 | return test_facility(12); |
| 165 | 166 | } |
| @@ -182,22 +183,22 @@ static int ap_apft_available(void) · 16 unmodified lines | ||
| 182 | 183 | */ |
| 183 | 184 | static inline int ap_qact_available(void) |
| 184 | 185 | { |
| 185 | − if (ap_configuration) | |
| 186 | − return ap_configuration->qact; | |
| 186 | + if (ap_qci_info) | |
| 187 | + return ap_qci_info->qact; | |
| 187 | 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 | 194 | * Returns the ap configuration info fetched via PQAP(QCI). |
| 194 | 195 | * On success 0 is returned, on failure a negative errno |
| 195 | 196 | * is returned, e.g. if the PQAP(QCI) instruction is not |
| 196 | 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 | 202 | return -EOPNOTSUPP; |
| 202 | 203 | if (!info) |
| 203 | 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 | 218 | return; |
| 219 | + } | |
| 214 | 220 | |
| 215 | − ap_configuration = kzalloc(sizeof(*ap_configuration), GFP_KERNEL); | |
| 216 | − if (!ap_configuration) | |
| 221 | + ap_qci_info = kzalloc(sizeof(*ap_qci_info), GFP_KERNEL); | |
| 222 | + if (!ap_qci_info) | |
| 217 | 223 | return; |
| 218 | − if (ap_query_configuration(ap_configuration) != 0) { | |
| 219 | − kfree(ap_configuration); | |
| 220 | − ap_configuration = NULL; | |
| 224 | + if (ap_fetch_qci_info(ap_qci_info) != 0) { | |
| 225 | + kfree(ap_qci_info); | |
| 226 | + ap_qci_info = NULL; | |
| 221 | 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 | 255 | * ap_test_config_card_id(): Test, whether an AP card ID is configured. |
| 236 | − * @id AP card ID | |
| 237 | 256 | * |
| 238 | 257 | * Returns 0 if the card is not configured |
| 239 | 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 | 261 | static inline int ap_test_config_card_id(unsigned int id) |
| 243 | 262 | { |
| 244 | − if (!ap_configuration) /* QCI not supported */ | |
| 245 | − /* only ids 0...3F may be probed */ | |
| 246 | − return id < 0x40 ? 1 : 0; | |
| 247 | − return ap_test_config(ap_configuration->apm, id); | |
| 263 | + if (id > ap_max_adapter_id) | |
| 264 | + return 0; | |
| 265 | + if (ap_qci_info) | |
| 266 | + return ap_test_config(ap_qci_info->apm, id); | |
| 267 | + return 1; | |
| 248 | 268 | } |
| 249 | 269 | |
| 250 | 270 | /* |
| 251 | 271 | * ap_test_config_usage_domain(): Test, whether an AP usage domain |
| 252 | 272 | * is configured. |
| 253 | − * @domain AP usage domain ID | |
| 254 | 273 | * |
| 255 | 274 | * Returns 0 if the usage domain is not configured |
| 256 | 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 | 278 | int ap_test_config_usage_domain(unsigned int domain) |
| 260 | 279 | { |
| 261 | − if (!ap_configuration) /* QCI not supported */ | |
| 262 | − return domain < 16; | |
| 263 | − return ap_test_config(ap_configuration->aqm, domain); | |
| 280 | + if (domain > ap_max_domain_id) | |
| 281 | + return 0; | |
| 282 | + if (ap_qci_info) | |
| 283 | + return ap_test_config(ap_qci_info->aqm, domain); | |
| 284 | + return 1; | |
| 264 | 285 | } |
| 265 | 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 | 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 | 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 | 302 | EXPORT_SYMBOL(ap_test_config_ctrl_domain); |
| 282 | 303 | |
| 283 | −/** | |
| 284 | − * ap_query_queue(): Check if an AP queue is available. | |
| 285 | − * @qid: The AP queue number | |
| 286 | − * @queue_depth: Pointer to queue depth value | |
| 287 | − * @device_type: Pointer to device type value | |
| 288 | − * @facilities: Pointer to facility indicator | |
| 304 | +/* | |
| 305 | + * ap_queue_info(): Check and get AP queue info. | |
| 306 | + * Returns true if TAPQ succeeded and the info is filled or | |
| 307 | + * false otherwise. | |
| 289 | 308 | */ |
| 290 | −static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, | |
| 291 | − unsigned int *facilities) | |
| 309 | +static bool ap_queue_info(ap_qid_t qid, int *q_type, | |
| 310 | + unsigned int *q_fac, int *q_depth) | |
| 292 | 311 | { |
| 293 | 312 | struct ap_queue_status status; |
| 294 | − unsigned long info; | |
| 295 | − int nd; | |
| 313 | + unsigned long info = 0; | |
| 296 | 314 | |
| 297 | − if (!ap_test_config_card_id(AP_QID_CARD(qid))) | |
| 298 | − return -ENODEV; | |
| 315 | + /* make sure we don't run into a specifiation exception */ | |
| 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 | 321 | status = ap_test_queue(qid, ap_apft_available(), &info); |
| 301 | 322 | switch (status.response_code) { |
| 302 | 323 | case AP_RESPONSE_NORMAL: |
| 303 | − *queue_depth = (int)(info & 0xff); | |
| 304 | − *device_type = (int)((info >> 24) & 0xff); | |
| 305 | − *facilities = (unsigned int)(info >> 32); | |
| 306 | − /* Update maximum domain id */ | |
| 307 | − nd = (info >> 16) & 0xff; | |
| 308 | − /* if N bit is available, z13 and newer */ | |
| 309 | − if ((info & (1UL << 57)) && nd > 0) | |
| 310 | − ap_max_domain_id = nd; | |
| 311 | − else /* older machine types */ | |
| 312 | − ap_max_domain_id = 15; | |
| 313 | − switch (*device_type) { | |
| 324 | + case AP_RESPONSE_RESET_IN_PROGRESS: | |
| 325 | + /* | |
| 326 | + * According to the architecture in all these cases the | |
| 327 | + * info should be filled. All bits 0 is not possible as | |
| 328 | + * there is at least one of the mode bits set. | |
| 329 | + */ | |
| 330 | + if (WARN_ON_ONCE(!info)) | |
| 331 | + return false; | |
| 332 | + *q_type = (int)((info >> 24) & 0xff); | |
| 333 | + *q_fac = (unsigned int)(info >> 32); | |
| 334 | + *q_depth = (int)(info & 0xff); | |
| 335 | + switch (*q_type) { | |
| 314 | 336 | /* For CEX2 and CEX3 the available functions |
| 315 | 337 | * are not reflected by the facilities bits. |
| 316 | 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 | 341 | case AP_DEVICE_TYPE_CEX2A: |
| 320 | 342 | case AP_DEVICE_TYPE_CEX3A: |
| 321 | − *facilities |= 0x08000000; | |
| 343 | + *q_fac |= 0x08000000; | |
| 322 | 344 | break; |
| 323 | 345 | case AP_DEVICE_TYPE_CEX2C: |
| 324 | 346 | case AP_DEVICE_TYPE_CEX3C: |
| 325 | − *facilities |= 0x10000000; | |
| 347 | + *q_fac |= 0x10000000; | |
| 326 | 348 | break; |
| 327 | 349 | default: |
| 328 | 350 | break; |
| 329 | 351 | } |
| 330 | − return 0; | |
| 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; | |
| 352 | + return true; | |
| 340 | 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 | 363 | ktime_t hr_time; |
| 348 | 364 | |
| 349 | 365 | switch (wait) { |
| 350 | − case AP_WAIT_AGAIN: | |
| 351 | − case AP_WAIT_INTERRUPT: | |
| 366 | + case AP_SM_WAIT_AGAIN: | |
| 367 | + case AP_SM_WAIT_INTERRUPT: | |
| 352 | 368 | if (ap_using_interrupts()) |
| 353 | 369 | break; |
| 354 | 370 | if (ap_poll_kthread) { |
| @@ -356,7 +372,7 @@ void ap_wait(enum ap_wait wait) · 1 unmodified line | ||
| 356 | 372 | break; |
| 357 | 373 | } |
| 358 | 374 | fallthrough; |
| 359 | − case AP_WAIT_TIMEOUT: | |
| 375 | + case AP_SM_WAIT_TIMEOUT: | |
| 360 | 376 | spin_lock_bh(&ap_poll_timer_lock); |
| 361 | 377 | if (!hrtimer_is_queued(&ap_poll_timer)) { |
| 362 | 378 | hr_time = poll_timeout; |
| @@ -365,7 +381,7 @@ void ap_wait(enum ap_wait wait) · 2 unmodified lines | ||
| 365 | 381 | } |
| 366 | 382 | spin_unlock_bh(&ap_poll_timer_lock); |
| 367 | 383 | break; |
| 368 | − case AP_WAIT_NONE: | |
| 384 | + case AP_SM_WAIT_NONE: | |
| 369 | 385 | default: |
| 370 | 386 | break; |
| 371 | 387 | } |
| @@ -382,7 +398,7 @@ void ap_request_timeout(struct timer_list *t) · 10 unmodified lines | ||
| 382 | 398 | struct ap_queue *aq = from_timer(aq, t, timeout); |
| 383 | 399 | |
| 384 | 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 | 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 | 435 | int bkt; |
| 420 | 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 | 439 | /* Reset the indicator if interrupts are used. Thus new interrupts can |
| 424 | 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 | 446 | spin_lock_bh(&ap_queues_lock); |
| 431 | 447 | hash_for_each(ap_queues, bkt, aq, hnode) { |
| 432 | 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 | 450 | spin_unlock_bh(&aq->lock); |
| 435 | 451 | } |
| 436 | 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 | 768 | struct device_driver *drv = &ap_drv->driver; |
| 753 | 769 | |
| 754 | − if (!initialised) | |
| 755 | − return -ENODEV; | |
| 756 | − | |
| 757 | 770 | drv->bus = &ap_bus_type; |
| 758 | 771 | drv->probe = ap_device_probe; |
| 759 | 772 | drv->remove = ap_device_remove; |
| @@ -929,11 +942,12 @@ static ssize_t ap_domain_store(struct bus_type *bus, · 169 unmodified lines | ||
| 929 | 942 | domain < 0 || domain > ap_max_domain_id || |
| 930 | 943 | !test_bit_inv(domain, ap_perms.aqm)) |
| 931 | 944 | return -EINVAL; |
| 945 | + | |
| 932 | 946 | spin_lock_bh(&ap_domain_lock); |
| 933 | 947 | ap_domain_index = domain; |
| 934 | 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 | 952 | return count; |
| 939 | 953 | } |
| @@ -942,45 +956,45 @@ static BUS_ATTR_RW(ap_domain); · 2 unmodified lines | ||
| 942 | 956 | |
| 943 | 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 | 960 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
| 947 | 961 | |
| 948 | 962 | return scnprintf(buf, PAGE_SIZE, |
| 949 | 963 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
| 950 | − ap_configuration->adm[0], ap_configuration->adm[1], | |
| 951 | − ap_configuration->adm[2], ap_configuration->adm[3], | |
| 952 | − ap_configuration->adm[4], ap_configuration->adm[5], | |
| 953 | − ap_configuration->adm[6], ap_configuration->adm[7]); | |
| 964 | + ap_qci_info->adm[0], ap_qci_info->adm[1], | |
| 965 | + ap_qci_info->adm[2], ap_qci_info->adm[3], | |
| 966 | + ap_qci_info->adm[4], ap_qci_info->adm[5], | |
| 967 | + ap_qci_info->adm[6], ap_qci_info->adm[7]); | |
| 954 | 968 | } |
| 955 | 969 | |
| 956 | 970 | static BUS_ATTR_RO(ap_control_domain_mask); |
| 957 | 971 | |
| 958 | 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 | 975 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
| 962 | 976 | |
| 963 | 977 | return scnprintf(buf, PAGE_SIZE, |
| 964 | 978 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
| 965 | − ap_configuration->aqm[0], ap_configuration->aqm[1], | |
| 966 | − ap_configuration->aqm[2], ap_configuration->aqm[3], | |
| 967 | − ap_configuration->aqm[4], ap_configuration->aqm[5], | |
| 968 | − ap_configuration->aqm[6], ap_configuration->aqm[7]); | |
| 979 | + ap_qci_info->aqm[0], ap_qci_info->aqm[1], | |
| 980 | + ap_qci_info->aqm[2], ap_qci_info->aqm[3], | |
| 981 | + ap_qci_info->aqm[4], ap_qci_info->aqm[5], | |
| 982 | + ap_qci_info->aqm[6], ap_qci_info->aqm[7]); | |
| 969 | 983 | } |
| 970 | 984 | |
| 971 | 985 | static BUS_ATTR_RO(ap_usage_domain_mask); |
| 972 | 986 | |
| 973 | 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 | 990 | return scnprintf(buf, PAGE_SIZE, "not supported\n"); |
| 977 | 991 | |
| 978 | 992 | return scnprintf(buf, PAGE_SIZE, |
| 979 | 993 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", |
| 980 | − ap_configuration->apm[0], ap_configuration->apm[1], | |
| 981 | − ap_configuration->apm[2], ap_configuration->apm[3], | |
| 982 | − ap_configuration->apm[4], ap_configuration->apm[5], | |
| 983 | − ap_configuration->apm[6], ap_configuration->apm[7]); | |
| 994 | + ap_qci_info->apm[0], ap_qci_info->apm[1], | |
| 995 | + ap_qci_info->apm[2], ap_qci_info->apm[3], | |
| 996 | + ap_qci_info->apm[4], ap_qci_info->apm[5], | |
| 997 | + ap_qci_info->apm[6], ap_qci_info->apm[7]); | |
| 984 | 998 | } |
| 985 | 999 | |
| 986 | 1000 | static BUS_ATTR_RO(ap_adapter_mask); |
| @@ -1066,17 +1080,18 @@ static BUS_ATTR_RW(poll_timeout); · 79 unmodified lines | ||
| 1066 | 1080 | |
| 1067 | 1081 | static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf) |
| 1068 | 1082 | { |
| 1069 | − int 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); | |
| 1083 | + return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_domain_id); | |
| 1076 | 1084 | } |
| 1077 | 1085 | |
| 1078 | 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 | 1095 | static ssize_t apmask_show(struct bus_type *bus, char *buf) |
| 1081 | 1096 | { |
| 1082 | 1097 | int rc; |
| @@ -1149,6 +1164,7 @@ static struct bus_attribute *const ap_bus_attrs[] = { · 66 unmodified lines | ||
| 1149 | 1164 | &bus_attr_ap_interrupts, |
| 1150 | 1165 | &bus_attr_poll_timeout, |
| 1151 | 1166 | &bus_attr_ap_max_domain_id, |
| 1167 | + &bus_attr_ap_max_adapter_id, | |
| 1152 | 1168 | &bus_attr_apmask, |
| 1153 | 1169 | &bus_attr_aqmask, |
| 1154 | 1170 | NULL, |
| @@ -1160,47 +1176,42 @@ static struct bus_attribute *const ap_bus_attrs[] = { · 5 unmodified lines | ||
| 1160 | 1176 | */ |
| 1161 | 1177 | static void ap_select_domain(void) |
| 1162 | 1178 | { |
| 1163 | − int count, max_count, best_domain; | |
| 1164 | 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 | |
| 1169 | − * the "domain=" parameter or the domain with the maximum number | |
| 1170 | − * of devices. | |
| 1183 | + * Choose the default domain. Either the one specified with | |
| 1184 | + * the "domain=" parameter or the first domain with at least | |
| 1185 | + * one valid APQN. | |
| 1171 | 1186 | */ |
| 1172 | 1187 | spin_lock_bh(&ap_domain_lock); |
| 1173 | 1188 | if (ap_domain_index >= 0) { |
| 1174 | 1189 | /* Domain has already been selected. */ |
| 1175 | − spin_unlock_bh(&ap_domain_lock); | |
| 1176 | − return; | |
| 1190 | + goto out; | |
| 1177 | 1191 | } |
| 1178 | − best_domain = -1; | |
| 1179 | − max_count = 0; | |
| 1180 | − for (i = 0; i < AP_DOMAINS; i++) { | |
| 1181 | − if (!ap_test_config_usage_domain(i) || | |
| 1182 | − !test_bit_inv(i, ap_perms.aqm)) | |
| 1192 | + for (dom = 0; dom <= ap_max_domain_id; dom++) { | |
| 1193 | + if (!ap_test_config_usage_domain(dom) || | |
| 1194 | + !test_bit_inv(dom, ap_perms.aqm)) | |
| 1183 | 1195 | continue; |
| 1184 | − count = 0; | |
| 1185 | − for (j = 0; j < AP_DEVICES; j++) { | |
| 1186 | − if (!ap_test_config_card_id(j)) | |
| 1196 | + for (card = 0; card <= ap_max_adapter_id; card++) { | |
| 1197 | + if (!ap_test_config_card_id(card) || | |
| 1198 | + !test_bit_inv(card, ap_perms.apm)) | |
| 1187 | 1199 | continue; |
| 1188 | − status = ap_test_queue(AP_MKQID(j, i), | |
| 1200 | + status = ap_test_queue(AP_MKQID(card, dom), | |
| 1189 | 1201 | ap_apft_available(), |
| 1190 | 1202 | NULL); |
| 1191 | − if (status.response_code != AP_RESPONSE_NORMAL) | |
| 1192 | − continue; | |
| 1193 | − count++; | |
| 1194 | − } | |
| 1195 | − if (count > max_count) { | |
| 1196 | − max_count = count; | |
| 1197 | − best_domain = i; | |
| 1203 | + if (status.response_code == AP_RESPONSE_NORMAL) | |
| 1204 | + break; | |
| 1198 | 1205 | } |
| 1206 | + if (card <= ap_max_adapter_id) | |
| 1207 | + break; | |
| 1199 | 1208 | } |
| 1200 | − if (best_domain >= 0) { | |
| 1201 | − ap_domain_index = best_domain; | |
| 1202 | − AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index); | |
| 1209 | + if (dom <= ap_max_domain_id) { | |
| 1210 | + ap_domain_index = dom; | |
| 1211 | + AP_DBF(DBF_DEBUG, "%s new default domain is %d\n", | |
| 1212 | + __func__, ap_domain_index); | |
| 1203 | 1213 | } |
| 1214 | +out: | |
| 1204 | 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 | 1291 | static void _ap_scan_bus_adapter(int id) |
| 1281 | 1292 | { |
| 1293 | + bool broken; | |
| 1282 | 1294 | ap_qid_t qid; |
| 1283 | 1295 | unsigned int func; |
| 1284 | 1296 | struct ap_card *ac; |
| 1285 | 1297 | struct device *dev; |
| 1286 | 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 | 1301 | /* check if there is a card device registered with this id */ |
| 1290 | 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 | 1324 | /* find the first valid queue */ |
| 1313 | 1325 | for (dom = 0; dom < AP_DOMAINS; dom++) { |
| 1314 | 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 | 1328 | break; |
| 1317 | 1329 | } |
| 1318 | − borked = 0; | |
| 1330 | + broken = false; | |
| 1319 | 1331 | if (dom >= AP_DOMAINS) { |
| 1320 | 1332 | /* no accessible queue on this card */ |
| 1321 | − borked = 1; | |
| 1333 | + broken = true; | |
| 1322 | 1334 | } else if (ac->raw_hwtype != type) { |
| 1323 | 1335 | /* card type has changed */ |
| 1324 | 1336 | AP_DBF(DBF_INFO, "card=%02x type changed.\n", id); |
| 1325 | − borked = 1; | |
| 1337 | + broken = true; | |
| 1326 | 1338 | } else if (ac->functions != func) { |
| 1327 | 1339 | /* card functions have changed */ |
| 1328 | 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 | 1344 | /* unregister card device and associated queues */ |
| 1333 | 1345 | bus_for_each_dev(&ap_bus_type, NULL, |
| 1334 | 1346 | (void *)(long) id, |
| @@ -1364,16 +1376,14 @@ static void _ap_scan_bus_adapter(int id) · 29 unmodified lines | ||
| 1364 | 1376 | continue; |
| 1365 | 1377 | } |
| 1366 | 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 | 1380 | if (dev) { |
| 1369 | − if (rc == -ENODEV) | |
| 1370 | − borked = 1; | |
| 1371 | − else { | |
| 1381 | + if (!broken) { | |
| 1372 | 1382 | spin_lock_bh(&aq->lock); |
| 1373 | − borked = aq->state == AP_STATE_BORKED; | |
| 1383 | + broken = aq->sm_state == AP_SM_STATE_BORKED; | |
| 1374 | 1384 | spin_unlock_bh(&aq->lock); |
| 1375 | 1385 | } |
| 1376 | − if (borked) { | |
| 1386 | + if (broken) { | |
| 1377 | 1387 | /* Remove broken device */ |
| 1378 | 1388 | AP_DBF(DBF_DEBUG, |
| 1379 | 1389 | "removing broken queue=%02x.%04x\n", |
| @@ -1383,7 +1393,7 @@ static void _ap_scan_bus_adapter(int id) · 3 unmodified lines | ||
| 1383 | 1393 | put_device(dev); |
| 1384 | 1394 | continue; |
| 1385 | 1395 | } |
| 1386 | − if (rc) | |
| 1396 | + if (broken) | |
| 1387 | 1397 | continue; |
| 1388 | 1398 | /* a new queue device is needed, check out comp type */ |
| 1389 | 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 | 1446 | int id; |
| 1437 | 1447 | |
| 1438 | − AP_DBF(DBF_DEBUG, "%s running\n", __func__); | |
| 1439 | − | |
| 1440 | − ap_query_configuration(ap_configuration); | |
| 1448 | + ap_fetch_qci_info(ap_qci_info); | |
| 1441 | 1449 | ap_select_domain(); |
| 1442 | 1450 | |
| 1451 | + AP_DBF(DBF_DEBUG, "%s running\n", __func__); | |
| 1452 | + | |
| 1443 | 1453 | /* loop over all possible adapters */ |
| 1444 | 1454 | for (id = 0; id < AP_DEVICES; id++) |
| 1445 | 1455 | _ap_scan_bus_adapter(id); |
| @@ -1505,7 +1515,6 @@ static void __init ap_perms_init(void) · 59 unmodified lines | ||
| 1505 | 1515 | */ |
| 1506 | 1516 | static int __init ap_module_init(void) |
| 1507 | 1517 | { |
| 1508 | − int max_domain_id; | |
| 1509 | 1518 | int rc, i; |
| 1510 | 1519 | |
| 1511 | 1520 | rc = ap_debug_init(); |
| @@ -1524,14 +1533,10 @@ static int __init ap_module_init(void) · 12 unmodified lines | ||
| 1524 | 1533 | ap_perms_init(); |
| 1525 | 1534 | |
| 1526 | 1535 | /* Get AP configuration data if available */ |
| 1527 | − ap_init_configuration(); | |
| 1528 | − | |
| 1529 | − if (ap_configuration) | |
| 1530 | − 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 || | |
| 1536 | + ap_init_qci_info(); | |
| 1537 | + | |
| 1538 | + /* check default domain setting */ | |
| 1539 | + if (ap_domain_index < -1 || ap_domain_index > ap_max_domain_id || | |
| 1535 | 1540 | (ap_domain_index >= 0 && |
| 1536 | 1541 | !test_bit_inv(ap_domain_index, ap_perms.aqm))) { |
| 1537 | 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 | 1544 | ap_domain_index = -1; |
| 1540 | 1545 | } |
| 1541 | 1546 | |
| 1547 | + /* enable interrupts if available */ | |
| 1542 | 1548 | if (ap_interrupts_available()) { |
| 1543 | 1549 | rc = register_adapter_interrupt(&ap_airq); |
| 1544 | 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 | 1589 | queue_work(system_long_wq, &ap_scan_work); |
| 1584 | − initialised = true; | |
| 1585 | 1590 | |
| 1586 | 1591 | return 0; |
| 1587 | 1592 | |
| @@ -1595,7 +1600,7 @@ out_bus: · 7 unmodified lines | ||
| 1595 | 1600 | out: |
| 1596 | 1601 | if (ap_using_interrupts()) |
| 1597 | 1602 | unregister_adapter_interrupt(&ap_airq); |
| 1598 | − kfree(ap_configuration); | |
| 1603 | + kfree(ap_qci_info); | |
| 1599 | 1604 | return rc; |
| 1600 | 1605 | } |
| 1601 | 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 | 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 { | |
| 89 | − AP_STATE_RESET_START, | |
| 90 | − AP_STATE_RESET_WAIT, | |
| 91 | − AP_STATE_SETIRQ_WAIT, | |
| 92 | − AP_STATE_IDLE, | |
| 93 | − AP_STATE_WORKING, | |
| 94 | − AP_STATE_QUEUE_FULL, | |
| 95 | − AP_STATE_REMOVE, /* about to be removed from driver */ | |
| 96 | − AP_STATE_UNBOUND, /* momentary not bound to a driver */ | |
| 97 | − AP_STATE_BORKED, /* broken */ | |
| 98 | − NR_AP_STATES | |
| 88 | +enum ap_sm_state { | |
| 89 | + AP_SM_STATE_RESET_START, | |
| 90 | + AP_SM_STATE_RESET_WAIT, | |
| 91 | + AP_SM_STATE_SETIRQ_WAIT, | |
| 92 | + AP_SM_STATE_IDLE, | |
| 93 | + AP_SM_STATE_WORKING, | |
| 94 | + AP_SM_STATE_QUEUE_FULL, | |
| 95 | + AP_SM_STATE_REMOVE, /* about to be removed from driver */ | |
| 96 | + AP_SM_STATE_UNBOUND, /* momentary not bound to a driver */ | |
| 97 | + AP_SM_STATE_BORKED, /* broken */ | |
| 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 { | |
| 105 | − AP_EVENT_POLL, | |
| 106 | − AP_EVENT_TIMEOUT, | |
| 107 | − NR_AP_EVENTS | |
| 104 | +enum ap_sm_event { | |
| 105 | + AP_SM_EVENT_POLL, | |
| 106 | + AP_SM_EVENT_TIMEOUT, | |
| 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 { | |
| 114 | − AP_WAIT_AGAIN, /* retry immediately */ | |
| 115 | − AP_WAIT_TIMEOUT, /* wait for timeout */ | |
| 116 | − AP_WAIT_INTERRUPT, /* wait for thin interrupt (if available) */ | |
| 117 | − AP_WAIT_NONE, /* no wait */ | |
| 118 | − NR_AP_WAIT | |
| 113 | +enum ap_sm_wait { | |
| 114 | + AP_SM_WAIT_AGAIN, /* retry immediately */ | |
| 115 | + AP_SM_WAIT_TIMEOUT, /* wait for timeout */ | |
| 116 | + AP_SM_WAIT_INTERRUPT, /* wait for thin interrupt (if available) */ | |
| 117 | + AP_SM_WAIT_NONE, /* no wait */ | |
| 118 | + NR_AP_SM_WAIT | |
| 119 | 119 | }; |
| 120 | 120 | |
| 121 | 121 | struct ap_device; |
| @@ -172,7 +172,7 @@ struct ap_queue { · 50 unmodified lines | ||
| 172 | 172 | ap_qid_t qid; /* AP queue id. */ |
| 173 | 173 | int interrupt; /* indicate if interrupts are enabled */ |
| 174 | 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 | 176 | int pendingq_count; /* # requests on pendingq list. */ |
| 177 | 177 | int requestq_count; /* # requests on requestq list. */ |
| 178 | 178 | u64 total_request_count; /* # requests ever for this AP device.*/ |
| @@ -185,22 +185,23 @@ struct ap_queue { · 6 unmodified lines | ||
| 185 | 185 | |
| 186 | 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 | 190 | struct ap_message { |
| 191 | 191 | struct list_head list; /* Request queueing. */ |
| 192 | 192 | unsigned long long psmid; /* Message id. */ |
| 193 | − void *message; /* Pointer to message buffer. */ | |
| 194 | − size_t length; /* Message length. */ | |
| 193 | + void *msg; /* Pointer to message buffer. */ | |
| 194 | + unsigned int len; /* Message length. */ | |
| 195 | + u32 flags; /* Flags, see AP_MSG_FLAG_xxx */ | |
| 195 | 196 | int rc; /* Return code for this message */ |
| 196 | − | |
| 197 | 197 | void *private; /* ap driver private pointer. */ |
| 198 | − unsigned int special:1; /* Used for special commands. */ | |
| 199 | 198 | /* receive is called from tasklet context */ |
| 200 | 199 | void (*receive)(struct ap_queue *, struct ap_message *, |
| 201 | 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 | 206 | * ap_init_message() - Initialize ap_message. |
| 206 | 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 | 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 | 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 | 231 | int ap_send(ap_qid_t, unsigned long long, void *, size_t); |
| 231 | 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_wait ap_sm_event_loop(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); | |
| 235 | +enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event); | |
| 235 | 236 | |
| 236 | 237 | void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg); |
| 237 | 238 | void ap_cancel_message(struct ap_queue *aq, struct ap_message *ap_msg); |
| 238 | 239 | void ap_flush_queue(struct ap_queue *aq); |
| 239 | 240 | |
| 240 | 241 | void *ap_airq_ptr(void); |
| 241 | −void ap_wait(enum ap_wait wait); | |
| 242 | +void ap_wait(enum ap_sm_wait wait); | |
| 242 | 243 | void ap_request_timeout(struct timer_list *t); |
| 243 | 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 | 70 | static inline struct ap_queue_status |
| 71 | 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 | 75 | qid |= 0x400000UL; |
| 76 | 76 | return ap_nqap(qid, psmid, msg, length); |
| 77 | 77 | } |
| @@ -119,9 +119,9 @@ EXPORT_SYMBOL(ap_recv); · 41 unmodified lines | ||
| 119 | 119 | |
| 120 | 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 | 129 | * not change the state of the device. |
| 130 | 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 | 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 | 137 | struct ap_message *ap_msg; |
| 138 | 138 | |
| 139 | 139 | status = ap_dqap(aq->qid, &aq->reply->psmid, |
| 140 | − aq->reply->message, aq->reply->length); | |
| 140 | + aq->reply->msg, aq->reply->len); | |
| 141 | 141 | switch (status.response_code) { |
| 142 | 142 | case AP_RESPONSE_NORMAL: |
| 143 | 143 | aq->queue_count--; |
| @@ -172,31 +172,31 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) · 28 unmodified lines | ||
| 172 | 172 | * ap_sm_read(): Receive pending reply messages from an AP queue. |
| 173 | 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 | 179 | struct ap_queue_status status; |
| 180 | 180 | |
| 181 | 181 | if (!aq->reply) |
| 182 | − return AP_WAIT_NONE; | |
| 182 | + return AP_SM_WAIT_NONE; | |
| 183 | 183 | status = ap_sm_recv(aq); |
| 184 | 184 | switch (status.response_code) { |
| 185 | 185 | case AP_RESPONSE_NORMAL: |
| 186 | 186 | if (aq->queue_count > 0) { |
| 187 | − aq->state = AP_STATE_WORKING; | |
| 188 | − return AP_WAIT_AGAIN; | |
| 187 | + aq->sm_state = AP_SM_STATE_WORKING; | |
| 188 | + return AP_SM_WAIT_AGAIN; | |
| 189 | 189 | } |
| 190 | − aq->state = AP_STATE_IDLE; | |
| 191 | − return AP_WAIT_NONE; | |
| 190 | + aq->sm_state = AP_SM_STATE_IDLE; | |
| 191 | + return AP_SM_WAIT_NONE; | |
| 192 | 192 | case AP_RESPONSE_NO_PENDING_REPLY: |
| 193 | 193 | if (aq->queue_count > 0) |
| 194 | − return AP_WAIT_INTERRUPT; | |
| 195 | − aq->state = AP_STATE_IDLE; | |
| 196 | − return AP_WAIT_NONE; | |
| 194 | + return AP_SM_WAIT_INTERRUPT; | |
| 195 | + aq->sm_state = AP_SM_STATE_IDLE; | |
| 196 | + return AP_SM_WAIT_NONE; | |
| 197 | 197 | default: |
| 198 | − aq->state = AP_STATE_BORKED; | |
| 199 | − return AP_WAIT_NONE; | |
| 198 | + aq->sm_state = AP_SM_STATE_BORKED; | |
| 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 | 204 | * ap_sm_write(): Send messages from the request queue to an AP queue. |
| 205 | 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 | 211 | struct ap_queue_status status; |
| 212 | 212 | struct ap_message *ap_msg; |
| 213 | 213 | |
| 214 | 214 | if (aq->requestq_count <= 0) |
| 215 | − return AP_WAIT_NONE; | |
| 215 | + return AP_SM_WAIT_NONE; | |
| 216 | 216 | /* Start the next request on the queue. */ |
| 217 | 217 | ap_msg = list_entry(aq->requestq.next, struct ap_message, list); |
| 218 | 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 | 221 | switch (status.response_code) { |
| 221 | 222 | case AP_RESPONSE_NORMAL: |
| 222 | 223 | aq->queue_count++; |
| @@ -226,26 +227,26 @@ static enum ap_wait ap_sm_write(struct ap_queue *aq) · 3 unmodified lines | ||
| 226 | 227 | aq->requestq_count--; |
| 227 | 228 | aq->pendingq_count++; |
| 228 | 229 | if (aq->queue_count < aq->card->queue_depth) { |
| 229 | − aq->state = AP_STATE_WORKING; | |
| 230 | − return AP_WAIT_AGAIN; | |
| 230 | + aq->sm_state = AP_SM_STATE_WORKING; | |
| 231 | + return AP_SM_WAIT_AGAIN; | |
| 231 | 232 | } |
| 232 | 233 | fallthrough; |
| 233 | 234 | case AP_RESPONSE_Q_FULL: |
| 234 | − aq->state = AP_STATE_QUEUE_FULL; | |
| 235 | − return AP_WAIT_INTERRUPT; | |
| 235 | + aq->sm_state = AP_SM_STATE_QUEUE_FULL; | |
| 236 | + return AP_SM_WAIT_INTERRUPT; | |
| 236 | 237 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 237 | − aq->state = AP_STATE_RESET_WAIT; | |
| 238 | − return AP_WAIT_TIMEOUT; | |
| 238 | + aq->sm_state = AP_SM_STATE_RESET_WAIT; | |
| 239 | + return AP_SM_WAIT_TIMEOUT; | |
| 239 | 240 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
| 240 | 241 | case AP_RESPONSE_REQ_FAC_NOT_INST: |
| 241 | 242 | list_del_init(&ap_msg->list); |
| 242 | 243 | aq->requestq_count--; |
| 243 | 244 | ap_msg->rc = -EINVAL; |
| 244 | 245 | ap_msg->receive(aq, ap_msg, NULL); |
| 245 | − return AP_WAIT_AGAIN; | |
| 246 | + return AP_SM_WAIT_AGAIN; | |
| 246 | 247 | default: |
| 247 | − aq->state = AP_STATE_BORKED; | |
| 248 | − return AP_WAIT_NONE; | |
| 248 | + aq->sm_state = AP_SM_STATE_BORKED; | |
| 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 | 254 | * ap_sm_read_write(): Send and receive messages to/from an AP queue. |
| 254 | 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 | 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 | 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 | 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 | 275 | switch (status.response_code) { |
| 275 | 276 | case AP_RESPONSE_NORMAL: |
| 276 | 277 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 277 | − aq->state = AP_STATE_RESET_WAIT; | |
| 278 | + aq->sm_state = AP_SM_STATE_RESET_WAIT; | |
| 278 | 279 | aq->interrupt = AP_INTR_DISABLED; |
| 279 | − return AP_WAIT_TIMEOUT; | |
| 280 | + return AP_SM_WAIT_TIMEOUT; | |
| 280 | 281 | case AP_RESPONSE_BUSY: |
| 281 | − return AP_WAIT_TIMEOUT; | |
| 282 | + return AP_SM_WAIT_TIMEOUT; | |
| 282 | 283 | case AP_RESPONSE_Q_NOT_AVAIL: |
| 283 | 284 | case AP_RESPONSE_DECONFIGURED: |
| 284 | 285 | case AP_RESPONSE_CHECKSTOPPED: |
| 285 | 286 | default: |
| 286 | − aq->state = AP_STATE_BORKED; | |
| 287 | − return AP_WAIT_NONE; | |
| 287 | + aq->sm_state = AP_SM_STATE_BORKED; | |
| 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 | 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 | 300 | struct ap_queue_status status; |
| 300 | 301 | void *lsi_ptr; |
| @@ -310,20 +311,20 @@ static enum ap_wait ap_sm_reset_wait(struct ap_queue *aq) · 9 unmodified lines | ||
| 310 | 311 | case AP_RESPONSE_NORMAL: |
| 311 | 312 | lsi_ptr = ap_airq_ptr(); |
| 312 | 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 | 315 | else |
| 315 | − aq->state = (aq->queue_count > 0) ? | |
| 316 | − AP_STATE_WORKING : AP_STATE_IDLE; | |
| 317 | − return AP_WAIT_AGAIN; | |
| 316 | + aq->sm_state = (aq->queue_count > 0) ? | |
| 317 | + AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; | |
| 318 | + return AP_SM_WAIT_AGAIN; | |
| 318 | 319 | case AP_RESPONSE_BUSY: |
| 319 | 320 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 320 | − return AP_WAIT_TIMEOUT; | |
| 321 | + return AP_SM_WAIT_TIMEOUT; | |
| 321 | 322 | case AP_RESPONSE_Q_NOT_AVAIL: |
| 322 | 323 | case AP_RESPONSE_DECONFIGURED: |
| 323 | 324 | case AP_RESPONSE_CHECKSTOPPED: |
| 324 | 325 | default: |
| 325 | − aq->state = AP_STATE_BORKED; | |
| 326 | − return AP_WAIT_NONE; | |
| 326 | + aq->sm_state = AP_SM_STATE_BORKED; | |
| 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 | 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 | 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 | 348 | if (status.irq_enabled == 1) { |
| 348 | 349 | /* Irqs are now enabled */ |
| 349 | 350 | aq->interrupt = AP_INTR_ENABLED; |
| 350 | − aq->state = (aq->queue_count > 0) ? | |
| 351 | − AP_STATE_WORKING : AP_STATE_IDLE; | |
| 351 | + aq->sm_state = (aq->queue_count > 0) ? | |
| 352 | + AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; | |
| 352 | 353 | } |
| 353 | 354 | |
| 354 | 355 | switch (status.response_code) { |
| 355 | 356 | case AP_RESPONSE_NORMAL: |
| 356 | 357 | if (aq->queue_count > 0) |
| 357 | − return AP_WAIT_AGAIN; | |
| 358 | + return AP_SM_WAIT_AGAIN; | |
| 358 | 359 | fallthrough; |
| 359 | 360 | case AP_RESPONSE_NO_PENDING_REPLY: |
| 360 | − return AP_WAIT_TIMEOUT; | |
| 361 | + return AP_SM_WAIT_TIMEOUT; | |
| 361 | 362 | default: |
| 362 | − aq->state = AP_STATE_BORKED; | |
| 363 | − return AP_WAIT_NONE; | |
| 363 | + aq->sm_state = AP_SM_STATE_BORKED; | |
| 364 | + return AP_SM_WAIT_NONE; | |
| 364 | 365 | } |
| 365 | 366 | } |
| 366 | 367 | |
| 367 | 368 | /* |
| 368 | 369 | * AP state machine jump table |
| 369 | 370 | */ |
| 370 | −static ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = { | |
| 371 | − [AP_STATE_RESET_START] = { | |
| 372 | − [AP_EVENT_POLL] = ap_sm_reset, | |
| 373 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 371 | +static ap_func_t *ap_jumptable[NR_AP_SM_STATES][NR_AP_SM_EVENTS] = { | |
| 372 | + [AP_SM_STATE_RESET_START] = { | |
| 373 | + [AP_SM_EVENT_POLL] = ap_sm_reset, | |
| 374 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, | |
| 374 | 375 | }, |
| 375 | − [AP_STATE_RESET_WAIT] = { | |
| 376 | − [AP_EVENT_POLL] = ap_sm_reset_wait, | |
| 377 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 376 | + [AP_SM_STATE_RESET_WAIT] = { | |
| 377 | + [AP_SM_EVENT_POLL] = ap_sm_reset_wait, | |
| 378 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, | |
| 378 | 379 | }, |
| 379 | − [AP_STATE_SETIRQ_WAIT] = { | |
| 380 | − [AP_EVENT_POLL] = ap_sm_setirq_wait, | |
| 381 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 380 | + [AP_SM_STATE_SETIRQ_WAIT] = { | |
| 381 | + [AP_SM_EVENT_POLL] = ap_sm_setirq_wait, | |
| 382 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, | |
| 382 | 383 | }, |
| 383 | − [AP_STATE_IDLE] = { | |
| 384 | − [AP_EVENT_POLL] = ap_sm_write, | |
| 385 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 384 | + [AP_SM_STATE_IDLE] = { | |
| 385 | + [AP_SM_EVENT_POLL] = ap_sm_write, | |
| 386 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, | |
| 386 | 387 | }, |
| 387 | − [AP_STATE_WORKING] = { | |
| 388 | − [AP_EVENT_POLL] = ap_sm_read_write, | |
| 389 | − [AP_EVENT_TIMEOUT] = ap_sm_reset, | |
| 388 | + [AP_SM_STATE_WORKING] = { | |
| 389 | + [AP_SM_EVENT_POLL] = ap_sm_read_write, | |
| 390 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_reset, | |
| 390 | 391 | }, |
| 391 | − [AP_STATE_QUEUE_FULL] = { | |
| 392 | − [AP_EVENT_POLL] = ap_sm_read, | |
| 393 | − [AP_EVENT_TIMEOUT] = ap_sm_reset, | |
| 392 | + [AP_SM_STATE_QUEUE_FULL] = { | |
| 393 | + [AP_SM_EVENT_POLL] = ap_sm_read, | |
| 394 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_reset, | |
| 394 | 395 | }, |
| 395 | − [AP_STATE_REMOVE] = { | |
| 396 | − [AP_EVENT_POLL] = ap_sm_nop, | |
| 397 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 396 | + [AP_SM_STATE_REMOVE] = { | |
| 397 | + [AP_SM_EVENT_POLL] = ap_sm_nop, | |
| 398 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, | |
| 398 | 399 | }, |
| 399 | − [AP_STATE_UNBOUND] = { | |
| 400 | − [AP_EVENT_POLL] = ap_sm_nop, | |
| 401 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 400 | + [AP_SM_STATE_UNBOUND] = { | |
| 401 | + [AP_SM_EVENT_POLL] = ap_sm_nop, | |
| 402 | + [AP_SM_EVENT_TIMEOUT] = ap_sm_nop, | |
| 402 | 403 | }, |
| 403 | − [AP_STATE_BORKED] = { | |
| 404 | − [AP_EVENT_POLL] = ap_sm_nop, | |
| 405 | − [AP_EVENT_TIMEOUT] = ap_sm_nop, | |
| 404 | + [AP_SM_STATE_BORKED] = { | |
| 405 | + [AP_SM_EVENT_POLL] = 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 | 421 | return wait; |
| 421 | 422 | } |
| @@ -486,13 +487,13 @@ static ssize_t reset_show(struct device *dev, · 64 unmodified lines | ||
| 486 | 487 | int rc = 0; |
| 487 | 488 | |
| 488 | 489 | spin_lock_bh(&aq->lock); |
| 489 | − switch (aq->state) { | |
| 490 | − case AP_STATE_RESET_START: | |
| 491 | − case AP_STATE_RESET_WAIT: | |
| 490 | + switch (aq->sm_state) { | |
| 491 | + case AP_SM_STATE_RESET_START: | |
| 492 | + case AP_SM_STATE_RESET_WAIT: | |
| 492 | 493 | rc = scnprintf(buf, PAGE_SIZE, "Reset in progress.\n"); |
| 493 | 494 | break; |
| 494 | − case AP_STATE_WORKING: | |
| 495 | − case AP_STATE_QUEUE_FULL: | |
| 495 | + case AP_SM_STATE_WORKING: | |
| 496 | + case AP_SM_STATE_QUEUE_FULL: | |
| 496 | 497 | rc = scnprintf(buf, PAGE_SIZE, "Reset Timer armed.\n"); |
| 497 | 498 | break; |
| 498 | 499 | default: |
| @@ -510,8 +511,8 @@ static ssize_t reset_store(struct device *dev, · 11 unmodified lines | ||
| 510 | 511 | |
| 511 | 512 | spin_lock_bh(&aq->lock); |
| 512 | 513 | __ap_flush_queue(aq); |
| 513 | − aq->state = AP_STATE_RESET_START; | |
| 514 | − ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); | |
| 514 | + aq->sm_state = AP_SM_STATE_RESET_START; | |
| 515 | + ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); | |
| 515 | 516 | spin_unlock_bh(&aq->lock); |
| 516 | 517 | |
| 517 | 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 | 530 | int rc = 0; |
| 530 | 531 | |
| 531 | 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 | 534 | rc = scnprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n"); |
| 534 | 535 | else if (aq->interrupt == AP_INTR_ENABLED) |
| 535 | 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 | 587 | aq->ap_dev.device.type = &ap_queue_type; |
| 587 | 588 | aq->ap_dev.device_type = device_type; |
| 588 | 589 | aq->qid = qid; |
| 589 | − aq->state = AP_STATE_UNBOUND; | |
| 590 | + aq->sm_state = AP_SM_STATE_UNBOUND; | |
| 590 | 591 | aq->interrupt = AP_INTR_DISABLED; |
| 591 | 592 | spin_lock_init(&aq->lock); |
| 592 | 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 | 602 | aq->reply = reply; |
| 602 | 603 | |
| 603 | 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 | 606 | spin_unlock_bh(&aq->lock); |
| 606 | 607 | } |
| 607 | 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 | 626 | aq->total_request_count++; |
| 626 | 627 | atomic64_inc(&aq->card->total_request_count); |
| 627 | 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 | 630 | spin_unlock_bh(&aq->lock); |
| 630 | 631 | } |
| 631 | 632 | EXPORT_SYMBOL(ap_queue_message); |
| @@ -698,7 +699,7 @@ void ap_queue_prepare_remove(struct ap_queue *aq) · 66 unmodified lines | ||
| 698 | 699 | /* flush queue */ |
| 699 | 700 | __ap_flush_queue(aq); |
| 700 | 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 | 703 | spin_unlock_bh(&aq->lock); |
| 703 | 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 | 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 | 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 | 714 | * is not used by any driver currently. |
| 714 | 715 | */ |
| 715 | 716 | spin_lock_bh(&aq->lock); |
| 716 | 717 | ap_zapq(aq->qid); |
| 717 | − aq->state = AP_STATE_UNBOUND; | |
| 718 | + aq->sm_state = AP_SM_STATE_UNBOUND; | |
| 718 | 719 | spin_unlock_bh(&aq->lock); |
| 719 | 720 | } |
| 720 | 721 | |
| 721 | 722 | void ap_queue_init_state(struct ap_queue *aq) |
| 722 | 723 | { |
| 723 | 724 | spin_lock_bh(&aq->lock); |
| 724 | − aq->state = AP_STATE_RESET_START; | |
| 725 | − ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); | |
| 725 | + aq->sm_state = AP_SM_STATE_RESET_START; | |
| 726 | + ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); | |
| 726 | 727 | spin_unlock_bh(&aq->lock); |
| 727 | 728 | } |
| 728 | 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 | 1603 | if (rc == 0) |
| 1604 | 1604 | break; |
| 1605 | 1605 | } |
| 1606 | − if (rc) | |
| 1607 | − return rc; | |
| 1606 | + if (rc) | |
| 1607 | + return rc; | |
| 1608 | 1608 | |
| 1609 | 1609 | if (is_xts) { |
| 1610 | 1610 | keysize = CCACIPHERTOKENSIZE; |
| @@ -634,7 +634,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms, · 633 unmodified lines | ||
| 634 | 634 | { |
| 635 | 635 | struct zcrypt_card *zc, *pref_zc; |
| 636 | 636 | struct zcrypt_queue *zq, *pref_zq; |
| 637 | − unsigned int weight, pref_weight; | |
| 637 | + unsigned int weight = 0, pref_weight = 0; | |
| 638 | 638 | unsigned int func_code; |
| 639 | 639 | int qid = 0, rc = -ENODEV; |
| 640 | 640 | struct module *mod; |
| @@ -718,7 +718,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms, · 77 unmodified lines | ||
| 718 | 718 | { |
| 719 | 719 | struct zcrypt_card *zc, *pref_zc; |
| 720 | 720 | struct zcrypt_queue *zq, *pref_zq; |
| 721 | − unsigned int weight, pref_weight; | |
| 721 | + unsigned int weight = 0, pref_weight = 0; | |
| 722 | 722 | unsigned int func_code; |
| 723 | 723 | int qid = 0, rc = -ENODEV; |
| 724 | 724 | struct module *mod; |
| @@ -803,7 +803,7 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, · 78 unmodified lines | ||
| 803 | 803 | struct zcrypt_card *zc, *pref_zc; |
| 804 | 804 | struct zcrypt_queue *zq, *pref_zq; |
| 805 | 805 | struct ap_message ap_msg; |
| 806 | − unsigned int weight, pref_weight; | |
| 806 | + unsigned int weight = 0, pref_weight = 0; | |
| 807 | 807 | unsigned int func_code; |
| 808 | 808 | unsigned short *domain, tdom; |
| 809 | 809 | int qid = 0, rc = -ENODEV; |
| @@ -822,7 +822,7 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, · 12 unmodified lines | ||
| 822 | 822 | * domain but a control only domain, use the default domain as target. |
| 823 | 823 | */ |
| 824 | 824 | tdom = *domain; |
| 825 | − if (tdom >= 0 && tdom < AP_DOMAINS && | |
| 825 | + if (tdom < AP_DOMAINS && | |
| 826 | 826 | !ap_test_config_usage_domain(tdom) && |
| 827 | 827 | ap_test_config_ctrl_domain(tdom) && |
| 828 | 828 | ap_domain_index >= 0) |
| @@ -931,7 +931,7 @@ static long _zcrypt_send_ep11_cprb(struct ap_perms *perms, · 102 unmodified lines | ||
| 931 | 931 | struct zcrypt_queue *zq, *pref_zq; |
| 932 | 932 | struct ep11_target_dev *targets; |
| 933 | 933 | unsigned short target_num; |
| 934 | − unsigned int weight, pref_weight; | |
| 934 | + unsigned int weight = 0, pref_weight = 0; | |
| 935 | 935 | unsigned int func_code; |
| 936 | 936 | struct ap_message ap_msg; |
| 937 | 937 | int qid = 0, rc = -ENODEV; |
| @@ -1040,7 +1040,7 @@ static long zcrypt_rng(char *buffer) · 102 unmodified lines | ||
| 1040 | 1040 | { |
| 1041 | 1041 | struct zcrypt_card *zc, *pref_zc; |
| 1042 | 1042 | struct zcrypt_queue *zq, *pref_zq; |
| 1043 | − unsigned int weight, pref_weight; | |
| 1043 | + unsigned int weight = 0, pref_weight = 0; | |
| 1044 | 1044 | unsigned int func_code; |
| 1045 | 1045 | struct ap_message ap_msg; |
| 1046 | 1046 | unsigned int domain; |
| @@ -1298,99 +1298,119 @@ static int zcrypt_requestq_count(void) · 251 unmodified lines | ||
| 1298 | 1298 | return requestq_count; |
| 1299 | 1299 | } |
| 1300 | 1300 | |
| 1301 | −static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |
| 1302 | − unsigned long arg) | |
| 1301 | +static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg) | |
| 1303 | 1302 | { |
| 1304 | 1303 | int rc; |
| 1305 | − struct ap_perms *perms = | |
| 1306 | − (struct ap_perms *) filp->private_data; | |
| 1304 | + struct ica_rsa_modexpo mex; | |
| 1305 | + struct ica_rsa_modexpo __user *umex = (void __user *) arg; | |
| 1307 | 1306 | |
| 1308 | − rc = zcrypt_check_ioctl(perms, cmd); | |
| 1309 | − if (rc) | |
| 1310 | − return rc; | |
| 1311 | − | |
| 1312 | − switch (cmd) { | |
| 1313 | − case ICARSAMODEXPO: { | |
| 1314 | − struct ica_rsa_modexpo __user *umex = (void __user *) arg; | |
| 1315 | − struct ica_rsa_modexpo mex; | |
| 1316 | − | |
| 1317 | − if (copy_from_user(&mex, umex, sizeof(mex))) | |
| 1318 | − return -EFAULT; | |
| 1307 | + if (copy_from_user(&mex, umex, sizeof(mex))) | |
| 1308 | + return -EFAULT; | |
| 1309 | + do { | |
| 1310 | + rc = zcrypt_rsa_modexpo(perms, &mex); | |
| 1311 | + } while (rc == -EAGAIN); | |
| 1312 | + /* on failure: retry once again after a requested rescan */ | |
| 1313 | + if ((rc == -ENODEV) && (zcrypt_process_rescan())) | |
| 1319 | 1314 | do { |
| 1320 | 1315 | rc = zcrypt_rsa_modexpo(perms, &mex); |
| 1321 | 1316 | } while (rc == -EAGAIN); |
| 1322 | − /* on failure: retry once again after a requested rescan */ | |
| 1323 | − if ((rc == -ENODEV) && (zcrypt_process_rescan())) | |
| 1324 | − do { | |
| 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); | |
| 1317 | + if (rc) { | |
| 1318 | + ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc); | |
| 1319 | + return rc; | |
| 1332 | 1320 | } |
| 1333 | − case ICARSACRT: { | |
| 1334 | − struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg; | |
| 1335 | − struct ica_rsa_modexpo_crt crt; | |
| 1321 | + return put_user(mex.outputdatalength, &umex->outputdatalength); | |
| 1322 | +} | |
| 1336 | 1323 | |
| 1337 | − if (copy_from_user(&crt, ucrt, sizeof(crt))) | |
| 1338 | − return -EFAULT; | |
| 1324 | +static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg) | |
| 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 | 1337 | do { |
| 1340 | 1338 | rc = zcrypt_rsa_crt(perms, &crt); |
| 1341 | 1339 | } while (rc == -EAGAIN); |
| 1342 | − /* on failure: retry once again after a requested rescan */ | |
| 1343 | − if ((rc == -ENODEV) && (zcrypt_process_rescan())) | |
| 1344 | − do { | |
| 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); | |
| 1340 | + if (rc) { | |
| 1341 | + ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc); | |
| 1342 | + return rc; | |
| 1352 | 1343 | } |
| 1353 | − case ZSECSENDCPRB: { | |
| 1354 | − struct ica_xcRB __user *uxcRB = (void __user *) arg; | |
| 1355 | − struct ica_xcRB xcRB; | |
| 1344 | + return put_user(crt.outputdatalength, &ucrt->outputdatalength); | |
| 1345 | +} | |
| 1356 | 1346 | |
| 1357 | − if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB))) | |
| 1358 | − return -EFAULT; | |
| 1347 | +static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg) | |
| 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 | 1360 | do { |
| 1360 | 1361 | rc = _zcrypt_send_cprb(perms, &xcRB); |
| 1361 | 1362 | } while (rc == -EAGAIN); |
| 1362 | − /* on failure: retry once again after a requested rescan */ | |
| 1363 | − if ((rc == -ENODEV) && (zcrypt_process_rescan())) | |
| 1364 | − do { | |
| 1365 | − rc = _zcrypt_send_cprb(perms, &xcRB); | |
| 1366 | − } while (rc == -EAGAIN); | |
| 1367 | − if (rc) | |
| 1368 | − ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n", | |
| 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; | |
| 1363 | + if (rc) | |
| 1364 | + ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n", | |
| 1365 | + rc, xcRB.status); | |
| 1366 | + if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) | |
| 1367 | + return -EFAULT; | |
| 1368 | + return rc; | |
| 1369 | +} | |
| 1377 | 1370 | |
| 1378 | − if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) | |
| 1379 | − return -EFAULT; | |
| 1371 | +static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg) | |
| 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 | 1384 | do { |
| 1381 | 1385 | rc = _zcrypt_send_ep11_cprb(perms, &xcrb); |
| 1382 | 1386 | } while (rc == -EAGAIN); |
| 1383 | − /* on failure: retry once again after a requested rescan */ | |
| 1384 | − if ((rc == -ENODEV) && (zcrypt_process_rescan())) | |
| 1385 | − do { | |
| 1386 | − rc = _zcrypt_send_ep11_cprb(perms, &xcrb); | |
| 1387 | − } while (rc == -EAGAIN); | |
| 1388 | − if (rc) | |
| 1389 | − ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc); | |
| 1390 | − if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) | |
| 1391 | − return -EFAULT; | |
| 1387 | + if (rc) | |
| 1388 | + ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc); | |
| 1389 | + if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) | |
| 1390 | + return -EFAULT; | |
| 1391 | + return rc; | |
| 1392 | +} | |
| 1393 | + | |
| 1394 | +static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |
| 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 | 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 | 1414 | case ZCRYPT_DEVICE_STATUS: { |
| 1395 | 1415 | struct zcrypt_device_status_ext *device_status; |
| 1396 | 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 | 205 | preqcblk->rpl_msgbl = cprbplusparamblen; |
| 206 | 206 | if (paramblen) { |
| 207 | 207 | preqcblk->req_parmb = |
| 208 | − ((u8 *) preqcblk) + sizeof(struct CPRBX); | |
| 208 | + ((u8 __user *) preqcblk) + sizeof(struct CPRBX); | |
| 209 | 209 | preqcblk->rpl_parmb = |
| 210 | − ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 210 | + ((u8 __user *) prepcblk) + sizeof(struct CPRBX); | |
| 211 | 211 | } |
| 212 | 212 | |
| 213 | 213 | *pcprbmem = cprbmem; |
| @@ -274,7 +274,7 @@ int cca_genseckey(u16 cardnr, u16 domain, · 60 unmodified lines | ||
| 274 | 274 | { |
| 275 | 275 | int i, rc, keysize; |
| 276 | 276 | int seckeysize; |
| 277 | − u8 *mem; | |
| 277 | + u8 *mem, *ptr; | |
| 278 | 278 | struct CPRBX *preqcblk, *prepcblk; |
| 279 | 279 | struct ica_xcRB xcrb; |
| 280 | 280 | struct kgreqparm { |
| @@ -320,7 +320,7 @@ int cca_genseckey(u16 cardnr, u16 domain, · 39 unmodified lines | ||
| 320 | 320 | preqcblk->domain = domain; |
| 321 | 321 | |
| 322 | 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 | 324 | memcpy(preqparm->subfunc_code, "KG", 2); |
| 325 | 325 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); |
| 326 | 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 | 379 | /* process response cprb param block */ |
| 380 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 381 | − prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; | |
| 380 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 381 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 382 | + prepparm = (struct kgrepparm *) ptr; | |
| 382 | 383 | |
| 383 | 384 | /* check length of the returned secure key token */ |
| 384 | 385 | seckeysize = prepparm->lv3.keyblock.toklen |
| @@ -415,7 +416,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, · 30 unmodified lines | ||
| 415 | 416 | const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE]) |
| 416 | 417 | { |
| 417 | 418 | int rc, keysize, seckeysize; |
| 418 | − u8 *mem; | |
| 419 | + u8 *mem, *ptr; | |
| 419 | 420 | struct CPRBX *preqcblk, *prepcblk; |
| 420 | 421 | struct ica_xcRB xcrb; |
| 421 | 422 | struct cmreqparm { |
| @@ -460,7 +461,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, · 38 unmodified lines | ||
| 460 | 461 | preqcblk->domain = domain; |
| 461 | 462 | |
| 462 | 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 | 465 | memcpy(preqparm->subfunc_code, "CM", 2); |
| 465 | 466 | memcpy(preqparm->rule_array, "AES ", 8); |
| 466 | 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 | 517 | /* process response cprb param block */ |
| 517 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 518 | − prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; | |
| 518 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 519 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 520 | + prepparm = (struct cmrepparm *) ptr; | |
| 519 | 521 | |
| 520 | 522 | /* check length of the returned secure key token */ |
| 521 | 523 | seckeysize = prepparm->lv3.keyblock.toklen |
| @@ -554,7 +556,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, · 32 unmodified lines | ||
| 554 | 556 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
| 555 | 557 | { |
| 556 | 558 | int rc; |
| 557 | − u8 *mem; | |
| 559 | + u8 *mem, *ptr; | |
| 558 | 560 | struct CPRBX *preqcblk, *prepcblk; |
| 559 | 561 | struct ica_xcRB xcrb; |
| 560 | 562 | struct uskreqparm { |
| @@ -605,7 +607,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, · 44 unmodified lines | ||
| 605 | 607 | preqcblk->domain = domain; |
| 606 | 608 | |
| 607 | 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 | 611 | memcpy(preqparm->subfunc_code, "US", 2); |
| 610 | 612 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); |
| 611 | 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 | 650 | /* process response cprb param block */ |
| 649 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 650 | − prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; | |
| 651 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 652 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 653 | + prepparm = (struct uskrepparm *) ptr; | |
| 651 | 654 | |
| 652 | 655 | /* check the returned keyblock */ |
| 653 | 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 | 717 | u8 *keybuf, size_t *keybufsize) |
| 715 | 718 | { |
| 716 | 719 | int rc; |
| 717 | − u8 *mem; | |
| 720 | + u8 *mem, *ptr; | |
| 718 | 721 | struct CPRBX *preqcblk, *prepcblk; |
| 719 | 722 | struct ica_xcRB xcrb; |
| 720 | 723 | struct gkreqparm { |
| @@ -796,7 +799,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, · 75 unmodified lines | ||
| 796 | 799 | preqcblk->req_parml = sizeof(struct gkreqparm); |
| 797 | 800 | |
| 798 | 801 | /* prepare request param block with GK request */ |
| 799 | − preqparm = (struct gkreqparm *) preqcblk->req_parmb; | |
| 802 | + preqparm = (struct gkreqparm __force *) preqcblk->req_parmb; | |
| 800 | 803 | memcpy(preqparm->subfunc_code, "GK", 2); |
| 801 | 804 | preqparm->rule_array_len = sizeof(uint16_t) + 2 * 8; |
| 802 | 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 | 872 | /* process response cprb param block */ |
| 870 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 871 | − prepparm = (struct gkrepparm *) prepcblk->rpl_parmb; | |
| 873 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 874 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 875 | + prepparm = (struct gkrepparm *) ptr; | |
| 872 | 876 | |
| 873 | 877 | /* do some plausibility checks on the key block */ |
| 874 | 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 | 921 | int *key_token_size) |
| 918 | 922 | { |
| 919 | 923 | int rc, n; |
| 920 | − u8 *mem; | |
| 924 | + u8 *mem, *ptr; | |
| 921 | 925 | struct CPRBX *preqcblk, *prepcblk; |
| 922 | 926 | struct ica_xcRB xcrb; |
| 923 | 927 | struct rule_array_block { |
| @@ -974,7 +978,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain, · 50 unmodified lines | ||
| 974 | 978 | preqcblk->req_parml = 0; |
| 975 | 979 | |
| 976 | 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 | 982 | memcpy(preq_ra_block->subfunc_code, "IP", 2); |
| 979 | 983 | preq_ra_block->rule_array_len = sizeof(uint16_t) + 2 * 8; |
| 980 | 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 | 993 | /* prepare vud block */ |
| 990 | − preq_vud_block = (struct vud_block *) | |
| 994 | + preq_vud_block = (struct vud_block __force *) | |
| 991 | 995 | (preqcblk->req_parmb + preqcblk->req_parml); |
| 992 | 996 | n = complete ? 0 : (clr_key_bit_size + 7) / 8; |
| 993 | 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 | 1005 | preqcblk->req_parml += preq_vud_block->len; |
| 1002 | 1006 | |
| 1003 | 1007 | /* prepare key block */ |
| 1004 | − preq_key_block = (struct key_block *) | |
| 1008 | + preq_key_block = (struct key_block __force *) | |
| 1005 | 1009 | (preqcblk->req_parmb + preqcblk->req_parml); |
| 1006 | 1010 | n = *key_token_size; |
| 1007 | 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 | 1040 | /* process response cprb param block */ |
| 1037 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 1038 | − prepparm = (struct iprepparm *) prepcblk->rpl_parmb; | |
| 1041 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 1042 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 1043 | + prepparm = (struct iprepparm *) ptr; | |
| 1039 | 1044 | |
| 1040 | 1045 | /* do some plausibility checks on the key block */ |
| 1041 | 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 | 1156 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
| 1152 | 1157 | { |
| 1153 | 1158 | int rc; |
| 1154 | − u8 *mem; | |
| 1159 | + u8 *mem, *ptr; | |
| 1155 | 1160 | struct CPRBX *preqcblk, *prepcblk; |
| 1156 | 1161 | struct ica_xcRB xcrb; |
| 1157 | 1162 | struct aureqparm { |
| @@ -1208,7 +1213,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, · 50 unmodified lines | ||
| 1208 | 1213 | preqcblk->domain = domain; |
| 1209 | 1214 | |
| 1210 | 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 | 1217 | memcpy(preqparm->subfunc_code, "AU", 2); |
| 1213 | 1218 | preqparm->rule_array_len = |
| 1214 | 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 | 1264 | /* process response cprb param block */ |
| 1260 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 1261 | − prepparm = (struct aurepparm *) prepcblk->rpl_parmb; | |
| 1265 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 1266 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 1267 | + prepparm = (struct aurepparm *) ptr; | |
| 1262 | 1268 | |
| 1263 | 1269 | /* check the returned keyblock */ |
| 1264 | 1270 | if (prepparm->vud.ckb.version != 0x01 && |
| @@ -1347,7 +1353,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, · 82 unmodified lines | ||
| 1347 | 1353 | preqcblk->domain = domain; |
| 1348 | 1354 | |
| 1349 | 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 | 1357 | memcpy(preqparm->subfunc_code, "FQ", 2); |
| 1352 | 1358 | memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); |
| 1353 | 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 | 1386 | /* process response cprb param block */ |
| 1381 | − prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 1382 | − prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; | |
| 1387 | + ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX); | |
| 1388 | + prepcblk->rpl_parmb = (u8 __user *) ptr; | |
| 1389 | + prepparm = (struct fqrepparm *) ptr; | |
| 1383 | 1390 | ptr = prepparm->lvdata; |
| 1384 | 1391 | |
| 1385 | 1392 | /* check and possibly copy reply rule array */ |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | #include "zcrypt_msgtype6.h" |
| 26 | 26 | #include "zcrypt_cex2c.h" |
| 27 | 27 | #include "zcrypt_cca_key.h" |
| 28 | +#include "zcrypt_ccamisc.h" | |
| 28 | 29 | |
| 29 | 30 | #define CEX2C_MIN_MOD_SIZE 16 /* 128 bits */ |
| 30 | 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 | 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 | 148 | * Large random number detection function. Its sends a message to a CEX2C/CEX3C |
| 63 | 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 | 173 | int rc, i; |
| 88 | 174 | |
| 89 | 175 | ap_init_message(&ap_msg); |
| 90 | − ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | |
| 91 | − if (!ap_msg.message) | |
| 176 | + ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); | |
| 177 | + if (!ap_msg.msg) | |
| 92 | 178 | return -ENOMEM; |
| 93 | 179 | |
| 94 | 180 | rng_type6CPRB_msgX(&ap_msg, 4, &domain); |
| 95 | 181 | |
| 96 | − msg = ap_msg.message; | |
| 182 | + msg = ap_msg.msg; | |
| 97 | 183 | msg->cprbx.domain = AP_QID_QUEUE(aq->qid); |
| 98 | 184 | |
| 99 | − rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.message, | |
| 100 | − ap_msg.length); | |
| 185 | + rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.msg, ap_msg.len); | |
| 101 | 186 | if (rc) |
| 102 | 187 | goto out_free; |
| 103 | 188 | |
| 104 | 189 | /* Wait for the test message to complete. */ |
| 105 | 190 | for (i = 0; i < 2 * HZ; i++) { |
| 106 | 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 | 193 | if (rc == 0 && psmid == 0x0102030405060708ULL) |
| 109 | 194 | break; |
| 110 | 195 | } |
| @@ -115,13 +200,13 @@ static int zcrypt_cex2c_rng_supported(struct ap_queue *aq) · 4 unmodified lines | ||
| 115 | 200 | goto out_free; |
| 116 | 201 | } |
| 117 | 202 | |
| 118 | − reply = ap_msg.message; | |
| 203 | + reply = ap_msg.msg; | |
| 119 | 204 | if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0) |
| 120 | 205 | rc = 1; |
| 121 | 206 | else |
| 122 | 207 | rc = 0; |
| 123 | 208 | out_free: |
| 124 | − free_page((unsigned long) ap_msg.message); | |
| 209 | + free_page((unsigned long) ap_msg.msg); | |
| 125 | 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 | 264 | if (rc) { |
| 180 | 265 | ac->private = NULL; |
| 181 | 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 | 280 | return rc; |
| @@ -190,8 +286,11 @@ static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) · 5 unmodified lines | ||
| 190 | 286 | */ |
| 191 | 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 | 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 | 294 | if (zc) |
| 196 | 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 | 339 | if (rc) { |
| 241 | 340 | aq->private = NULL; |
| 242 | 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 | 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 | 364 | struct ap_queue *aq = to_ap_queue(&ap_dev->device); |
| 254 | 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 | 369 | if (zq) |
| 257 | 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 | 250 | ep11_get_card_info(ac->id, &ci, zc->online); |
| 251 | 251 | |
| 252 | 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 | 254 | if (n > 0) |
| 255 | 255 | buf[n++] = ' '; |
| 256 | 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 | 345 | &di); |
| 346 | 346 | |
| 347 | 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 | 349 | if (n > 0) |
| 350 | 350 | buf[n++] = ' '; |
| 351 | 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 | 529 | if (rc) { |
| 530 | 530 | ac->private = NULL; |
| 531 | 531 | zcrypt_card_free(zc); |
| 532 | − goto out; | |
| 532 | + return rc; | |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | 535 | if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { |
| 536 | 536 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 537 | 537 | &cca_card_attr_grp); |
| 538 | − if (rc) | |
| 538 | + if (rc) { | |
| 539 | 539 | zcrypt_card_unregister(zc); |
| 540 | + ac->private = NULL; | |
| 541 | + zcrypt_card_free(zc); | |
| 542 | + } | |
| 540 | 543 | } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) { |
| 541 | 544 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 542 | 545 | &ep11_card_attr_grp); |
| 543 | − if (rc) | |
| 546 | + if (rc) { | |
| 544 | 547 | zcrypt_card_unregister(zc); |
| 548 | + ac->private = NULL; | |
| 549 | + zcrypt_card_free(zc); | |
| 550 | + } | |
| 545 | 551 | } |
| 546 | 552 | |
| 547 | −out: | |
| 548 | 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 | 622 | if (rc) { |
| 618 | 623 | aq->private = NULL; |
| 619 | 624 | zcrypt_queue_free(zq); |
| 620 | − goto out; | |
| 625 | + return rc; | |
| 621 | 626 | } |
| 622 | 627 | |
| 623 | 628 | if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { |
| 624 | 629 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 625 | 630 | &cca_queue_attr_grp); |
| 626 | − if (rc) | |
| 631 | + if (rc) { | |
| 627 | 632 | zcrypt_queue_unregister(zq); |
| 633 | + aq->private = NULL; | |
| 634 | + zcrypt_queue_free(zq); | |
| 635 | + } | |
| 628 | 636 | } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) { |
| 629 | 637 | rc = sysfs_create_group(&ap_dev->device.kobj, |
| 630 | 638 | &ep11_queue_attr_grp); |
| 631 | − if (rc) | |
| 639 | + if (rc) { | |
| 632 | 640 | zcrypt_queue_unregister(zq); |
| 641 | + aq->private = NULL; | |
| 642 | + zcrypt_queue_free(zq); | |
| 643 | + } | |
| 633 | 644 | } |
| 634 | 645 | |
| 635 | −out: | |
| 636 | 646 | return rc; |
| 637 | 647 | } |
| 638 | 648 | |
| @@ -80,7 +80,7 @@ struct error_hdr { · 79 unmodified lines | ||
| 80 | 80 | static inline int convert_error(struct zcrypt_queue *zq, |
| 81 | 81 | struct ap_message *reply) |
| 82 | 82 | { |
| 83 | − struct error_hdr *ehdr = reply->message; | |
| 83 | + struct error_hdr *ehdr = reply->msg; | |
| 84 | 84 | int card = AP_QID_CARD(zq->queue->qid); |
| 85 | 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 | 127 | struct { |
| 128 | 128 | struct type86_hdr hdr; |
| 129 | 129 | struct type86_fmt2_ext fmt2; |
| 130 | − } __packed * head = reply->message; | |
| 130 | + } __packed * head = reply->msg; | |
| 131 | 131 | unsigned int apfs = *((u32 *)head->fmt2.apfs); |
| 132 | 132 | |
| 133 | 133 | ZCRYPT_DBF(DBF_ERR, |
| @@ -207,10 +207,10 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq, · 206 unmodified lines | ||
| 207 | 207 | mod_len = mex->inputdatalength; |
| 208 | 208 | |
| 209 | 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 | 212 | memset(meb1, 0, sizeof(*meb1)); |
| 213 | − ap_msg->length = sizeof(*meb1); | |
| 213 | + ap_msg->len = sizeof(*meb1); | |
| 214 | 214 | meb1->header.msg_type_code = TYPE50_TYPE_CODE; |
| 215 | 215 | meb1->header.msg_len = sizeof(*meb1); |
| 216 | 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 | 218 | exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; |
| 219 | 219 | inp = meb1->message + sizeof(meb1->message) - mod_len; |
| 220 | 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 | 223 | memset(meb2, 0, sizeof(*meb2)); |
| 224 | − ap_msg->length = sizeof(*meb2); | |
| 224 | + ap_msg->len = sizeof(*meb2); | |
| 225 | 225 | meb2->header.msg_type_code = TYPE50_TYPE_CODE; |
| 226 | 226 | meb2->header.msg_len = sizeof(*meb2); |
| 227 | 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 | 229 | exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; |
| 230 | 230 | inp = meb2->message + sizeof(meb2->message) - mod_len; |
| 231 | 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 | 234 | memset(meb3, 0, sizeof(*meb3)); |
| 235 | − ap_msg->length = sizeof(*meb3); | |
| 235 | + ap_msg->len = sizeof(*meb3); | |
| 236 | 236 | meb3->header.msg_type_code = TYPE50_TYPE_CODE; |
| 237 | 237 | meb3->header.msg_len = sizeof(*meb3); |
| 238 | 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 | 275 | * 512 byte modulus (4k keys). |
| 276 | 276 | */ |
| 277 | 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 | 280 | memset(crb1, 0, sizeof(*crb1)); |
| 281 | − ap_msg->length = sizeof(*crb1); | |
| 281 | + ap_msg->len = sizeof(*crb1); | |
| 282 | 282 | crb1->header.msg_type_code = TYPE50_TYPE_CODE; |
| 283 | 283 | crb1->header.msg_len = sizeof(*crb1); |
| 284 | 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 | 289 | u = crb1->u + sizeof(crb1->u) - short_len; |
| 290 | 290 | inp = crb1->message + sizeof(crb1->message) - mod_len; |
| 291 | 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 | 294 | memset(crb2, 0, sizeof(*crb2)); |
| 295 | − ap_msg->length = sizeof(*crb2); | |
| 295 | + ap_msg->len = sizeof(*crb2); | |
| 296 | 296 | crb2->header.msg_type_code = TYPE50_TYPE_CODE; |
| 297 | 297 | crb2->header.msg_len = sizeof(*crb2); |
| 298 | 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 | 304 | inp = crb2->message + sizeof(crb2->message) - mod_len; |
| 305 | 305 | } else if ((mod_len <= 512) && /* up to 4096 bit key size */ |
| 306 | 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 | 309 | memset(crb3, 0, sizeof(*crb3)); |
| 310 | − ap_msg->length = sizeof(*crb3); | |
| 310 | + ap_msg->len = sizeof(*crb3); | |
| 311 | 311 | crb3->header.msg_type_code = TYPE50_TYPE_CODE; |
| 312 | 312 | crb3->header.msg_len = sizeof(*crb3); |
| 313 | 313 | crb3->keyblock_type = TYPE50_CRB3_FMT; |
| @@ -350,7 +350,7 @@ static int convert_type80(struct zcrypt_queue *zq, · 36 unmodified lines | ||
| 350 | 350 | char __user *outputdata, |
| 351 | 351 | unsigned int outputdatalength) |
| 352 | 352 | { |
| 353 | − struct type80_hdr *t80h = reply->message; | |
| 353 | + struct type80_hdr *t80h = reply->msg; | |
| 354 | 354 | unsigned char *data; |
| 355 | 355 | |
| 356 | 356 | if (t80h->len < sizeof(*t80h) + outputdatalength) { |
| @@ -370,7 +370,7 @@ static int convert_type80(struct zcrypt_queue *zq, · 13 unmodified lines | ||
| 370 | 370 | BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); |
| 371 | 371 | else |
| 372 | 372 | BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); |
| 373 | − data = reply->message + t80h->len - outputdatalength; | |
| 373 | + data = reply->msg + t80h->len - outputdatalength; | |
| 374 | 374 | if (copy_to_user(outputdata, data, outputdatalength)) |
| 375 | 375 | return -EFAULT; |
| 376 | 376 | return 0; |
| @@ -382,7 +382,7 @@ static int convert_response(struct zcrypt_queue *zq, · 5 unmodified lines | ||
| 382 | 382 | unsigned int outputdatalength) |
| 383 | 383 | { |
| 384 | 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 | 387 | switch (rtype) { |
| 388 | 388 | case TYPE82_RSP_CODE: |
| @@ -422,22 +422,20 @@ static void zcrypt_cex2a_receive(struct ap_queue *aq, · 33 unmodified lines | ||
| 422 | 422 | .reply_code = REP82_ERROR_MACHINE_FAILURE, |
| 423 | 423 | }; |
| 424 | 424 | struct type80_hdr *t80h; |
| 425 | − int length; | |
| 425 | + int len; | |
| 426 | 426 | |
| 427 | 427 | /* Copy the reply message to the request message buffer. */ |
| 428 | 428 | if (!reply) |
| 429 | 429 | goto out; /* ap_msg->rc indicates the error */ |
| 430 | − t80h = reply->message; | |
| 430 | + t80h = reply->msg; | |
| 431 | 431 | if (t80h->type == TYPE80_RSP_CODE) { |
| 432 | 432 | if (aq->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) |
| 433 | − length = min_t(int, | |
| 434 | − CEX2A_MAX_RESPONSE_SIZE, t80h->len); | |
| 433 | + len = min_t(int, CEX2A_MAX_RESPONSE_SIZE, t80h->len); | |
| 435 | 434 | else |
| 436 | − length = min_t(int, | |
| 437 | − CEX3A_MAX_RESPONSE_SIZE, t80h->len); | |
| 438 | − memcpy(msg->message, reply->message, length); | |
| 435 | + len = min_t(int, CEX3A_MAX_RESPONSE_SIZE, t80h->len); | |
| 436 | + memcpy(msg->msg, reply->msg, len); | |
| 439 | 437 | } else |
| 440 | − memcpy(msg->message, reply->message, sizeof(error_reply)); | |
| 438 | + memcpy(msg->msg, reply->msg, sizeof(error_reply)); | |
| 441 | 439 | out: |
| 442 | 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 | 459 | ap_init_message(&ap_msg); |
| 462 | 460 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
| 463 | − ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, | |
| 464 | − GFP_KERNEL); | |
| 461 | + ap_msg.msg = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, GFP_KERNEL); | |
| 465 | 462 | else |
| 466 | − ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | |
| 467 | − GFP_KERNEL); | |
| 468 | − if (!ap_msg.message) | |
| 463 | + ap_msg.msg = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, GFP_KERNEL); | |
| 464 | + if (!ap_msg.msg) | |
| 469 | 465 | return -ENOMEM; |
| 470 | 466 | ap_msg.receive = zcrypt_cex2a_receive; |
| 471 | 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 | 482 | /* Signal pending. */ |
| 487 | 483 | ap_cancel_message(zq->queue, &ap_msg); |
| 488 | 484 | out_free: |
| 489 | − kfree(ap_msg.message); | |
| 485 | + kfree(ap_msg.msg); | |
| 490 | 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 | 503 | ap_init_message(&ap_msg); |
| 508 | 504 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
| 509 | − ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, | |
| 510 | − GFP_KERNEL); | |
| 505 | + ap_msg.msg = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, GFP_KERNEL); | |
| 511 | 506 | else |
| 512 | − ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | |
| 513 | − GFP_KERNEL); | |
| 514 | − if (!ap_msg.message) | |
| 507 | + ap_msg.msg = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, GFP_KERNEL); | |
| 508 | + if (!ap_msg.msg) | |
| 515 | 509 | return -ENOMEM; |
| 516 | 510 | ap_msg.receive = zcrypt_cex2a_receive; |
| 517 | 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 | 526 | /* Signal pending. */ |
| 533 | 527 | ap_cancel_message(zq->queue, &ap_msg); |
| 534 | 528 | out_free: |
| 535 | − kfree(ap_msg.message); | |
| 529 | + kfree(ap_msg.msg); | |
| 536 | 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 | 266 | struct function_and_rules_block fr; |
| 267 | 267 | unsigned short length; |
| 268 | 268 | char text[0]; |
| 269 | − } __packed * msg = ap_msg->message; | |
| 269 | + } __packed * msg = ap_msg->msg; | |
| 270 | 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 | 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 | 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 | 336 | struct function_and_rules_block fr; |
| 337 | 337 | unsigned short length; |
| 338 | 338 | char text[0]; |
| 339 | − } __packed * msg = ap_msg->message; | |
| 339 | + } __packed * msg = ap_msg->msg; | |
| 340 | 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 | 371 | msg->fr = static_pkd_fnr; |
| 372 | 372 | |
| 373 | − ap_msg->length = size; | |
| 373 | + ap_msg->len = size; | |
| 374 | 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 | 400 | struct { |
| 401 | 401 | struct type6_hdr hdr; |
| 402 | 402 | struct CPRBX cprbx; |
| 403 | − } __packed * msg = ap_msg->message; | |
| 403 | + } __packed * msg = ap_msg->msg; | |
| 404 | 404 | |
| 405 | 405 | int rcblen = CEIL4(xcRB->request_control_blk_length); |
| 406 | 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 | 408 | char *function_code; |
| 409 | 409 | |
| 410 | 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 | 412 | return -EINVAL; /* overflow after alignment*/ |
| 413 | 413 | |
| 414 | 414 | /* length checks */ |
| 415 | − ap_msg->length = sizeof(struct type6_hdr) + | |
| 415 | + ap_msg->len = sizeof(struct type6_hdr) + | |
| 416 | 416 | CEIL4(xcRB->request_control_blk_length) + |
| 417 | 417 | xcRB->request_data_length; |
| 418 | − if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE) | |
| 418 | + if (ap_msg->len > MSGTYPE06_MAX_MSG_SIZE) | |
| 419 | 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 | 481 | if (memcmp(function_code, "US", 2) == 0 |
| 482 | 482 | || memcmp(function_code, "AU", 2) == 0) |
| 483 | − ap_msg->special = 1; | |
| 484 | − else | |
| 485 | − ap_msg->special = 0; | |
| 483 | + ap_msg->flags |= AP_MSG_FLAG_SPECIAL; | |
| 486 | 484 | |
| 487 | 485 | /* copy data block */ |
| 488 | 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 | 510 | struct ep11_cprb cprbx; |
| 513 | 511 | unsigned char pld_tag; /* fixed value 0x30 */ |
| 514 | 512 | unsigned char pld_lenfmt; /* payload length format */ |
| 515 | − } __packed * msg = ap_msg->message; | |
| 513 | + } __packed * msg = ap_msg->msg; | |
| 516 | 514 | |
| 517 | 515 | struct pld_hdr { |
| 518 | 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 | 525 | return -EINVAL; /* overflow after alignment*/ |
| 528 | 526 | |
| 529 | 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 | 529 | if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE - |
| 532 | 530 | (sizeof(struct type6_hdr))) |
| 533 | 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 | 568 | /* enable special processing based on the cprbs flags special bit */ |
| 571 | 569 | if (msg->cprbx.flags & 0x20) |
| 572 | − ap_msg->special = 1; | |
| 570 | + ap_msg->flags |= AP_MSG_FLAG_SPECIAL; | |
| 573 | 571 | |
| 574 | 572 | return 0; |
| 575 | 573 | } |
| @@ -639,7 +637,7 @@ static int convert_type86_ica(struct zcrypt_queue *zq, · 63 unmodified lines | ||
| 639 | 637 | 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41, |
| 640 | 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 | 641 | unsigned short service_rc, service_rs; |
| 644 | 642 | unsigned int reply_len, pad_len; |
| 645 | 643 | char *data; |
| @@ -713,8 +711,8 @@ static int convert_type86_xcrb(struct zcrypt_queue *zq, · 67 unmodified lines | ||
| 713 | 711 | struct ap_message *reply, |
| 714 | 712 | struct ica_xcRB *xcRB) |
| 715 | 713 | { |
| 716 | − struct type86_fmt2_msg *msg = reply->message; | |
| 717 | − char *data = reply->message; | |
| 714 | + struct type86_fmt2_msg *msg = reply->msg; | |
| 715 | + char *data = reply->msg; | |
| 718 | 716 | |
| 719 | 717 | /* Copy CPRB to user */ |
| 720 | 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 | 742 | struct ap_message *reply, |
| 745 | 743 | struct ep11_urb *xcRB) |
| 746 | 744 | { |
| 747 | − struct type86_fmt2_msg *msg = reply->message; | |
| 748 | − char *data = reply->message; | |
| 745 | + struct type86_fmt2_msg *msg = reply->msg; | |
| 746 | + char *data = reply->msg; | |
| 749 | 747 | |
| 750 | 748 | if (xcRB->resp_len < msg->fmt2.count1) |
| 751 | 749 | return -EINVAL; |
| @@ -766,8 +764,8 @@ static int convert_type86_rng(struct zcrypt_queue *zq, · 14 unmodified lines | ||
| 766 | 764 | struct type86_hdr hdr; |
| 767 | 765 | struct type86_fmt2_ext fmt2; |
| 768 | 766 | struct CPRBX cprbx; |
| 769 | − } __packed * msg = reply->message; | |
| 770 | − char *data = reply->message; | |
| 767 | + } __packed * msg = reply->msg; | |
| 768 | + char *data = reply->msg; | |
| 771 | 769 | |
| 772 | 770 | if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) |
| 773 | 771 | return -EINVAL; |
| @@ -780,7 +778,7 @@ static int convert_response_ica(struct zcrypt_queue *zq, · 6 unmodified lines | ||
| 780 | 778 | char __user *outputdata, |
| 781 | 779 | unsigned int outputdatalength) |
| 782 | 780 | { |
| 783 | − struct type86x_reply *msg = reply->message; | |
| 781 | + struct type86x_reply *msg = reply->msg; | |
| 784 | 782 | |
| 785 | 783 | switch (msg->hdr.type) { |
| 786 | 784 | case TYPE82_RSP_CODE: |
| @@ -820,7 +818,7 @@ static int convert_response_xcrb(struct zcrypt_queue *zq, · 33 unmodified lines | ||
| 820 | 818 | struct ap_message *reply, |
| 821 | 819 | struct ica_xcRB *xcRB) |
| 822 | 820 | { |
| 823 | − struct type86x_reply *msg = reply->message; | |
| 821 | + struct type86x_reply *msg = reply->msg; | |
| 824 | 822 | |
| 825 | 823 | switch (msg->hdr.type) { |
| 826 | 824 | case TYPE82_RSP_CODE: |
| @@ -853,7 +851,7 @@ static int convert_response_xcrb(struct zcrypt_queue *zq, · 26 unmodified lines | ||
| 853 | 851 | static int convert_response_ep11_xcrb(struct zcrypt_queue *zq, |
| 854 | 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 | 856 | switch (msg->hdr.type) { |
| 859 | 857 | case TYPE82_RSP_CODE: |
| @@ -883,7 +881,7 @@ static int convert_response_rng(struct zcrypt_queue *zq, · 23 unmodified lines | ||
| 883 | 881 | struct ap_message *reply, |
| 884 | 882 | char *data) |
| 885 | 883 | { |
| 886 | − struct type86x_reply *msg = reply->message; | |
| 884 | + struct type86x_reply *msg = reply->msg; | |
| 887 | 885 | |
| 888 | 886 | switch (msg->hdr.type) { |
| 889 | 887 | case TYPE82_RSP_CODE: |
| @@ -928,32 +926,30 @@ static void zcrypt_msgtype6_receive(struct ap_queue *aq, · 38 unmodified lines | ||
| 928 | 926 | struct response_type *resp_type = |
| 929 | 927 | (struct response_type *) msg->private; |
| 930 | 928 | struct type86x_reply *t86r; |
| 931 | − int length; | |
| 929 | + int len; | |
| 932 | 930 | |
| 933 | 931 | /* Copy the reply message to the request message buffer. */ |
| 934 | 932 | if (!reply) |
| 935 | 933 | goto out; /* ap_msg->rc indicates the error */ |
| 936 | − t86r = reply->message; | |
| 934 | + t86r = reply->msg; | |
| 937 | 935 | if (t86r->hdr.type == TYPE86_RSP_CODE && |
| 938 | 936 | t86r->cprbx.cprb_ver_id == 0x02) { |
| 939 | 937 | switch (resp_type->type) { |
| 940 | 938 | case CEXXC_RESPONSE_TYPE_ICA: |
| 941 | − length = sizeof(struct type86x_reply) | |
| 942 | − + t86r->length - 2; | |
| 943 | − length = min(CEXXC_MAX_ICA_RESPONSE_SIZE, length); | |
| 944 | − memcpy(msg->message, reply->message, length); | |
| 939 | + len = sizeof(struct type86x_reply) + t86r->length - 2; | |
| 940 | + len = min_t(int, CEXXC_MAX_ICA_RESPONSE_SIZE, len); | |
| 941 | + memcpy(msg->msg, reply->msg, len); | |
| 945 | 942 | break; |
| 946 | 943 | case CEXXC_RESPONSE_TYPE_XCRB: |
| 947 | − length = t86r->fmt2.offset2 + t86r->fmt2.count2; | |
| 948 | − length = min(MSGTYPE06_MAX_MSG_SIZE, length); | |
| 949 | − memcpy(msg->message, reply->message, length); | |
| 944 | + len = t86r->fmt2.offset2 + t86r->fmt2.count2; | |
| 945 | + len = min_t(int, MSGTYPE06_MAX_MSG_SIZE, len); | |
| 946 | + memcpy(msg->msg, reply->msg, len); | |
| 950 | 947 | break; |
| 951 | 948 | default: |
| 952 | − memcpy(msg->message, &error_reply, | |
| 953 | − sizeof(error_reply)); | |
| 949 | + memcpy(msg->msg, &error_reply, sizeof(error_reply)); | |
| 954 | 950 | } |
| 955 | 951 | } else |
| 956 | − memcpy(msg->message, reply->message, sizeof(error_reply)); | |
| 952 | + memcpy(msg->msg, reply->msg, sizeof(error_reply)); | |
| 957 | 953 | out: |
| 958 | 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 | 973 | struct response_type *resp_type = |
| 978 | 974 | (struct response_type *)msg->private; |
| 979 | 975 | struct type86_ep11_reply *t86r; |
| 980 | − int length; | |
| 976 | + int len; | |
| 981 | 977 | |
| 982 | 978 | /* Copy the reply message to the request message buffer. */ |
| 983 | 979 | if (!reply) |
| 984 | 980 | goto out; /* ap_msg->rc indicates the error */ |
| 985 | − t86r = reply->message; | |
| 981 | + t86r = reply->msg; | |
| 986 | 982 | if (t86r->hdr.type == TYPE86_RSP_CODE && |
| 987 | 983 | t86r->cprbx.cprb_ver_id == 0x04) { |
| 988 | 984 | switch (resp_type->type) { |
| 989 | 985 | case CEXXC_RESPONSE_TYPE_EP11: |
| 990 | − length = t86r->fmt2.offset1 + t86r->fmt2.count1; | |
| 991 | − length = min(MSGTYPE06_MAX_MSG_SIZE, length); | |
| 992 | − memcpy(msg->message, reply->message, length); | |
| 986 | + len = t86r->fmt2.offset1 + t86r->fmt2.count1; | |
| 987 | + len = min_t(int, MSGTYPE06_MAX_MSG_SIZE, len); | |
| 988 | + memcpy(msg->msg, reply->msg, len); | |
| 993 | 989 | break; |
| 994 | 990 | default: |
| 995 | − memcpy(msg->message, &error_reply, sizeof(error_reply)); | |
| 991 | + memcpy(msg->msg, &error_reply, sizeof(error_reply)); | |
| 996 | 992 | } |
| 997 | 993 | } else { |
| 998 | − memcpy(msg->message, reply->message, sizeof(error_reply)); | |
| 994 | + memcpy(msg->msg, reply->msg, sizeof(error_reply)); | |
| 999 | 995 | } |
| 1000 | 996 | out: |
| 1001 | 997 | complete(&(resp_type->work)); |
| @@ -1020,8 +1016,8 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq, · 18 unmodified lines | ||
| 1020 | 1016 | int rc; |
| 1021 | 1017 | |
| 1022 | 1018 | ap_init_message(&ap_msg); |
| 1023 | − ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | |
| 1024 | − if (!ap_msg.message) | |
| 1019 | + ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); | |
| 1020 | + if (!ap_msg.msg) | |
| 1025 | 1021 | return -ENOMEM; |
| 1026 | 1022 | ap_msg.receive = zcrypt_msgtype6_receive; |
| 1027 | 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 | 1039 | /* Signal pending. */ |
| 1044 | 1040 | ap_cancel_message(zq->queue, &ap_msg); |
| 1045 | 1041 | out_free: |
| 1046 | − free_page((unsigned long) ap_msg.message); | |
| 1042 | + free_page((unsigned long) ap_msg.msg); | |
| 1047 | 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 | 1060 | int rc; |
| 1065 | 1061 | |
| 1066 | 1062 | ap_init_message(&ap_msg); |
| 1067 | − ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | |
| 1068 | − if (!ap_msg.message) | |
| 1063 | + ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL); | |
| 1064 | + if (!ap_msg.msg) | |
| 1069 | 1065 | return -ENOMEM; |
| 1070 | 1066 | ap_msg.receive = zcrypt_msgtype6_receive; |
| 1071 | 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 | 1084 | ap_cancel_message(zq->queue, &ap_msg); |
| 1089 | 1085 | } |
| 1090 | 1086 | out_free: |
| 1091 | − free_page((unsigned long) ap_msg.message); | |
| 1087 | + free_page((unsigned long) ap_msg.msg); | |
| 1092 | 1088 | return rc; |
| 1093 | 1089 | } |
| 1094 | 1090 | |
| @@ -1107,8 +1103,8 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, · 12 unmodified lines | ||
| 1107 | 1103 | .type = CEXXC_RESPONSE_TYPE_XCRB, |
| 1108 | 1104 | }; |
| 1109 | 1105 | |
| 1110 | − ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | |
| 1111 | − if (!ap_msg->message) | |
| 1106 | + ap_msg->msg = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | |
| 1107 | + if (!ap_msg->msg) | |
| 1112 | 1108 | return -ENOMEM; |
| 1113 | 1109 | ap_msg->receive = zcrypt_msgtype6_receive; |
| 1114 | 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 | 1158 | .type = CEXXC_RESPONSE_TYPE_EP11, |
| 1163 | 1159 | }; |
| 1164 | 1160 | |
| 1165 | − ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | |
| 1166 | − if (!ap_msg->message) | |
| 1161 | + ap_msg->msg = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | |
| 1162 | + if (!ap_msg->msg) | |
| 1167 | 1163 | return -ENOMEM; |
| 1168 | 1164 | ap_msg->receive = zcrypt_msgtype6_receive_ep11; |
| 1169 | 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 | 1189 | struct ep11_cprb cprbx; |
| 1194 | 1190 | unsigned char pld_tag; /* fixed value 0x30 */ |
| 1195 | 1191 | unsigned char pld_lenfmt; /* payload length format */ |
| 1196 | − } __packed * msg = ap_msg->message; | |
| 1192 | + } __packed * msg = ap_msg->msg; | |
| 1197 | 1193 | struct pld_hdr { |
| 1198 | 1194 | unsigned char func_tag; /* fixed value 0x4 */ |
| 1199 | 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 | 1252 | .type = CEXXC_RESPONSE_TYPE_XCRB, |
| 1257 | 1253 | }; |
| 1258 | 1254 | |
| 1259 | − ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | |
| 1260 | − if (!ap_msg->message) | |
| 1255 | + ap_msg->msg = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | |
| 1256 | + if (!ap_msg->msg) | |
| 1261 | 1257 | return -ENOMEM; |
| 1262 | 1258 | ap_msg->receive = zcrypt_msgtype6_receive; |
| 1263 | 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 | 1286 | char rule[8]; |
| 1291 | 1287 | short int verb_length; |
| 1292 | 1288 | short int key_length; |
| 1293 | − } __packed * msg = ap_msg->message; | |
| 1289 | + } __packed * msg = ap_msg->msg; | |
| 1294 | 1290 | struct response_type *rtype = (struct response_type *)(ap_msg->private); |
| 1295 | 1291 | int rc; |
| 1296 | 1292 | |
| @@ -127,7 +127,7 @@ static inline void rng_type6CPRB_msgX(struct ap_message *ap_msg, · 126 unmodified lines | ||
| 127 | 127 | char rule[8]; |
| 128 | 128 | short int verb_length; |
| 129 | 129 | short int key_length; |
| 130 | − } __packed * msg = ap_msg->message; | |
| 130 | + } __packed * msg = ap_msg->msg; | |
| 131 | 131 | static struct type6_hdr static_type6_hdrX = { |
| 132 | 132 | .type = 0x06, |
| 133 | 133 | .offset1 = 0x00000058, |
| @@ -154,7 +154,7 @@ static inline void rng_type6CPRB_msgX(struct ap_message *ap_msg, · 20 unmodified lines | ||
| 154 | 154 | memcpy(msg->rule, "RANDOM ", 8); |
| 155 | 155 | msg->verb_length = 0x02; |
| 156 | 156 | msg->key_length = 0x02; |
| 157 | − ap_msg->length = sizeof(*msg); | |
| 157 | + ap_msg->len = sizeof(*msg); | |
| 158 | 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 | 107 | zq = kzalloc(sizeof(struct zcrypt_queue), GFP_KERNEL); |
| 108 | 108 | if (!zq) |
| 109 | 109 | return NULL; |
| 110 | − zq->reply.message = kmalloc(max_response_size, GFP_KERNEL); | |
| 111 | − if (!zq->reply.message) | |
| 110 | + zq->reply.msg = kmalloc(max_response_size, GFP_KERNEL); | |
| 111 | + if (!zq->reply.msg) | |
| 112 | 112 | goto out_free; |
| 113 | − zq->reply.length = max_response_size; | |
| 113 | + zq->reply.len = max_response_size; | |
| 114 | 114 | INIT_LIST_HEAD(&zq->list); |
| 115 | 115 | kref_init(&zq->refcount); |
| 116 | 116 | return zq; |
| @@ -123,7 +123,7 @@ EXPORT_SYMBOL(zcrypt_queue_alloc); · 6 unmodified lines | ||
| 123 | 123 | |
| 124 | 124 | void zcrypt_queue_free(struct zcrypt_queue *zq) |
| 125 | 125 | { |
| 126 | − kfree(zq->reply.message); | |
| 126 | + kfree(zq->reply.msg); | |
| 127 | 127 | kfree(zq); |
| 128 | 128 | } |
| 129 | 129 | EXPORT_SYMBOL(zcrypt_queue_free); |
| @@ -77,16 +77,12 @@ struct memblock_type { · 76 unmodified lines | ||
| 77 | 77 | * @current_limit: physical address of the current allocation limit |
| 78 | 78 | * @memory: usable memory regions |
| 79 | 79 | * @reserved: reserved memory regions |
| 80 | − * @physmem: all physical memory | |
| 81 | 80 | */ |
| 82 | 81 | struct memblock { |
| 83 | 82 | bool bottom_up; /* is bottom up direction? */ |
| 84 | 83 | phys_addr_t current_limit; |
| 85 | 84 | struct memblock_type memory; |
| 86 | 85 | struct memblock_type reserved; |
| 87 | −#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP | |
| 88 | − struct memblock_type physmem; | |
| 89 | −#endif | |
| 90 | 86 | }; |
| 91 | 87 | |
| 92 | 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 | 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 | 169 | * for_each_mem_range - iterate through memblock areas from type_a and not |
| 150 | 170 | * included in type_b. Or just type_a if type_b is NULL. |
| @@ -44,19 +44,20 @@ · 43 unmodified lines | ||
| 44 | 44 | * in the system, for instance when the memory is restricted with |
| 45 | 45 | * ``mem=`` command line parameter |
| 46 | 46 | * * ``reserved`` - describes the regions that were allocated |
| 47 | − * * ``physmap`` - describes the actual physical memory regardless of | |
| 48 | − * the possible restrictions; the ``physmap`` type is only available | |
| 49 | − * on some architectures. | |
| 47 | + * * ``physmem`` - describes the actual physical memory available during | |
| 48 | + * boot regardless of the possible restrictions and memory hot(un)plug; | |
| 49 | + * the ``physmem`` type is only available on some architectures. | |
| 50 | 50 | * |
| 51 | 51 | * Each region is represented by :c:type:`struct memblock_region` that |
| 52 | 52 | * defines the region extents, its attributes and NUMA node id on NUMA |
| 53 | 53 | * systems. Every memory type is described by the :c:type:`struct |
| 54 | 54 | * memblock_type` which contains an array of memory regions along with |
| 55 | − * the allocator metadata. The memory types are nicely wrapped with | |
| 56 | − * :c:type:`struct memblock`. This structure is statically initialzed | |
| 57 | − * at build time. The region arrays for the "memory" and "reserved" | |
| 58 | − * types are initially sized to %INIT_MEMBLOCK_REGIONS and for the | |
| 59 | − * "physmap" type to %INIT_PHYSMEM_REGIONS. | |
| 55 | + * the allocator metadata. The "memory" and "reserved" types are nicely | |
| 56 | + * wrapped with :c:type:`struct memblock`. This structure is statically | |
| 57 | + * initialized at build time. The region arrays are initially sized to | |
| 58 | + * %INIT_MEMBLOCK_REGIONS for "memory" and %INIT_MEMBLOCK_RESERVED_REGIONS | |
| 59 | + * for "reserved". The region array for "physmem" is initially sized to | |
| 60 | + * %INIT_PHYSMEM_REGIONS. | |
| 60 | 61 | * The memblock_allow_resize() enables automatic resizing of the region |
| 61 | 62 | * arrays during addition of new regions. This feature should be used |
| 62 | 63 | * with care so that memory allocated for the region array will not |
| @@ -87,8 +88,8 @@ · 24 unmodified lines | ||
| 87 | 88 | * function frees all the memory to the buddy page allocator. |
| 88 | 89 | * |
| 89 | 90 | * Unless an architecture enables %CONFIG_ARCH_KEEP_MEMBLOCK, the |
| 90 | − * memblock data structures will be discarded after the system | |
| 91 | − * initialization completes. | |
| 91 | + * memblock data structures (except "physmem") will be discarded after the | |
| 92 | + * system initialization completes. | |
| 92 | 93 | */ |
| 93 | 94 | |
| 94 | 95 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
| @@ -104,7 +105,7 @@ unsigned long long max_possible_pfn; · 9 unmodified lines | ||
| 104 | 105 | static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock; |
| 105 | 106 | static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock; |
| 106 | 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 | 109 | #endif |
| 109 | 110 | |
| 110 | 111 | struct memblock memblock __initdata_memblock = { |
| @@ -118,17 +119,19 @@ struct memblock memblock __initdata_memblock = { · 7 unmodified lines | ||
| 118 | 119 | .reserved.max = INIT_MEMBLOCK_RESERVED_REGIONS, |
| 119 | 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 | 122 | .bottom_up = false, |
| 129 | 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 | 135 | int memblock_debug __initdata_memblock; |
| 133 | 136 | static bool system_has_some_mirror __initdata_memblock = false; |
| 134 | 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 | 841 | memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, |
| 839 | 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 | 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 | 1022 | * As both region arrays are sorted, the function advances the two indices |
| 1020 | 1023 | * in lockstep and returns each intersection. |
| 1021 | 1024 | */ |
| 1022 | −void __init_memblock __next_mem_range(u64 *idx, int nid, | |
| 1023 | − enum memblock_flags flags, | |
| 1024 | − struct memblock_type *type_a, | |
| 1025 | − struct memblock_type *type_b, | |
| 1026 | − phys_addr_t *out_start, | |
| 1027 | − phys_addr_t *out_end, int *out_nid) | |
| 1025 | +void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, | |
| 1026 | + struct memblock_type *type_a, | |
| 1027 | + struct memblock_type *type_b, phys_addr_t *out_start, | |
| 1028 | + phys_addr_t *out_end, int *out_nid) | |
| 1028 | 1029 | { |
| 1029 | 1030 | int idx_a = *idx & 0xffffffff; |
| 1030 | 1031 | int idx_b = *idx >> 32; |
| @@ -1924,7 +1925,7 @@ void __init_memblock __memblock_dump_all(void) · 893 unmodified lines | ||
| 1924 | 1925 | memblock_dump(&memblock.memory); |
| 1925 | 1926 | memblock_dump(&memblock.reserved); |
| 1926 | 1927 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP |
| 1927 | − memblock_dump(&memblock.physmem); | |
| 1928 | + memblock_dump(&physmem); | |
| 1928 | 1929 | #endif |
| 1929 | 1930 | } |
| 1930 | 1931 | |
| @@ -2064,8 +2065,8 @@ static int __init memblock_init_debugfs(void) · 133 unmodified lines | ||
| 2064 | 2065 | debugfs_create_file("reserved", 0444, root, |
| 2065 | 2066 | &memblock.reserved, &memblock_debug_fops); |
| 2066 | 2067 | #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP |
| 2067 | − debugfs_create_file("physmem", 0444, root, | |
| 2068 | − &memblock.physmem, &memblock_debug_fops); | |
| 2068 | + debugfs_create_file("physmem", 0444, root, &physmem, | |
| 2069 | + &memblock_debug_fops); | |
| 2069 | 2070 | #endif |
| 2070 | 2071 | |
| 2071 | 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 | 297 | static int do_file(char const *const fname, void *addr) |
| 259 | 298 | { |
| 260 | 299 | int rc = -1; |
| @@ -297,6 +336,8 @@ static int do_file(char const *const fname, void *addr) · 36 unmodified lines | ||
| 297 | 336 | custom_sort = x86_sort_relative_table; |
| 298 | 337 | break; |
| 299 | 338 | case EM_S390: |
| 339 | + custom_sort = s390_sort_relative_table; | |
| 340 | + break; | |
| 300 | 341 | case EM_AARCH64: |
| 301 | 342 | case EM_PARISC: |
| 302 | 343 | case EM_PPC: |