This is the second variant to reduce the size of the alternative tables. Basically it halves the size by reducing length, condition and replacement fields. bloat-o-meter shows a reduction of -0.01% by this change: Total: Before=10254498, After=10253654, chg -0.01% Since this patch introduces more changes without benefit, I won't apply it for now, but want it to show up in patchwork. Signed-off-by: Helge Deller <deller@xxxxxx> diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h index 0ec54f43d6d2..1705abd97f5f 100644 --- a/arch/parisc/include/asm/alternative.h +++ b/arch/parisc/include/asm/alternative.h @@ -10,7 +10,9 @@ #define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */ #define ALT_COND_RUN_ON_QEMU 0x20 /* if running on QEMU */ -#define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */ +#define ALTCODE_PxTLB 0x01 /* add local flag to pdtlb & pitlb */ +#define ALTCODE_NOP 0x02 /* insert nops */ + #define INSN_NOP 0x08000240 /* nop */ #ifndef __ASSEMBLY__ @@ -22,10 +24,10 @@ struct alt_instr { s32 orig_offset; /* offset to original instructions */ - s32 len; /* end of original instructions */ - u32 cond; /* see ALT_COND_XXX */ - u32 replacement; /* replacement instruction or code */ -}; + u16 len; /* number of instructions */ + u8 cond; /* see ALT_COND_XXX condition */ + u8 replacement; /* see ALTCODE_XXX replacement instruction */ +} __packed; void set_kernel_text_rw(int enable_read_write); void apply_alternatives_all(void); @@ -34,9 +36,11 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end, /* Alternative SMP implementation. */ #define ALTERNATIVE(cond, replacement) "!0:" \ - ".section .altinstructions, \"aw\" !" \ - ".word (0b-4-.), 1, " __stringify(cond) "," \ - __stringify(replacement) " !" \ + ".section .altinstructions, \"aw\" !" \ + ".word (0b-4) - . !" \ + ".hword 1 !" \ + ".byte " __stringify(cond) "!" \ + ".byte " __stringify(replacement) "!" \ ".previous" #else @@ -44,15 +48,9 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end, /* to replace one single instructions by a new instruction */ #define ALTERNATIVE(from, to, cond, replacement)\ .section .altinstructions, "aw" ! \ - .word (from - .), (to - from)/4 ! \ - .word cond, replacement ! \ - .previous - -/* to replace multiple instructions by new code */ -#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\ - .section .altinstructions, "aw" ! \ - .word (from - .), -num_instructions ! \ - .word cond, (new_instr_ptr - .) ! \ + .word from - . ! \ + .hword (to - from)/4 ! \ + .byte cond, replacement ! \ .previous #endif /* __ASSEMBLY__ */ diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h index c705decf2bed..f99bb8feff78 100644 --- a/arch/parisc/include/asm/barrier.h +++ b/arch/parisc/include/asm/barrier.h @@ -9,7 +9,7 @@ /* The synchronize caches instruction executes as a nop on systems in which all memory references are performed in order. */ #define synchronize_caches() asm volatile("sync" \ - ALTERNATIVE(ALT_COND_NO_SMP, INSN_NOP) \ + ALTERNATIVE(ALT_COND_NO_SMP, ALTCODE_NOP) \ : : : "memory") #if defined(CONFIG_SMP) diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index e23d06b51a20..41fa03e7efa1 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -40,20 +40,20 @@ extern struct pdc_cache_info cache_info; void parisc_setup_cache_timing(void); #define pdtlb(sr, addr) asm volatile("pdtlb 0(%%sr%0,%1)" \ - ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ + ALTERNATIVE(ALT_COND_NO_SMP, ALTCODE_PxTLB) \ : : "i"(sr), "r" (addr) : "memory") #define pitlb(sr, addr) asm volatile("pitlb 0(%%sr%0,%1)" \ - ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ - ALTERNATIVE(ALT_COND_NO_SPLIT_TLB, INSN_NOP) \ + ALTERNATIVE(ALT_COND_NO_SMP, ALTCODE_PxTLB) \ + ALTERNATIVE(ALT_COND_NO_SPLIT_TLB, ALTCODE_NOP) \ : : "i"(sr), "r" (addr) : "memory") #define asm_io_fdc(addr) asm volatile("fdc %%r0(%0)" \ - ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ - ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) \ + ALTERNATIVE(ALT_COND_NO_DCACHE, ALTCODE_NOP) \ + ALTERNATIVE(ALT_COND_NO_IOC_FDC, ALTCODE_NOP) \ : : "r" (addr) : "memory") #define asm_io_sync() asm volatile("sync" \ - ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ - ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :::"memory") + ALTERNATIVE(ALT_COND_NO_DCACHE, ALTCODE_NOP) \ + ALTERNATIVE(ALT_COND_NO_IOC_FDC, ALTCODE_NOP) :::"memory") #define asm_syncdma() asm volatile("syncdma" :::"memory") #endif /* ! __ASSEMBLY__ */ diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c index daa1e9047275..0c455ae13150 100644 --- a/arch/parisc/kernel/alternative.c +++ b/arch/parisc/kernel/alternative.c @@ -26,7 +26,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start, struct alt_instr *entry; int index = 0, applied = 0; int num_cpus = num_online_cpus(); - u32 cond_check; + u8 cond_check; cond_check = ALT_COND_ALWAYS | ((num_cpus == 1) ? ALT_COND_NO_SMP : 0) | @@ -45,15 +45,19 @@ void __init_or_module apply_alternatives(struct alt_instr *start, for (entry = start; entry < end; entry++, index++) { - u32 *from, cond, replacement; - s32 len; + u32 *from, replacement; + u8 cond; + u16 len; from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset); len = entry->len; cond = entry->cond; replacement = entry->replacement; - WARN_ON(!cond); + if (WARN_ON(!cond || !len)) + continue; + if (WARN_ON(replacement != ALTCODE_PxTLB && replacement != ALTCODE_NOP)) + continue; if ((cond & ALT_COND_ALWAYS) == 0 && no_alternatives) continue; @@ -66,7 +70,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start, continue; /* Want to replace pdtlb by a pdtlb,l instruction? */ - if (replacement == INSN_PxTLB) { + if (replacement == ALTCODE_PxTLB) { replacement = *from; if (boot_cpu_data.cpu_type >= pcxu) /* >= pa2.0 ? */ replacement |= (1 << 10); /* set el bit */ @@ -76,21 +80,20 @@ void __init_or_module apply_alternatives(struct alt_instr *start, * Replace instruction with NOPs? * For long distance insert a branch instruction instead. */ - if (replacement == INSN_NOP && len > 1) - replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ + if (replacement == ALTCODE_NOP) { + if (len > 1) + replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ + else + replacement = INSN_NOP; + len = 1; + } pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n", index, cond, len, replacement, from, from); - if (len < 0) { - /* Replace multiple instruction by new code */ - u32 *source; - len = -len; - source = (u32 *)((ulong)&entry->replacement + entry->replacement); - memcpy(from, source, 4 * len); - } else { + while (len--) { /* Replace by one instruction */ - *from = replacement; + *from++ = replacement; } applied++; } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index df8102fb435f..32167b276c26 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -407,7 +407,7 @@ bb,<,n \pte,_PAGE_PRESENT_BIT,3f b \fault stw \spc,0(\tmp) -99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) +99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, ALTCODE_NOP) #endif 2: LDREG 0(\ptp),\pte bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault @@ -424,7 +424,7 @@ #ifdef CONFIG_TLB_PTLOCK 98: or,COND(=) %r0,\spc,%r0 stw,ma \spc,0(\tmp) -99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) +99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, ALTCODE_NOP) #endif .endm @@ -433,7 +433,7 @@ #ifdef CONFIG_TLB_PTLOCK 98: get_ptl \tmp ptl_unlock0 \spc,\tmp -99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) +99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, ALTCODE_NOP) #endif .endm diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 9a0018f1f42c..038d876b0a92 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -103,7 +103,7 @@ fitonemiddle: /* Loop if LOOP = 1 */ add %r21, %r20, %r20 /* increment space */ fitdone: - ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, INSN_NOP) + ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, ALTCODE_NOP) /* Flush Data Tlb */ @@ -172,17 +172,16 @@ fdtdone: rfi nop -2: bv %r0(%r2) - nop + bv,n %r0(%r2) /* * When running in qemu, drop whole flush_tlb_all_local function and * replace by one pdtlbe instruction, for which QEMU will drop all * local TLB entries. */ -3: pdtlbe %r0(%sr1,%r0) - bv,n %r0(%r2) - ALTERNATIVE_CODE(flush_tlb_all_local, 2, ALT_COND_RUN_ON_QEMU, 3b) +3: ALTERNATIVE(flush_tlb_all_local, 3b, ALT_COND_RUN_ON_QEMU, ALTCODE_NOP) + bv %r0(%r2) + pdtlbe %r0(%sr1,%r0) ENDPROC_CFI(flush_tlb_all_local) .import cache_info,data @@ -241,7 +240,7 @@ fioneloop2: fisync: sync mtsm %r22 /* restore I-bit */ -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, ALTCODE_NOP) bv %r0(%r2) nop ENDPROC_CFI(flush_instruction_cache_local) @@ -302,7 +301,7 @@ fdoneloop2: fdsync: sync mtsm %r22 /* restore I-bit */ -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) bv %r0(%r2) nop ENDPROC_CFI(flush_data_cache_local) @@ -545,8 +544,8 @@ ENTRY_CFI(copy_user_page_asm) #else 0: pdtlb %r0(%r28) 1: pdtlb %r0(%r29) - ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) - ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB) + ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) + ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) #endif #ifdef CONFIG_64BIT @@ -674,7 +673,7 @@ ENTRY_CFI(clear_user_page_asm) pdtlb,l %r0(%r28) #else 0: pdtlb %r0(%r28) - ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) + ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) #endif #ifdef CONFIG_64BIT @@ -740,7 +739,7 @@ ENTRY_CFI(flush_dcache_page_asm) pdtlb,l %r0(%r28) #else 0: pdtlb %r0(%r28) - ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) + ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) #endif 88: ldil L%dcache_stride, %r1 @@ -772,7 +771,7 @@ ENTRY_CFI(flush_dcache_page_asm) cmpb,COND(>>) %r25, %r28, 1b /* predict taken */ fdc,m r31(%r28) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -789,7 +788,7 @@ ENTRY_CFI(purge_dcache_page_asm) pdtlb,l %r0(%r28) #else 0: pdtlb %r0(%r28) - ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) + ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) #endif 88: ldil L%dcache_stride, %r1 @@ -821,7 +820,7 @@ ENTRY_CFI(purge_dcache_page_asm) cmpb,COND(>>) %r25, %r28, 1b /* predict taken */ pdc,m r31(%r28) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -840,13 +839,13 @@ ENTRY_CFI(flush_icache_page_asm) #ifdef CONFIG_PA20 pdtlb,l %r0(%r28) 1: pitlb,l %r0(%sr4,%r28) - ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP) + ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, ALTCODE_NOP) #else 0: pdtlb %r0(%r28) 1: pitlb %r0(%sr4,%r28) - ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) - ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB) - ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP) + ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) + ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, ALTCODE_PxTLB) + ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, ALTCODE_NOP) #endif 88: ldil L%icache_stride, %r1 @@ -880,7 +879,7 @@ ENTRY_CFI(flush_icache_page_asm) cmpb,COND(>>) %r25, %r28, 1b /* predict taken */ fic,m %r31(%sr4,%r28) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -916,7 +915,7 @@ ENTRY_CFI(flush_kernel_dcache_page_asm) cmpb,COND(>>) %r25, %r26, 1b /* predict taken */ fdc,m %r23(%r26) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -952,7 +951,7 @@ ENTRY_CFI(purge_kernel_dcache_page_asm) cmpb,COND(>>) %r25, %r26, 1b /* predict taken */ pdc,m %r23(%r26) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -993,7 +992,7 @@ ENTRY_CFI(flush_user_dcache_range_asm) 2: cmpb,COND(>>),n %r25, %r26, 2b fdc,m %r23(%sr3, %r26) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -1035,7 +1034,7 @@ ENTRY_CFI(flush_kernel_dcache_range_asm) fdc,m %r23(%r26) sync -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) bv %r0(%r2) nop ENDPROC_CFI(flush_kernel_dcache_range_asm) @@ -1076,7 +1075,7 @@ ENTRY_CFI(purge_kernel_dcache_range_asm) pdc,m %r23(%r26) sync -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, ALTCODE_NOP) bv %r0(%r2) nop ENDPROC_CFI(purge_kernel_dcache_range_asm) @@ -1116,7 +1115,7 @@ ENTRY_CFI(flush_user_icache_range_asm) 2: cmpb,COND(>>),n %r25, %r26, 2b fic,m %r23(%sr3, %r26) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -1153,7 +1152,7 @@ ENTRY_CFI(flush_kernel_icache_page) cmpb,COND(>>) %r25, %r26, 1b /* predict taken */ fic,m %r23(%sr4, %r26) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, ALTCODE_NOP) sync bv %r0(%r2) nop @@ -1194,7 +1193,7 @@ ENTRY_CFI(flush_kernel_icache_range_asm) 2: cmpb,COND(>>),n %r25, %r26, 2b /* predict taken */ fic,m %r23(%sr4, %r26) -89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, INSN_NOP) +89: ALTERNATIVE(88b, 89b, ALT_COND_NO_ICACHE, ALTCODE_NOP) sync bv %r0(%r2) nop