Commit 3eb51486 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents c309b6f2 24a20b0a
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -62,5 +62,35 @@
			#interrupt-cells = <1>;
			interrupts = <20>;
		};

		virtio0: virtio@f0100000 {
			compatible = "virtio,mmio";
			reg = <0xf0100000 0x2000>;
			interrupts = <31>;
		};

		virtio1: virtio@f0102000 {
			compatible = "virtio,mmio";
			reg = <0xf0102000 0x2000>;
			interrupts = <32>;
		};

		virtio2: virtio@f0104000 {
			compatible = "virtio,mmio";
			reg = <0xf0104000 0x2000>;
			interrupts = <33>;
		};

		virtio3: virtio@f0106000 {
			compatible = "virtio,mmio";
			reg = <0xf0106000 0x2000>;
			interrupts = <34>;
		};

		virtio4: virtio@f0108000 {
			compatible = "virtio,mmio";
			reg = <0xf0108000 0x2000>;
			interrupts = <35>;
		};
	};
};
+14 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 */
/dts-v1/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/reset/snps,hsdk-reset.h>

/ {
@@ -252,6 +253,19 @@
			dma-coherent;
		};

		spi0: spi@20000 {
			compatible = "snps,dw-apb-ssi";
			reg = <0x20000 0x100>;
			#address-cells = <1>;
			#size-cells = <0>;
			interrupts = <16>;
			num-cs = <2>;
			reg-io-width = <4>;
			clocks = <&input_clk>;
			cs-gpios = <&creg_gpio 0 GPIO_ACTIVE_LOW>,
				   <&creg_gpio 1 GPIO_ACTIVE_LOW>;
		};

		creg_gpio: gpio@14b0 {
			compatible = "snps,creg-gpio-hsdk";
			reg = <0x14b0 0x4>;
+4 −1
Original line number Diff line number Diff line
@@ -35,10 +35,12 @@ CONFIG_INET=y
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_BLK_DEV is not set
CONFIG_VIRTIO_BLK=y
CONFIG_NETDEVICES=y
CONFIG_VIRTIO_NET=y
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
@@ -68,6 +70,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
# CONFIG_HID is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_VIRTIO_MMIO=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
+5 −0
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_SPI=y
CONFIG_SPI_DESIGNWARE=y
CONFIG_SPI_DW_MMIO=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
@@ -66,6 +69,8 @@ CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_DW=y
CONFIG_DMADEVICES=y
CONFIG_DW_AXI_DMAC=y
CONFIG_EXT3_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
+190 −171
Original line number Diff line number Diff line
@@ -7,232 +7,251 @@
#include <asm/irqflags-arcv2.h>
#include <asm/thread_info.h>	/* For THREAD_SIZE */

/*
 * Interrupt/Exception stack layout (pt_regs) for ARCv2
 *   (End of struct aligned to end of page [unless nested])
 *
 *  INTERRUPT                          EXCEPTION
 *
 *    manual    ---------------------  manual
 *              |      orig_r0      |
 *              |      event/ECR    |
 *              |      bta          |
 *              |      user_r25     |
 *              |      gp           |
 *              |      fp           |
 *              |      sp           |
 *              |      r12          |
 *              |      r30          |
 *              |      r58          |
 *              |      r59          |
 *  hw autosave ---------------------
 *    optional  |      r0           |
 *              |      r1           |
 *              ~                   ~
 *              |      r9           |
 *              |      r10          |
 *              |      r11          |
 *              |      blink        |
 *              |      lpe          |
 *              |      lps          |
 *              |      lpc          |
 *              |      ei base      |
 *              |      ldi base     |
 *              |      jli base     |
 *              ---------------------
 *  hw autosave |       pc / eret   |
 *   mandatory  | stat32 / erstatus |
 *              ---------------------
 */

/*------------------------------------------------------------------------*/
.macro INTERRUPT_PROLOGUE	called_from
.macro INTERRUPT_PROLOGUE

	; Before jumping to Interrupt Vector, hardware micro-ops did following:
	; (A) Before jumping to Interrupt Vector, hardware micro-ops did following:
	;   1. SP auto-switched to kernel mode stack
	;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
	;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
	;   2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0)
	;   3. Auto save: (mandatory) Push PC and STAT32 on stack
	;                 hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE
	;   4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI
	;
	; Now manually save: r12, sp, fp, gp, r25
	; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair

