Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'arc-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc

Pull ARC updates from Vineet Gupta:

- long due rewrite of do_page_fault

- refactoring of entry/exit code to utilize the double load/store
instructions

- hsdk platform updates

* tag 'arc-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
ARC: [plat-hsdk]: Enable AXI DW DMAC in defconfig
ARC: [plat-hsdk]: enable DW SPI controller
ARC: hide unused function unw_hdr_alloc
ARC: [haps] Add Virtio support
ARCv2: entry: simplify return to Delay Slot via interrupt
ARC: entry: EV_Trap expects r10 (vs. r9) to have exception cause
ARCv2: entry: rewrite to enable use of double load/stores LDD/STD
ARCv2: entry: avoid a branch
ARCv2: entry: push out the Z flag unclobber from common EXCEPTION_PROLOGUE
ARCv2: entry: comments about hardware auto-save on taken interrupts
ARC: mm: do_page_fault refactor #8: release mmap_sem sooner
ARC: mm: do_page_fault refactor #7: fold the various error handling
ARC: mm: do_page_fault refactor #6: error handlers to use same pattern
ARC: mm: do_page_fault refactor #5: scoot no_context to end
ARC: mm: do_page_fault refactor #4: consolidate retry related logic
ARC: mm: do_page_fault refactor #3: tidyup vma access permission code
ARC: mm: do_page_fault refactor #2: remove short lived variable
ARC: mm: do_page_fault refactor #1: remove label @good_area