#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
.ifnc \called_from, exception
	st.as	r9, [sp, -10]	; save r9 in it's final stack slot
	sub	sp, sp, 12	; skip JLI, LDI, EI

	PUSH	lp_count
	PUSHAX	lp_start
	PUSHAX	lp_end
	PUSH	blink

	PUSH	r11
	PUSH	r10

	sub	sp, sp, 4	; skip r9

	PUSH	r8
	PUSH	r7
	PUSH	r6
	PUSH	r5
	PUSH	r4
	PUSH	r3
	PUSH	r2
	PUSH	r1
	PUSH	r0
.endif
#endif
	; carve pt_regs on stack (case #3), PC/STAT32 already on stack
	sub	sp, sp, SZ_PT_REGS - 8

#ifdef CONFIG_ARC_HAS_ACCL_REGS
	PUSH	r59
	PUSH	r58
	__SAVE_REGFILE_HARD
#else
	; carve pt_regs on stack (case #4), which grew partially already
	sub	sp, sp, PT_r0
#endif

	PUSH	r30
	PUSH	r12
	__SAVE_REGFILE_SOFT
.endm

/*------------------------------------------------------------------------*/
.macro EXCEPTION_PROLOGUE

	; (A) Before jumping to Exception Vector, hardware micro-ops did following:
	;   1. SP auto-switched to kernel mode stack
	;   2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0)
	;
	; (B) Manually save the complete reg file below

	sub	sp, sp, SZ_PT_REGS	; carve pt_regs

	; _HARD saves r10 clobbered by _SOFT as scratch hence comes first

	__SAVE_REGFILE_HARD
	__SAVE_REGFILE_SOFT

	st	r0, [sp]	; orig_r0

	lr	r10, [eret]
	lr	r11, [erstatus]
	ST2	r10, r11, PT_ret

	lr	r10, [ecr]
	lr	r11, [erbta]
	ST2	r10, r11, PT_event

	; OUTPUT: r10 has ECR expected by EV_Trap
.endm

/*------------------------------------------------------------------------
 * This macro saves the registers manually which would normally be autosaved
 * by hardware on taken interrupts. It is used by
 *   - exception handlers (which don't have autosave)
 *   - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE
 */
.macro __SAVE_REGFILE_HARD

	ST2	r0,  r1,  PT_r0
	ST2	r2,  r3,  PT_r2
	ST2	r4,  r5,  PT_r4
	ST2	r6,  r7,  PT_r6
	ST2	r8,  r9,  PT_r8
	ST2	r10, r11, PT_r10

	st	blink, [sp, PT_blink]

	lr	r10, [lp_end]
	lr	r11, [lp_start]
	ST2	r10, r11, PT_lpe

	st	lp_count, [sp, PT_lpc]

	; skip JLI, LDI, EI for now
.endm

/*------------------------------------------------------------------------
 * This macros saves a bunch of other registers which can't be autosaved for
 * various reasons:
 *   - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11
 *   - r30: free reg, used by gcc as scratch
 *   - ACCL/ACCH pair when they exist
 */
.macro __SAVE_REGFILE_SOFT

	ST2	gp, fp, PT_r26		; gp (r26), fp (r27)

	st	r12, [sp, PT_sp + 4]
	st	r30, [sp, PT_sp + 8]

	; Saving pt_regs->sp correctly requires some extra work due to the way
	; Auto stack switch works
	;  - U mode: retrieve it from AUX_USER_SP
	;  - K mode: add the offset from current SP where H/w starts auto push
	;
	; Utilize the fact that Z bit is set if Intr taken in U mode
	mov.nz	r9, sp
	add.nz	r9, r9, SZ_PT_REGS - PT_sp - 4
	bnz	1f
	; 1. Utilize the fact that Z bit is set if Intr taken in U mode
	; 2. Upon entry SP is always saved (for any inspection, unwinding etc),
	;    but on return, restored only if U mode

	lr	r9, [AUX_USER_SP]
1:
	PUSH	r9	; SP
	lr	r10, [AUX_USER_SP]	; U mode SP

	; ISA requires ADD.nz to have same dest and src reg operands
	mov.nz	r10, sp
	add.nz	r10, r10, SZ_PT_REGS	; K mode SP

	PUSH	fp
	PUSH	gp
	st	r10, [sp, PT_sp]	; SP (pt_regs->sp)

#ifdef CONFIG_ARC_CURR_IN_REG
	PUSH	r25			; user_r25
	st	r25, [sp, PT_user_r25]
	GET_CURR_TASK_ON_CPU	r25
#else
	sub	sp, sp, 4
#endif

.ifnc \called_from, exception
	sub	sp, sp, 12	; BTA/ECR/orig_r0 placeholder per pt_regs
.endif
#ifdef CONFIG_ARC_HAS_ACCL_REGS
	ST2	r58, r59, PT_sp + 12
#endif

.endm

/*------------------------------------------------------------------------*/
.macro INTERRUPT_EPILOGUE	called_from
.macro __RESTORE_REGFILE_SOFT

.ifnc \called_from, exception
	add	sp, sp, 12	; skip BTA/ECR/orig_r0 placeholderss
.endif
	LD2	gp, fp, PT_r26		; gp (r26), fp (r27)

#ifdef CONFIG_ARC_CURR_IN_REG
	POP	r25
#else
	add	sp, sp, 4
#endif
	ld	r12, [sp, PT_sp + 4]
	ld	r30, [sp, PT_sp + 8]

	POP	gp
	POP	fp

	; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
	; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
	add.z	sp, sp, 4
	; Restore SP (into AUX_USER_SP) only if returning to U mode
	;  - for K mode, it will be implicitly restored as stack is unwound
	;  - Z flag set on K is inverse of what hardware does on interrupt entry
	;    but that doesn't really matter
	bz	1f

	POPAX	AUX_USER_SP
	ld	r10, [sp, PT_sp]	; SP (pt_regs->sp)
	sr	r10, [AUX_USER_SP]
1:
	POP	r12
	POP	r30

#ifdef CONFIG_ARC_HAS_ACCL_REGS
	POP	r58
	POP	r59
#ifdef CONFIG_ARC_CURR_IN_REG
	ld	r25, [sp, PT_user_r25]
#endif

#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
.ifnc \called_from, exception
	POP	r0
	POP	r1
	POP	r2
	POP	r3
	POP	r4
	POP	r5
	POP	r6
	POP	r7
	POP	r8
	POP	r9
	POP	r10
	POP	r11

	POP	blink
	POPAX	lp_end
	POPAX	lp_start

	POP	r9
	mov	lp_count, r9

	add	sp, sp, 12	; skip JLI, LDI, EI
	ld.as	r9, [sp, -10]	; reload r9 which got clobbered
.endif
#ifdef CONFIG_ARC_HAS_ACCL_REGS
	LD2	r58, r59, PT_sp + 12
#endif
.endm

/*------------------------------------------------------------------------*/
.macro __RESTORE_REGFILE_HARD

	ld	blink, [sp, PT_blink]

	LD2	r10, r11, PT_lpe
	sr	r10, [lp_end]
	sr	r11, [lp_start]

	ld	r10, [sp, PT_lpc]	; lp_count can't be target of LD
	mov	lp_count, r10

	LD2	r0,  r1,  PT_r0
	LD2	r2,  r3,  PT_r2
	LD2	r4,  r5,  PT_r4
	LD2	r6,  r7,  PT_r6
	LD2	r8,  r9,  PT_r8
	LD2	r10, r11, PT_r10
.endm


/*------------------------------------------------------------------------*/
.macro EXCEPTION_PROLOGUE
.macro INTERRUPT_EPILOGUE

	; Before jumping to Exception Vector, hardware micro-ops did following:
	;   1. SP auto-switched to kernel mode stack
	;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
	;
	; Now manually save the complete reg file

	PUSH	r9		; freeup a register: slot of erstatus

	PUSHAX	eret
	sub	sp, sp, 12	; skip JLI, LDI, EI
	PUSH	lp_count
	PUSHAX	lp_start
	PUSHAX	lp_end
	PUSH	blink

	PUSH	r11
	PUSH	r10

	ld.as	r9,  [sp, 10]	; load stashed r9 (status32 stack slot)
	lr	r10, [erstatus]
	st.as	r10, [sp, 10]	; save status32 at it's right stack slot

	PUSH	r9
	PUSH	r8
	PUSH	r7
	PUSH	r6
	PUSH	r5
	PUSH	r4
	PUSH	r3
	PUSH	r2
	PUSH	r1
	PUSH	r0

	; -- for interrupts, regs above are auto-saved by h/w in that order --
	; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
	;
	; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
	; Although H/w exception micro-ops do set Z flag for U mode (just like
	; for interrupts), it could get clobbered in case we soft land here from
	; a TLB Miss exception handler (tlbex.S)
	; INPUT: r0 has STAT32 of calling context
	; INPUT: Z flag set if returning to K mode

	and	r10, r10, STATUS_U_MASK
	xor.f	0, r10, STATUS_U_MASK
	; _SOFT clobbers r10 restored by _HARD hence the order

	INTERRUPT_PROLOGUE  exception
	__RESTORE_REGFILE_SOFT

	PUSHAX	erbta
	PUSHAX	ecr		; r9 contains ECR, expected by EV_Trap
#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
	__RESTORE_REGFILE_HARD
	add	sp, sp, SZ_PT_REGS - 8
#else
	add	sp, sp, PT_r0
#endif

	PUSH	r0		; orig_r0
.endm

/*------------------------------------------------------------------------*/
.macro EXCEPTION_EPILOGUE

	; Assumes r0 has PT_status32
	btst   r0, STATUS_U_BIT	; Z flag set if K, used in INTERRUPT_EPILOGUE

	add	sp, sp, 8	; orig_r0/ECR don't need restoring
	POPAX	erbta

	INTERRUPT_EPILOGUE  exception
	; INPUT: r0 has STAT32 of calling context

	POP	r0
	POP	r1
	POP	r2
	POP	r3
	POP	r4
	POP	r5
	POP	r6
	POP	r7
	POP	r8
	POP	r9
	POP	r10
	POP	r11
	btst	r0, STATUS_U_BIT	; Z flag set if K, used in restoring SP

	POP	blink
	POPAX	lp_end
	POPAX	lp_start
	ld	r10, [sp, PT_event + 4]
	sr	r10, [erbta]

	POP	r9
	mov	lp_count, r9
	LD2	r10, r11, PT_ret
	sr	r10, [eret]
	sr	r11, [erstatus]

	add	sp, sp, 12	; skip JLI, LDI, EI
	POPAX	eret
	POPAX	erstatus
	__RESTORE_REGFILE_SOFT
	__RESTORE_REGFILE_HARD

	ld.as	r9, [sp, -12]	; reload r9 which got clobbered
	add	sp, sp, SZ_PT_REGS
.endm

.macro FAKE_RET_FROM_EXCPN
Loading