+386 -349
+30
arch/arc/boot/dts/haps_hs.dts
··· 62 62 #interrupt-cells = <1>; 63 63 interrupts = <20>; 64 64 }; 65 + 66 + virtio0: virtio@f0100000 { 67 + compatible = "virtio,mmio"; 68 + reg = <0xf0100000 0x2000>; 69 + interrupts = <31>; 70 + }; 71 + 72 + virtio1: virtio@f0102000 { 73 + compatible = "virtio,mmio"; 74 + reg = <0xf0102000 0x2000>; 75 + interrupts = <32>; 76 + }; 77 + 78 + virtio2: virtio@f0104000 { 79 + compatible = "virtio,mmio"; 80 + reg = <0xf0104000 0x2000>; 81 + interrupts = <33>; 82 + }; 83 + 84 + virtio3: virtio@f0106000 { 85 + compatible = "virtio,mmio"; 86 + reg = <0xf0106000 0x2000>; 87 + interrupts = <34>; 88 + }; 89 + 90 + virtio4: virtio@f0108000 { 91 + compatible = "virtio,mmio"; 92 + reg = <0xf0108000 0x2000>; 93 + interrupts = <35>; 94 + }; 65 95 }; 66 96 };
+14
arch/arc/boot/dts/hsdk.dts
··· 8 8 */ 9 9 /dts-v1/; 10 10 11 + #include <dt-bindings/gpio/gpio.h> 11 12 #include <dt-bindings/reset/snps,hsdk-reset.h> 12 13 13 14 / { ··· 251 250 interrupts = <12>; 252 251 bus-width = <4>; 253 252 dma-coherent; 253 + }; 254 + 255 + spi0: spi@20000 { 256 + compatible = "snps,dw-apb-ssi"; 257 + reg = <0x20000 0x100>; 258 + #address-cells = <1>; 259 + #size-cells = <0>; 260 + interrupts = <16>; 261 + num-cs = <2>; 262 + reg-io-width = <4>; 263 + clocks = <&input_clk>; 264 + cs-gpios = <&creg_gpio 0 GPIO_ACTIVE_LOW>, 265 + <&creg_gpio 1 GPIO_ACTIVE_LOW>; 254 266 }; 255 267 256 268 creg_gpio: gpio@14b0 {
+4 -1
arch/arc/configs/haps_hs_defconfig
··· 35 35 # CONFIG_IPV6 is not set 36 36 # CONFIG_WIRELESS is not set 37 37 CONFIG_DEVTMPFS=y 38 + CONFIG_DEVTMPFS_MOUNT=y 38 39 # CONFIG_STANDALONE is not set 39 40 # CONFIG_PREVENT_FIRMWARE_BUILD is not set 40 - # CONFIG_BLK_DEV is not set 41 + CONFIG_VIRTIO_BLK=y 41 42 CONFIG_NETDEVICES=y 43 + CONFIG_VIRTIO_NET=y 42 44 # CONFIG_NET_VENDOR_ARC is not set 43 45 # CONFIG_NET_VENDOR_BROADCOM is not set 44 46 # CONFIG_NET_VENDOR_INTEL is not set ··· 70 68 CONFIG_LOGO=y 71 69 # CONFIG_HID is not set 72 70 # CONFIG_USB_SUPPORT is not set 71 + CONFIG_VIRTIO_MMIO=y 73 72 # CONFIG_IOMMU_SUPPORT is not set 74 73 CONFIG_EXT2_FS=y 75 74 CONFIG_EXT2_FS_XATTR=y
+5
arch/arc/configs/hsdk_defconfig
··· 46 46 CONFIG_SERIAL_8250_DW=y 47 47 CONFIG_SERIAL_OF_PLATFORM=y 48 48 # CONFIG_HW_RANDOM is not set 49 + CONFIG_SPI=y 50 + CONFIG_SPI_DESIGNWARE=y 51 + CONFIG_SPI_DW_MMIO=y 49 52 CONFIG_GPIOLIB=y 50 53 CONFIG_GPIO_SYSFS=y 51 54 CONFIG_GPIO_DWAPB=y ··· 69 66 CONFIG_MMC_SDHCI=y 70 67 CONFIG_MMC_SDHCI_PLTFM=y 71 68 CONFIG_MMC_DW=y 69 + CONFIG_DMADEVICES=y 70 + CONFIG_DW_AXI_DMAC=y 72 71 CONFIG_EXT3_FS=y 73 72 CONFIG_VFAT_FS=y 74 73 CONFIG_TMPFS=y
+196 -177
arch/arc/include/asm/entry-arcv2.h
··· 7 7 #include <asm/irqflags-arcv2.h> 8 8 #include <asm/thread_info.h> /* For THREAD_SIZE */ 9 9 10 - /*------------------------------------------------------------------------*/ 11 - .macro INTERRUPT_PROLOGUE called_from 10 + /* 11 + * Interrupt/Exception stack layout (pt_regs) for ARCv2 12 + * (End of struct aligned to end of page [unless nested]) 13 + * 14 + * INTERRUPT EXCEPTION 15 + * 16 + * manual --------------------- manual 17 + * | orig_r0 | 18 + * | event/ECR | 19 + * | bta | 20 + * | user_r25 | 21 + * | gp | 22 + * | fp | 23 + * | sp | 24 + * | r12 | 25 + * | r30 | 26 + * | r58 | 27 + * | r59 | 28 + * hw autosave --------------------- 29 + * optional | r0 | 30 + * | r1 | 31 + * ~ ~ 32 + * | r9 | 33 + * | r10 | 34 + * | r11 | 35 + * | blink | 36 + * | lpe | 37 + * | lps | 38 + * | lpc | 39 + * | ei base | 40 + * | ldi base | 41 + * | jli base | 42 + * --------------------- 43 + * hw autosave | pc / eret | 44 + * mandatory | stat32 / erstatus | 45 + * --------------------- 46 + */ 12 47 13 - ; Before jumping to Interrupt Vector, hardware micro-ops did following: 48 + /*------------------------------------------------------------------------*/ 49 + .macro INTERRUPT_PROLOGUE 50 + 51 + ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following: 14 52 ; 1. SP auto-switched to kernel mode stack 15 - ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0) 16 - ; 3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32 53 + ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0) 54 + ; 3. Auto save: (mandatory) Push PC and STAT32 on stack 55 + ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE 56 + ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI 17 57 ; 18 - ; Now manually save: r12, sp, fp, gp, r25 58 + ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair 19 59 20 60 #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 21 - .ifnc \called_from, exception 22 - st.as r9, [sp, -10] ; save r9 in it's final stack slot 23 - sub sp, sp, 12 ; skip JLI, LDI, EI 61 + ; carve pt_regs on stack (case #3), PC/STAT32 already on stack 62 + sub sp, sp, SZ_PT_REGS - 8 24 63 25 - PUSH lp_count 26 - PUSHAX lp_start 27 - PUSHAX lp_end 28 - PUSH blink 29 - 30 - PUSH r11 31 - PUSH r10 32 - 33 - sub sp, sp, 4 ; skip r9 34 - 35 - PUSH r8 36 - PUSH r7 37 - PUSH r6 38 - PUSH r5 39 - PUSH r4 40 - PUSH r3 41 - PUSH r2 42 - PUSH r1 43 - PUSH r0 44 - .endif 64 + __SAVE_REGFILE_HARD 65 + #else 66 + ; carve pt_regs on stack (case #4), which grew partially already 67 + sub sp, sp, PT_r0 45 68 #endif 46 69 47 - #ifdef CONFIG_ARC_HAS_ACCL_REGS 48 - PUSH r59 49 - PUSH r58 50 - #endif 70 + __SAVE_REGFILE_SOFT 71 + .endm 51 72 52 - PUSH r30 53 - PUSH r12 73 + /*------------------------------------------------------------------------*/ 74 + .macro EXCEPTION_PROLOGUE 75 + 76 + ; (A) Before jumping to Exception Vector, hardware micro-ops did following: 77 + ; 1. SP auto-switched to kernel mode stack 78 + ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0) 79 + ; 80 + ; (B) Manually save the complete reg file below 81 + 82 + sub sp, sp, SZ_PT_REGS ; carve pt_regs 83 + 84 + ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first 85 + 86 + __SAVE_REGFILE_HARD 87 + __SAVE_REGFILE_SOFT 88 + 89 + st r0, [sp] ; orig_r0 90 + 91 + lr r10, [eret] 92 + lr r11, [erstatus] 93 + ST2 r10, r11, PT_ret 94 + 95 + lr r10, [ecr] 96 + lr r11, [erbta] 97 + ST2 r10, r11, PT_event 98 + 99 + ; OUTPUT: r10 has ECR expected by EV_Trap 100 + .endm 101 + 102 + /*------------------------------------------------------------------------ 103 + * This macro saves the registers manually which would normally be autosaved 104 + * by hardware on taken interrupts. It is used by 105 + * - exception handlers (which don't have autosave) 106 + * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE 107 + */ 108 + .macro __SAVE_REGFILE_HARD 109 + 110 + ST2 r0, r1, PT_r0 111 + ST2 r2, r3, PT_r2 112 + ST2 r4, r5, PT_r4 113 + ST2 r6, r7, PT_r6 114 + ST2 r8, r9, PT_r8 115 + ST2 r10, r11, PT_r10 116 + 117 + st blink, [sp, PT_blink] 118 + 119 + lr r10, [lp_end] 120 + lr r11, [lp_start] 121 + ST2 r10, r11, PT_lpe 122 + 123 + st lp_count, [sp, PT_lpc] 124 + 125 + ; skip JLI, LDI, EI for now 126 + .endm 127 + 128 + /*------------------------------------------------------------------------ 129 + * This macros saves a bunch of other registers which can't be autosaved for 130 + * various reasons: 131 + * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11 132 + * - r30: free reg, used by gcc as scratch 133 + * - ACCL/ACCH pair when they exist 134 + */ 135 + .macro __SAVE_REGFILE_SOFT 136 + 137 + ST2 gp, fp, PT_r26 ; gp (r26), fp (r27) 138 + 139 + st r12, [sp, PT_sp + 4] 140 + st r30, [sp, PT_sp + 8] 54 141 55 142 ; Saving pt_regs->sp correctly requires some extra work due to the way 56 143 ; Auto stack switch works 57 144 ; - U mode: retrieve it from AUX_USER_SP 58 145 ; - K mode: add the offset from current SP where H/w starts auto push 59 146 ; 60 - ; Utilize the fact that Z bit is set if Intr taken in U mode 61 - mov.nz r9, sp 62 - add.nz r9, r9, SZ_PT_REGS - PT_sp - 4 63 - bnz 1f 147 + ; 1. Utilize the fact that Z bit is set if Intr taken in U mode 148 + ; 2. Upon entry SP is always saved (for any inspection, unwinding etc), 149 + ; but on return, restored only if U mode 64 150 65 - lr r9, [AUX_USER_SP] 66 - 1: 67 - PUSH r9 ; SP 151 + lr r10, [AUX_USER_SP] ; U mode SP 68 152 69 - PUSH fp 70 - PUSH gp 153 + ; ISA requires ADD.nz to have same dest and src reg operands 154 + mov.nz r10, sp 155 + add.nz r10, r10, SZ_PT_REGS ; K mode SP 156 + 157 + st r10, [sp, PT_sp] ; SP (pt_regs->sp) 71 158 72 159 #ifdef CONFIG_ARC_CURR_IN_REG 73 - PUSH r25 ; user_r25 160 + st r25, [sp, PT_user_r25] 74 161 GET_CURR_TASK_ON_CPU r25 75 - #else 76 - sub sp, sp, 4 77 162 #endif 78 - 79 - .ifnc \called_from, exception 80 - sub sp, sp, 12 ; BTA/ECR/orig_r0 placeholder per pt_regs 81 - .endif 82 - 83 - .endm 84 - 85 - /*------------------------------------------------------------------------*/ 86 - .macro INTERRUPT_EPILOGUE called_from 87 - 88 - .ifnc \called_from, exception 89 - add sp, sp, 12 ; skip BTA/ECR/orig_r0 placeholderss 90 - .endif 91 - 92 - #ifdef CONFIG_ARC_CURR_IN_REG 93 - POP r25 94 - #else 95 - add sp, sp, 4 96 - #endif 97 - 98 - POP gp 99 - POP fp 100 - 101 - ; Don't touch AUX_USER_SP if returning to K mode (Z bit set) 102 - ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE) 103 - add.z sp, sp, 4 104 - bz 1f 105 - 106 - POPAX AUX_USER_SP 107 - 1: 108 - POP r12 109 - POP r30 110 163 111 164 #ifdef CONFIG_ARC_HAS_ACCL_REGS 112 - POP r58 113 - POP r59 114 - #endif 115 - 116 - #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 117 - .ifnc \called_from, exception 118 - POP r0 119 - POP r1 120 - POP r2 121 - POP r3 122 - POP r4 123 - POP r5 124 - POP r6 125 - POP r7 126 - POP r8 127 - POP r9 128 - POP r10 129 - POP r11 130 - 131 - POP blink 132 - POPAX lp_end 133 - POPAX lp_start 134 - 135 - POP r9 136 - mov lp_count, r9 137 - 138 - add sp, sp, 12 ; skip JLI, LDI, EI 139 - ld.as r9, [sp, -10] ; reload r9 which got clobbered 140 - .endif 165 + ST2 r58, r59, PT_sp + 12 141 166 #endif 142 167 143 168 .endm 144 169 145 170 /*------------------------------------------------------------------------*/ 146 - .macro EXCEPTION_PROLOGUE 171 + .macro __RESTORE_REGFILE_SOFT 147 172 148 - ; Before jumping to Exception Vector, hardware micro-ops did following: 149 - ; 1. SP auto-switched to kernel mode stack 150 - ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0) 151 - ; 152 - ; Now manually save the complete reg file 173 + LD2 gp, fp, PT_r26 ; gp (r26), fp (r27) 153 174 154 - PUSH r9 ; freeup a register: slot of erstatus 175 + ld r12, [sp, PT_sp + 4] 176 + ld r30, [sp, PT_sp + 8] 155 177 156 - PUSHAX eret 157 - sub sp, sp, 12 ; skip JLI, LDI, EI 158 - PUSH lp_count 159 - PUSHAX lp_start 160 - PUSHAX lp_end 161 - PUSH blink 178 + ; Restore SP (into AUX_USER_SP) only if returning to U mode 179 + ; - for K mode, it will be implicitly restored as stack is unwound 180 + ; - Z flag set on K is inverse of what hardware does on interrupt entry 181 + ; but that doesn't really matter 182 + bz 1f 162 183 163 - PUSH r11 164 - PUSH r10 184 + ld r10, [sp, PT_sp] ; SP (pt_regs->sp) 185 + sr r10, [AUX_USER_SP] 186 + 1: 165 187 166 - ld.as r9, [sp, 10] ; load stashed r9 (status32 stack slot) 167 - lr r10, [erstatus] 168 - st.as r10, [sp, 10] ; save status32 at it's right stack slot 188 + #ifdef CONFIG_ARC_CURR_IN_REG 189 + ld r25, [sp, PT_user_r25] 190 + #endif 169 191 170 - PUSH r9 171 - PUSH r8 172 - PUSH r7 173 - PUSH r6 174 - PUSH r5 175 - PUSH r4 176 - PUSH r3 177 - PUSH r2 178 - PUSH r1 179 - PUSH r0 192 + #ifdef CONFIG_ARC_HAS_ACCL_REGS 193 + LD2 r58, r59, PT_sp + 12 194 + #endif 195 + .endm 180 196 181 - ; -- for interrupts, regs above are auto-saved by h/w in that order -- 182 - ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25) 183 - ; 184 - ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE) 185 - ; Although H/w exception micro-ops do set Z flag for U mode (just like 186 - ; for interrupts), it could get clobbered in case we soft land here from 187 - ; a TLB Miss exception handler (tlbex.S) 197 + /*------------------------------------------------------------------------*/ 198 + .macro __RESTORE_REGFILE_HARD 188 199 189 - and r10, r10, STATUS_U_MASK 190 - xor.f 0, r10, STATUS_U_MASK 200 + ld blink, [sp, PT_blink] 191 201 192 - INTERRUPT_PROLOGUE exception 202 + LD2 r10, r11, PT_lpe 203 + sr r10, [lp_end] 204 + sr r11, [lp_start] 193 205 194 - PUSHAX erbta 195 - PUSHAX ecr ; r9 contains ECR, expected by EV_Trap 206 + ld r10, [sp, PT_lpc] ; lp_count can't be target of LD 207 + mov lp_count, r10 196 208 197 - PUSH r0 ; orig_r0 209 + LD2 r0, r1, PT_r0 210 + LD2 r2, r3, PT_r2 211 + LD2 r4, r5, PT_r4 212 + LD2 r6, r7, PT_r6 213 + LD2 r8, r9, PT_r8 214 + LD2 r10, r11, PT_r10 215 + .endm 216 + 217 + 218 + /*------------------------------------------------------------------------*/ 219 + .macro INTERRUPT_EPILOGUE 220 + 221 + ; INPUT: r0 has STAT32 of calling context 222 + ; INPUT: Z flag set if returning to K mode 223 + 224 + ; _SOFT clobbers r10 restored by _HARD hence the order 225 + 226 + __RESTORE_REGFILE_SOFT 227 + 228 + #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE 229 + __RESTORE_REGFILE_HARD 230 + add sp, sp, SZ_PT_REGS - 8 231 + #else 232 + add sp, sp, PT_r0 233 + #endif 234 + 198 235 .endm 199 236 200 237 /*------------------------------------------------------------------------*/ 201 238 .macro EXCEPTION_EPILOGUE 202 239 203 - ; Assumes r0 has PT_status32 204 - btst r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE 240 + ; INPUT: r0 has STAT32 of calling context 205 241 206 - add sp, sp, 8 ; orig_r0/ECR don't need restoring 207 - POPAX erbta 242 + btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP 208 243 209 - INTERRUPT_EPILOGUE exception 244 + ld r10, [sp, PT_event + 4] 245 + sr r10, [erbta] 210 246 211 - POP r0 212 - POP r1 213 - POP r2 214 - POP r3 215 - POP r4 216 - POP r5 217 - POP r6 218 - POP r7 219 - POP r8 220 - POP r9 221 - POP r10 222 - POP r11 247 + LD2 r10, r11, PT_ret 248 + sr r10, [eret] 249 + sr r11, [erstatus] 223 250 224 - POP blink 225 - POPAX lp_end 226 - POPAX lp_start 251 + __RESTORE_REGFILE_SOFT 252 + __RESTORE_REGFILE_HARD 227 253 228 - POP r9 229 - mov lp_count, r9 230 - 231 - add sp, sp, 12 ; skip JLI, LDI, EI 232 - POPAX eret 233 - POPAX erstatus 234 - 235 - ld.as r9, [sp, -12] ; reload r9 which got clobbered 254 + add sp, sp, SZ_PT_REGS 236 255 .endm 237 256 238 257 .macro FAKE_RET_FROM_EXCPN
+2 -2
arch/arc/include/asm/entry-compact.h
··· 195 195 PUSHAX CTOP_AUX_EFLAGS 196 196 #endif 197 197 198 - lr r9, [ecr] 199 - st r9, [sp, PT_event] /* EV_Trap expects r9 to have ECR */ 198 + lr r10, [ecr] 199 + st r10, [sp, PT_event] /* EV_Trap expects r10 to have ECR */ 200 200 .endm 201 201 202 202 /*--------------------------------------------------------------
+18
arch/arc/include/asm/linkage.h
··· 10 10 11 11 #ifdef __ASSEMBLY__ 12 12 13 + .macro ST2 e, o, off 14 + #ifdef CONFIG_ARC_HAS_LL64 15 + std \e, [sp, \off] 16 + #else 17 + st \e, [sp, \off] 18 + st \o, [sp, \off+4] 19 + #endif 20 + .endm 21 + 22 + .macro LD2 e, o, off 23 + #ifdef CONFIG_ARC_HAS_LL64 24 + ldd \e, [sp, \off] 25 + #else 26 + ld \e, [sp, \off] 27 + ld \o, [sp, \off+4] 28 + #endif 29 + .endm 30 + 13 31 #define ASM_NL ` /* use '`' to mark new line in macro */ 14 32 15 33 /* annotation for data we want in DCCM - if enabled in .config */
+7
arch/arc/kernel/asm-offsets.c
··· 55 55 DEFINE(PT_r5, offsetof(struct pt_regs, r5)); 56 56 DEFINE(PT_r6, offsetof(struct pt_regs, r6)); 57 57 DEFINE(PT_r7, offsetof(struct pt_regs, r7)); 58 + DEFINE(PT_r8, offsetof(struct pt_regs, r8)); 59 + DEFINE(PT_r10, offsetof(struct pt_regs, r10)); 60 + DEFINE(PT_r26, offsetof(struct pt_regs, r26)); 58 61 DEFINE(PT_ret, offsetof(struct pt_regs, ret)); 62 + DEFINE(PT_blink, offsetof(struct pt_regs, blink)); 63 + DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end)); 64 + DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count)); 65 + DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25)); 59 66 60 67 DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); 61 68 DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
+12 -50
arch/arc/kernel/entry-arcv2.S
··· 67 67 68 68 ENTRY(handle_interrupt) 69 69 70 - INTERRUPT_PROLOGUE irq 70 + INTERRUPT_PROLOGUE 71 71 72 72 # irq control APIs local_irq_save/restore/disable/enable fiddle with 73 73 # global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio) ··· 79 79 # 80 80 # Note this disable is only for consistent book-keeping as further interrupts 81 81 # will be disabled anyways even w/o this. Hardware tracks active interrupts 82 - # seperately in AUX_IRQ_ACTIVE.active and will not take new interrupts 82 + # seperately in AUX_IRQ_ACT.active and will not take new interrupts 83 83 # unless this one returns (or higher prio becomes pending in 2-prio scheme) 84 84 85 85 IRQ_DISABLE ··· 200 200 ld r0, [sp, PT_status32] ; U/K mode at time of entry 201 201 lr r10, [AUX_IRQ_ACT] 202 202 203 - bmsk r11, r10, 15 ; AUX_IRQ_ACT.ACTIVE 203 + bmsk r11, r10, 15 ; extract AUX_IRQ_ACT.active 204 204 breq r11, 0, .Lexcept_ret ; No intr active, ret from Exception 205 205 206 206 ;####### Return from Intr ####### 207 + 208 + .Lisr_ret: 207 209 208 210 debug_marker_l1: 209 211 ; bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot 210 212 btst r0, STATUS_DE_BIT ; Z flag set if bit clear 211 213 bnz .Lintr_ret_to_delay_slot ; branch if STATUS_DE_BIT set 212 214 213 - .Lisr_ret_fast_path: 214 215 ; Handle special case #1: (Entry via Exception, Return via IRQ) 215 216 ; 216 217 ; Exception in U mode, preempted in kernel, Intr taken (K mode), orig ··· 224 223 bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U 225 224 sr r11, [AUX_IRQ_ACT] 226 225 227 - INTERRUPT_EPILOGUE irq 226 + INTERRUPT_EPILOGUE 228 227 rtie 229 228 230 229 ;####### Return from Exception / pure kernel mode ####### ··· 245 244 ; 246 245 ; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround 247 246 ; 248 - ; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline 249 - ; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly 247 + ; Solution is to drop out of interrupt context into pure kernel mode 248 + ; and return from pure kernel mode which does right things for delay slot 250 249 251 250 .Lintr_ret_to_delay_slot: 252 251 debug_marker_ds: ··· 255 254 add r2, r2, 1 256 255 st r2, [@intr_to_DE_cnt] 257 256 258 - ld r2, [sp, PT_ret] 259 - ld r3, [sp, PT_status32] 260 - 261 - ; STAT32 for Int return created from scratch 262 - ; (No delay dlot, disable Further intr in trampoline) 263 - 264 - bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK 265 - st r0, [sp, PT_status32] 266 - 267 - mov r1, .Lintr_ret_to_delay_slot_2 268 - st r1, [sp, PT_ret] 269 - 270 - ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots 271 - st r2, [sp, 0] 272 - st r3, [sp, 4] 273 - 274 - b .Lisr_ret_fast_path 275 - 276 - .Lintr_ret_to_delay_slot_2: 277 - ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP 278 - sub sp, sp, SZ_PT_REGS 279 - st r9, [sp, -4] 280 - 281 - ld r9, [sp, 0] 282 - sr r9, [eret] 283 - 284 - ld r9, [sp, 4] 285 - sr r9, [erstatus] 286 - 287 - ; restore AUX_USER_SP if returning to U mode 288 - bbit0 r9, STATUS_U_BIT, 1f 289 - ld r9, [sp, PT_sp] 290 - sr r9, [AUX_USER_SP] 291 - 292 - 1: 293 - ld r9, [sp, 8] 294 - sr r9, [erbta] 295 - 296 - ld r9, [sp, -4] 297 - add sp, sp, SZ_PT_REGS 298 - 299 - ; return from pure kernel mode to delay slot 300 - rtie 257 + ; drop out of interrupt context (clear AUX_IRQ_ACT.active) 258 + bmskn r11, r10, 15 259 + sr r11, [AUX_IRQ_ACT] 260 + b .Lexcept_ret 301 261 302 262 END(ret_from_exception)
+1 -1
arch/arc/kernel/entry-compact.S
··· 256 256 257 257 EXCEPTION_PROLOGUE 258 258 259 - mov r2, r9 ; ECR set into r9 already 259 + mov r2, r10 ; ECR set into r10 already 260 260 lr r0, [efa] ; Faulting Data address (not part of pt_regs saved above) 261 261 262 262 ; Exception auto-disables further Intr/exceptions.
+2 -2
arch/arc/kernel/entry.S
··· 232 232 EXCEPTION_PROLOGUE 233 233 234 234 ;============ TRAP 1 :breakpoints 235 - ; Check ECR for trap with arg (PROLOGUE ensures r9 has ECR) 236 - bmsk.f 0, r9, 7 235 + ; Check ECR for trap with arg (PROLOGUE ensures r10 has ECR) 236 + bmsk.f 0, r10, 7 237 237 bnz trap_with_param 238 238 239 239 ;============ TRAP (no param): syscall top level
+4 -5
arch/arc/kernel/unwind.c
··· 181 181 return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS); 182 182 } 183 183 184 - static void *unw_hdr_alloc(unsigned long sz) 185 - { 186 - return kmalloc(sz, GFP_KERNEL); 187 - } 188 - 189 184 static void init_unwind_table(struct unwind_table *table, const char *name, 190 185 const void *core_start, unsigned long core_size, 191 186 const void *init_start, unsigned long init_size, ··· 361 366 } 362 367 363 368 #ifdef CONFIG_MODULES 369 + static void *unw_hdr_alloc(unsigned long sz) 370 + { 371 + return kmalloc(sz, GFP_KERNEL); 372 + } 364 373 365 374 static struct unwind_table *last_table; 366 375
+80 -111
arch/arc/mm/fault.c
··· 63 63 struct vm_area_struct *vma = NULL; 64 64 struct task_struct *tsk = current; 65 65 struct mm_struct *mm = tsk->mm; 66 - int si_code = SEGV_MAPERR; 67 - int ret; 68 - vm_fault_t fault; 69 - int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ 70 - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; 66 + int sig, si_code = SEGV_MAPERR; 67 + unsigned int write = 0, exec = 0, mask; 68 + vm_fault_t fault = VM_FAULT_SIGSEGV; /* handle_mm_fault() output */ 69 + unsigned int flags; /* handle_mm_fault() input */ 71 70 72 71 /* 73 - * We fault-in kernel-space virtual memory on-demand. The 74 - * 'reference' page table is init_mm.pgd. 75 - * 76 72 * NOTE! We MUST NOT take any locks for this case. We may 77 73 * be in an interrupt or a critical region, and should 78 74 * only copy the information from the master page table, 79 75 * nothing more. 80 76 */ 81 77 if (address >= VMALLOC_START && !user_mode(regs)) { 82 - ret = handle_kernel_vaddr_fault(address); 83 - if (unlikely(ret)) 78 + if (unlikely(handle_kernel_vaddr_fault(address))) 84 79 goto no_context; 85 80 else 86 81 return; ··· 88 93 if (faulthandler_disabled() || !mm) 89 94 goto no_context; 90 95 96 + if (regs->ecr_cause & ECR_C_PROTV_STORE) /* ST/EX */ 97 + write = 1; 98 + else if ((regs->ecr_vec == ECR_V_PROTV) && 99 + (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) 100 + exec = 1; 101 + 102 + flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; 91 103 if (user_mode(regs)) 92 104 flags |= FAULT_FLAG_USER; 105 + if (write) 106 + flags |= FAULT_FLAG_WRITE; 107 + 93 108 retry: 94 109 down_read(&mm->mmap_sem); 110 + 95 111 vma = find_vma(mm, address); 96 112 if (!vma) 97 113 goto bad_area; 98 - if (vma->vm_start <= address) 99 - goto good_area; 100 - if (!(vma->vm_flags & VM_GROWSDOWN)) 101 - goto bad_area; 102 - if (expand_stack(vma, address)) 103 - goto bad_area; 104 - 105 - /* 106 - * Ok, we have a good vm_area for this memory access, so 107 - * we can handle it.. 108 - */ 109 - good_area: 110 - si_code = SEGV_ACCERR; 111 - 112 - /* Handle protection violation, execute on heap or stack */ 113 - 114 - if ((regs->ecr_vec == ECR_V_PROTV) && 115 - (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) 116 - goto bad_area; 117 - 118 - if (write) { 119 - if (!(vma->vm_flags & VM_WRITE)) 120 - goto bad_area; 121 - flags |= FAULT_FLAG_WRITE; 122 - } else { 123 - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 114 + if (unlikely(address < vma->vm_start)) { 115 + if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, address)) 124 116 goto bad_area; 125 117 } 126 118 127 119 /* 128 - * If for any reason at all we couldn't handle the fault, 129 - * make sure we exit gracefully rather than endlessly redo 130 - * the fault. 120 + * vm_area is good, now check permissions for this memory access 131 121 */ 122 + mask = VM_READ; 123 + if (write) 124 + mask = VM_WRITE; 125 + if (exec) 126 + mask = VM_EXEC; 127 + 128 + if (!(vma->vm_flags & mask)) { 129 + si_code = SEGV_ACCERR; 130 + goto bad_area; 131 + } 132 + 132 133 fault = handle_mm_fault(vma, address, flags); 133 134 134 - if (fatal_signal_pending(current)) { 135 + /* 136 + * Fault retry nuances 137 + */ 138 + if (unlikely(fault & VM_FAULT_RETRY)) { 135 139 136 140 /* 137 - * if fault retry, mmap_sem already relinquished by core mm 138 - * so OK to return to user mode (with signal handled first) 141 + * If fault needs to be retried, handle any pending signals 142 + * first (by returning to user mode). 143 + * mmap_sem already relinquished by core mm for RETRY case 139 144 */ 140 - if (fault & VM_FAULT_RETRY) { 145 + if (fatal_signal_pending(current)) { 141 146 if (!user_mode(regs)) 142 147 goto no_context; 143 148 return; 144 149 } 145 - } 146 - 147 - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); 148 - 149 - if (likely(!(fault & VM_FAULT_ERROR))) { 150 + /* 151 + * retry state machine 152 + */ 150 153 if (flags & FAULT_FLAG_ALLOW_RETRY) { 151 - /* To avoid updating stats twice for retry case */ 152 - if (fault & VM_FAULT_MAJOR) { 153 - tsk->maj_flt++; 154 - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 155 - regs, address); 156 - } else { 157 - tsk->min_flt++; 158 - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 159 - regs, address); 160 - } 161 - 162 - if (fault & VM_FAULT_RETRY) { 163 - flags &= ~FAULT_FLAG_ALLOW_RETRY; 164 - flags |= FAULT_FLAG_TRIED; 165 - goto retry; 166 - } 154 + flags &= ~FAULT_FLAG_ALLOW_RETRY; 155 + flags |= FAULT_FLAG_TRIED; 156 + goto retry; 167 157 } 168 - 169 - /* Fault Handled Gracefully */ 170 - up_read(&mm->mmap_sem); 171 - return; 172 158 } 173 159 174 - if (fault & VM_FAULT_OOM) 175 - goto out_of_memory; 176 - else if (fault & VM_FAULT_SIGSEGV) 177 - goto bad_area; 178 - else if (fault & VM_FAULT_SIGBUS) 179 - goto do_sigbus; 180 - 181 - /* no man's land */ 182 - BUG(); 183 - 184 - /* 185 - * Something tried to access memory that isn't in our memory map.. 186 - * Fix it, but check if it's kernel or user first.. 187 - */ 188 160 bad_area: 189 161 up_read(&mm->mmap_sem); 190 162 191 - /* User mode accesses just cause a SIGSEGV */ 192 - if (user_mode(regs)) { 193 - tsk->thread.fault_address = address; 194 - force_sig_fault(SIGSEGV, si_code, (void __user *)address); 195 - return; 196 - } 197 - 198 - no_context: 199 - /* Are we prepared to handle this kernel fault? 200 - * 201 - * (The kernel has valid exception-points in the source 202 - * when it accesses user-memory. When it fails in one 203 - * of those points, we find it in a table and do a jump 204 - * to some fixup code that loads an appropriate error 205 - * code) 163 + /* 164 + * Major/minor page fault accounting 165 + * (in case of retry we only land here once) 206 166 */ 207 - if (fixup_exception(regs)) 208 - return; 167 + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); 209 168 210 - die("Oops", regs, address); 169 + if (likely(!(fault & VM_FAULT_ERROR))) { 170 + if (fault & VM_FAULT_MAJOR) { 171 + tsk->maj_flt++; 172 + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 173 + regs, address); 174 + } else { 175 + tsk->min_flt++; 176 + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 177 + regs, address); 178 + } 211 179 212 - out_of_memory: 213 - up_read(&mm->mmap_sem); 214 - 215 - if (user_mode(regs)) { 216 - pagefault_out_of_memory(); 180 + /* Normal return path: fault Handled Gracefully */ 217 181 return; 218 182 } 219 - 220 - goto no_context; 221 - 222 - do_sigbus: 223 - up_read(&mm->mmap_sem); 224 183 225 184 if (!user_mode(regs)) 226 185 goto no_context; 227 186 187 + if (fault & VM_FAULT_OOM) { 188 + pagefault_out_of_memory(); 189 + return; 190 + } 191 + 192 + if (fault & VM_FAULT_SIGBUS) { 193 + sig = SIGBUS; 194 + si_code = BUS_ADRERR; 195 + } 196 + else { 197 + sig = SIGSEGV; 198 + } 199 + 228 200 tsk->thread.fault_address = address; 229 - force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address); 201 + force_sig_fault(sig, si_code, (void __user *)address); 202 + return; 203 + 204 + no_context: 205 + if (fixup_exception(regs)) 206 + return; 207 + 208 + die("Oops", regs, address); 230 209 }
+11
arch/arc/mm/tlbex.S
··· 393 393 ;-------- Common routine to call Linux Page Fault Handler ----------- 394 394 do_slow_path_pf: 395 395 396 + #ifdef CONFIG_ISA_ARCV2 397 + ; Set Z flag if exception in U mode. Hardware micro-ops do this on any 398 + ; taken interrupt/exception, and thus is already the case at the entry 399 + ; above, but ensuing code would have already clobbered. 400 + ; EXCEPTION_PROLOGUE called in slow path, relies on correct Z flag set 401 + 402 + lr r2, [erstatus] 403 + and r2, r2, STATUS_U_MASK 404 + bxor.f 0, r2, STATUS_U_BIT 405 + #endif 406 + 396 407 ; Restore the 4-scratch regs saved by fast path miss handler 397 408 TLBMISS_RESTORE_REGS 398 409