diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 17:23:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 17:23:42 -0500 |
commit | b0f0c26a2ed49eccf98a011b86fe24fb9f2b35f6 (patch) | |
tree | ad2efaa0ab0459257948127c56d4a7747cbefa11 | |
parent | 99fa0ad92c4fd8b529c89b3640b42323984be761 (diff) | |
parent | d16d2be111a61baf3a4696f07bfc7a8e36697cec (diff) |
Merge tag 'nios2-v3.20-rc1' of git://git.rocketboards.org/linux-socfpga-next
Pull arch/nios2 update from Ley Foon Tan:
"Here is the nios2 update for 3.20:
- add early printk support
- add kgdb support
- add compressed kernel support
- bugfixes"
* tag 'nios2-v3.20-rc1' of git://git.rocketboards.org/linux-socfpga-next:
nios2: add kgdb support
MAINTAINERS: update arch/nios2 git tree
nios2: default CONFIG_NIOS2_BOOT_LINK_OFFSET to 8MB
nios2: Add support for compressed kernel
nios2: add early printk support
nios2: Port OOM changes to do_page_fault()
nios2: Remove unused prepare_to_copy()
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | arch/nios2/Kconfig | 9 | ||||
-rw-r--r-- | arch/nios2/Kconfig.debug | 11 | ||||
-rw-r--r-- | arch/nios2/boot/Makefile | 7 | ||||
-rw-r--r-- | arch/nios2/boot/compressed/Makefile | 19 | ||||
-rw-r--r-- | arch/nios2/boot/compressed/console.c | 125 | ||||
-rw-r--r-- | arch/nios2/boot/compressed/head.S | 117 | ||||
-rw-r--r-- | arch/nios2/boot/compressed/misc.c | 187 | ||||
-rw-r--r-- | arch/nios2/boot/compressed/vmlinux.lds.S | 58 | ||||
-rw-r--r-- | arch/nios2/boot/compressed/vmlinux.scr | 28 | ||||
-rw-r--r-- | arch/nios2/configs/3c120_defconfig | 1 | ||||
-rw-r--r-- | arch/nios2/include/asm/kgdb.h | 93 | ||||
-rw-r--r-- | arch/nios2/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/nios2/include/asm/prom.h | 22 | ||||
-rw-r--r-- | arch/nios2/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/nios2/kernel/early_printk.c | 118 | ||||
-rw-r--r-- | arch/nios2/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/nios2/kernel/kgdb.c | 171 | ||||
-rw-r--r-- | arch/nios2/kernel/prom.c | 52 | ||||
-rw-r--r-- | arch/nios2/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/nios2/mm/fault.c | 37 |
21 files changed, 1067 insertions, 11 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 85024e23309f..3eee4c7739ae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6876,7 +6876,7 @@ F: drivers/scsi/nsp32* | |||
6876 | NIOS2 ARCHITECTURE | 6876 | NIOS2 ARCHITECTURE |
6877 | M: Ley Foon Tan <lftan@altera.com> | 6877 | M: Ley Foon Tan <lftan@altera.com> |
6878 | L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) | 6878 | L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers) |
6879 | T: git git://git.rocketboards.org/linux-socfpga.git | 6879 | T: git git://git.rocketboards.org/linux-socfpga-next.git |
6880 | S: Maintained | 6880 | S: Maintained |
6881 | F: arch/nios2/ | 6881 | F: arch/nios2/ |
6882 | 6882 | ||
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig index 2361acf6d2b1..437555424bda 100644 --- a/arch/nios2/Kconfig +++ b/arch/nios2/Kconfig | |||
@@ -8,6 +8,7 @@ config NIOS2 | |||
8 | select GENERIC_IRQ_PROBE | 8 | select GENERIC_IRQ_PROBE |
9 | select GENERIC_IRQ_SHOW | 9 | select GENERIC_IRQ_SHOW |
10 | select HAVE_ARCH_TRACEHOOK | 10 | select HAVE_ARCH_TRACEHOOK |
11 | select HAVE_ARCH_KGDB | ||
11 | select IRQ_DOMAIN | 12 | select IRQ_DOMAIN |
12 | select MODULES_USE_ELF_RELA | 13 | select MODULES_USE_ELF_RELA |
13 | select OF | 14 | select OF |
@@ -134,6 +135,14 @@ config NIOS2_PASS_CMDLINE | |||
134 | will override "Default kernel command string". | 135 | will override "Default kernel command string". |
135 | Say N if you are unsure. | 136 | Say N if you are unsure. |
136 | 137 | ||
138 | config NIOS2_BOOT_LINK_OFFSET | ||
139 | hex "Link address offset for booting" | ||
140 | default "0x00500000" | ||
141 | help | ||
142 | This option allows you to set the link address offset of the zImage. | ||
143 | This can be useful if you are on a board which has a small amount of | ||
144 | memory. | ||
145 | |||
137 | endmenu | 146 | endmenu |
138 | 147 | ||
139 | menu "Advanced setup" | 148 | menu "Advanced setup" |
diff --git a/arch/nios2/Kconfig.debug b/arch/nios2/Kconfig.debug index 8d4e6bacd997..2fd08cbfdddb 100644 --- a/arch/nios2/Kconfig.debug +++ b/arch/nios2/Kconfig.debug | |||
@@ -14,4 +14,15 @@ config DEBUG_STACK_USAGE | |||
14 | 14 | ||
15 | This option will slow down process creation somewhat. | 15 | This option will slow down process creation somewhat. |
16 | 16 | ||
17 | config EARLY_PRINTK | ||
18 | bool "Activate early kernel debugging" | ||
19 | default y | ||
20 | select SERIAL_CORE_CONSOLE | ||
21 | depends on SERIAL_ALTERA_JTAGUART_CONSOLE || SERIAL_ALTERA_UART_CONSOLE | ||
22 | help | ||
23 | Enable early printk on console | ||
24 | This is useful for kernel debugging when your machine crashes very | ||
25 | early before the console code is initialized. | ||
26 | You should normally say N here, unless you want to debug such a crash. | ||
27 | |||
17 | endmenu | 28 | endmenu |
diff --git a/arch/nios2/boot/Makefile b/arch/nios2/boot/Makefile index 59392dc0bdcb..c899876320df 100644 --- a/arch/nios2/boot/Makefile +++ b/arch/nios2/boot/Makefile | |||
@@ -24,6 +24,13 @@ $(obj)/vmImage: $(obj)/vmlinux.gz | |||
24 | $(call if_changed,uimage) | 24 | $(call if_changed,uimage) |
25 | @$(kecho) 'Kernel: $@ is ready' | 25 | @$(kecho) 'Kernel: $@ is ready' |
26 | 26 | ||
27 | $(obj)/zImage: $(obj)/compressed/vmlinux FORCE | ||
28 | $(call if_changed,objcopy) | ||
29 | @$(kecho) 'Kernel: $@ is ready' | ||
30 | |||
31 | $(obj)/compressed/vmlinux: $(obj)/vmlinux.gz FORCE | ||
32 | $(Q)$(MAKE) $(build)=$(obj)/compressed $@ | ||
33 | |||
27 | # Rule to build device tree blobs | 34 | # Rule to build device tree blobs |
28 | DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE)) | 35 | DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE)) |
29 | 36 | ||
diff --git a/arch/nios2/boot/compressed/Makefile b/arch/nios2/boot/compressed/Makefile new file mode 100644 index 000000000000..5b0fb346d888 --- /dev/null +++ b/arch/nios2/boot/compressed/Makefile | |||
@@ -0,0 +1,19 @@ | |||
1 | # | ||
2 | # create a compressed vmlinux image from the original vmlinux | ||
3 | # | ||
4 | |||
5 | targets := vmlinux head.o misc.o piggy.o vmlinux.lds | ||
6 | asflags-y := | ||
7 | |||
8 | OBJECTS = $(obj)/head.o $(obj)/misc.o | ||
9 | |||
10 | LDFLAGS_vmlinux := -T | ||
11 | |||
12 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE | ||
13 | $(call if_changed,ld) | ||
14 | @: | ||
15 | |||
16 | LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T | ||
17 | |||
18 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/../vmlinux.gz FORCE | ||
19 | $(call if_changed,ld) | ||
diff --git a/arch/nios2/boot/compressed/console.c b/arch/nios2/boot/compressed/console.c new file mode 100644 index 000000000000..2675e879b85a --- /dev/null +++ b/arch/nios2/boot/compressed/console.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2010 Thomas Chou <thomas@wytron.com.tw> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/io.h> | ||
20 | |||
21 | #if (defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE))\ | ||
22 | || (defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE)) | ||
23 | static void *my_ioremap(unsigned long physaddr) | ||
24 | { | ||
25 | return (void *)(physaddr | CONFIG_NIOS2_IO_REGION_BASE); | ||
26 | } | ||
27 | #endif | ||
28 | |||
29 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE) | ||
30 | |||
31 | #define ALTERA_JTAGUART_SIZE 8 | ||
32 | #define ALTERA_JTAGUART_DATA_REG 0 | ||
33 | #define ALTERA_JTAGUART_CONTROL_REG 4 | ||
34 | #define ALTERA_JTAGUART_CONTROL_AC_MSK (0x00000400) | ||
35 | #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK (0xFFFF0000) | ||
36 | static void *uartbase; | ||
37 | |||
38 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | ||
39 | static void jtag_putc(int ch) | ||
40 | { | ||
41 | if (readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) & | ||
42 | ALTERA_JTAGUART_CONTROL_WSPACE_MSK) | ||
43 | writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG); | ||
44 | } | ||
45 | #else | ||
46 | static void jtag_putc(int ch) | ||
47 | { | ||
48 | while ((readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) & | ||
49 | ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) | ||
50 | ; | ||
51 | writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG); | ||
52 | } | ||
53 | #endif | ||
54 | |||
55 | static int putchar(int ch) | ||
56 | { | ||
57 | jtag_putc(ch); | ||
58 | return ch; | ||
59 | } | ||
60 | |||
61 | static void console_init(void) | ||
62 | { | ||
63 | uartbase = my_ioremap((unsigned long) JTAG_UART_BASE); | ||
64 | writel(ALTERA_JTAGUART_CONTROL_AC_MSK, | ||
65 | uartbase + ALTERA_JTAGUART_CONTROL_REG); | ||
66 | } | ||
67 | |||
68 | #elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE) | ||
69 | |||
70 | #define ALTERA_UART_SIZE 32 | ||
71 | #define ALTERA_UART_TXDATA_REG 4 | ||
72 | #define ALTERA_UART_STATUS_REG 8 | ||
73 | #define ALTERA_UART_DIVISOR_REG 16 | ||
74 | #define ALTERA_UART_STATUS_TRDY_MSK (0x40) | ||
75 | static unsigned uartbase; | ||
76 | |||
77 | static void uart_putc(int ch) | ||
78 | { | ||
79 | int i; | ||
80 | |||
81 | for (i = 0; (i < 0x10000); i++) { | ||
82 | if (readw(uartbase + ALTERA_UART_STATUS_REG) & | ||
83 | ALTERA_UART_STATUS_TRDY_MSK) | ||
84 | break; | ||
85 | } | ||
86 | writeb(ch, uartbase + ALTERA_UART_TXDATA_REG); | ||
87 | } | ||
88 | |||
89 | static int putchar(int ch) | ||
90 | { | ||
91 | uart_putc(ch); | ||
92 | if (ch == '\n') | ||
93 | uart_putc('\r'); | ||
94 | return ch; | ||
95 | } | ||
96 | |||
97 | static void console_init(void) | ||
98 | { | ||
99 | unsigned int baud, baudclk; | ||
100 | |||
101 | uartbase = (unsigned long) my_ioremap((unsigned long) UART0_BASE); | ||
102 | baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE; | ||
103 | baudclk = UART0_FREQ / baud; | ||
104 | writew(baudclk, uartbase + ALTERA_UART_DIVISOR_REG); | ||
105 | } | ||
106 | |||
107 | #else | ||
108 | |||
109 | static int putchar(int ch) | ||
110 | { | ||
111 | return ch; | ||
112 | } | ||
113 | |||
114 | static void console_init(void) | ||
115 | { | ||
116 | } | ||
117 | |||
118 | #endif | ||
119 | |||
120 | static int puts(const char *s) | ||
121 | { | ||
122 | while (*s) | ||
123 | putchar(*s++); | ||
124 | return 0; | ||
125 | } | ||
diff --git a/arch/nios2/boot/compressed/head.S b/arch/nios2/boot/compressed/head.S new file mode 100644 index 000000000000..15c6c48dd909 --- /dev/null +++ b/arch/nios2/boot/compressed/head.S | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
3 | * | ||
4 | * Based on arch/nios2/kernel/head.S | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This code can be loaded anywhere, eg FLASH ROM as reset vector, | ||
14 | * as long as output does not overlap it. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <asm/cache.h> | ||
19 | |||
20 | .text | ||
21 | .set noat | ||
22 | ENTRY(_start) | ||
23 | wrctl status, r0 /* disable interrupt */ | ||
24 | /* invalidate all instruction cache */ | ||
25 | movia r1, NIOS2_ICACHE_SIZE | ||
26 | movui r2, NIOS2_ICACHE_LINE_SIZE | ||
27 | 1: initi r1 | ||
28 | sub r1, r1, r2 | ||
29 | bgt r1, r0, 1b | ||
30 | /* invalidate all data cache */ | ||
31 | movia r1, NIOS2_DCACHE_SIZE | ||
32 | movui r2, NIOS2_DCACHE_LINE_SIZE | ||
33 | 1: initd 0(r1) | ||
34 | sub r1, r1, r2 | ||
35 | bgt r1, r0, 1b | ||
36 | |||
37 | nextpc r1 /* Find out where we are */ | ||
38 | chkadr: | ||
39 | movia r2, chkadr | ||
40 | beq r1, r2, finish_move /* We are running in correct address, | ||
41 | done */ | ||
42 | /* move code, r1: src, r2: dest, r3: last dest */ | ||
43 | addi r1, r1, (_start - chkadr) /* Source */ | ||
44 | movia r2, _start /* Destination */ | ||
45 | movia r3, __bss_start /* End of copy */ | ||
46 | 1: ldw r8, 0(r1) /* load a word from [r1] */ | ||
47 | stw r8, 0(r2) /* stort a word to dest [r2] */ | ||
48 | addi r1, r1, 4 /* inc the src addr */ | ||
49 | addi r2, r2, 4 /* inc the dest addr */ | ||
50 | blt r2, r3, 1b | ||
51 | /* flush the data cache after moving */ | ||
52 | movia r1, NIOS2_DCACHE_SIZE | ||
53 | movui r2, NIOS2_DCACHE_LINE_SIZE | ||
54 | 1: flushd 0(r1) | ||
55 | sub r1, r1, r2 | ||
56 | bgt r1, r0, 1b | ||
57 | movia r1, finish_move | ||
58 | jmp r1 /* jmp to linked address */ | ||
59 | |||
60 | finish_move: | ||
61 | /* zero out the .bss segment (uninitialized common data) */ | ||
62 | movia r2, __bss_start /* presume nothing is between */ | ||
63 | movia r1, _end /* the .bss and _end. */ | ||
64 | 1: stb r0, 0(r2) | ||
65 | addi r2, r2, 1 | ||
66 | bne r1, r2, 1b | ||
67 | /* | ||
68 | * set up the stack pointer, some where higher than _end. | ||
69 | * The stack space must be greater than 32K for decompress. | ||
70 | */ | ||
71 | movia sp, 0x10000 | ||
72 | add sp, sp, r1 | ||
73 | /* save args passed from u-boot, maybe */ | ||
74 | addi sp, sp, -16 | ||
75 | stw r4, 0(sp) | ||
76 | stw r5, 4(sp) | ||
77 | stw r6, 8(sp) | ||
78 | stw r7, 12(sp) | ||
79 | /* decompress the kernel */ | ||
80 | call decompress_kernel | ||
81 | /* pass saved args to kernel */ | ||
82 | ldw r4, 0(sp) | ||
83 | ldw r5, 4(sp) | ||
84 | ldw r6, 8(sp) | ||
85 | ldw r7, 12(sp) | ||
86 | |||
87 | /* flush all data cache after decompressing */ | ||
88 | movia r1, NIOS2_DCACHE_SIZE | ||
89 | movui r2, NIOS2_DCACHE_LINE_SIZE | ||
90 | 1: flushd 0(r1) | ||
91 | sub r1, r1, r2 | ||
92 | bgt r1, r0, 1b | ||
93 | /* flush all instruction cache */ | ||
94 | movia r1, NIOS2_ICACHE_SIZE | ||
95 | movui r2, NIOS2_ICACHE_LINE_SIZE | ||
96 | 1: flushi r1 | ||
97 | sub r1, r1, r2 | ||
98 | bgt r1, r0, 1b | ||
99 | flushp | ||
100 | /* jump to start real kernel */ | ||
101 | movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE) | ||
102 | jmp r1 | ||
103 | |||
104 | .balign 512 | ||
105 | fake_headers_as_bzImage: | ||
106 | .short 0 | ||
107 | .ascii "HdrS" | ||
108 | .short 0x0202 | ||
109 | .short 0 | ||
110 | .short 0 | ||
111 | .byte 0x00, 0x10 | ||
112 | .short 0 | ||
113 | .byte 0 | ||
114 | .byte 1 | ||
115 | .byte 0x00, 0x80 | ||
116 | .long 0 | ||
117 | .long 0 | ||
diff --git a/arch/nios2/boot/compressed/misc.c b/arch/nios2/boot/compressed/misc.c new file mode 100644 index 000000000000..84377825ef1a --- /dev/null +++ b/arch/nios2/boot/compressed/misc.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
3 | * | ||
4 | * This is a collection of several routines from gzip-1.0.3 | ||
5 | * adapted for Linux. | ||
6 | * | ||
7 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | ||
8 | * | ||
9 | * Adapted for SH by Stuart Menefy, Aug 1999 | ||
10 | * | ||
11 | * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000 | ||
12 | * | ||
13 | * Based on arch/sh/boot/compressed/misc.c | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/string.h> | ||
31 | |||
32 | /* | ||
33 | * gzip declarations | ||
34 | */ | ||
35 | #define OF(args) args | ||
36 | #define STATIC static | ||
37 | |||
38 | #undef memset | ||
39 | #undef memcpy | ||
40 | #define memzero(s, n) memset((s), 0, (n)) | ||
41 | |||
42 | typedef unsigned char uch; | ||
43 | typedef unsigned short ush; | ||
44 | typedef unsigned long ulg; | ||
45 | #define WSIZE 0x8000 /* Window size must be at least 32k, */ | ||
46 | /* and a power of two */ | ||
47 | |||
48 | static uch *inbuf; /* input buffer */ | ||
49 | static uch window[WSIZE]; /* Sliding window buffer */ | ||
50 | |||
51 | static unsigned insize; /* valid bytes in inbuf */ | ||
52 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
53 | static unsigned outcnt; /* bytes in output buffer */ | ||
54 | |||
55 | /* gzip flag byte */ | ||
56 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ | ||
57 | #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip | ||
58 | file */ | ||
59 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ | ||
60 | #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ | ||
61 | #define COMMENT 0x10 /* bit 4 set: file comment present */ | ||
62 | #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ | ||
63 | #define RESERVED 0xC0 /* bit 6,7: reserved */ | ||
64 | |||
65 | #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | ||
66 | |||
67 | #ifdef DEBUG | ||
68 | # define Assert(cond, msg) {if (!(cond)) error(msg); } | ||
69 | # define Trace(x) fprintf x | ||
70 | # define Tracev(x) {if (verbose) fprintf x ; } | ||
71 | # define Tracevv(x) {if (verbose > 1) fprintf x ; } | ||
72 | # define Tracec(c, x) {if (verbose && (c)) fprintf x ; } | ||
73 | # define Tracecv(c, x) {if (verbose > 1 && (c)) fprintf x ; } | ||
74 | #else | ||
75 | # define Assert(cond, msg) | ||
76 | # define Trace(x) | ||
77 | # define Tracev(x) | ||
78 | # define Tracevv(x) | ||
79 | # define Tracec(c, x) | ||
80 | # define Tracecv(c, x) | ||
81 | #endif | ||
82 | static int fill_inbuf(void); | ||
83 | static void flush_window(void); | ||
84 | static void error(char *m); | ||
85 | |||
86 | extern char input_data[]; | ||
87 | extern int input_len; | ||
88 | |||
89 | static long bytes_out; | ||
90 | static uch *output_data; | ||
91 | static unsigned long output_ptr; | ||
92 | |||
93 | #include "console.c" | ||
94 | |||
95 | static void error(char *m); | ||
96 | |||
97 | int puts(const char *); | ||
98 | |||
99 | extern int _end; | ||
100 | static unsigned long free_mem_ptr; | ||
101 | static unsigned long free_mem_end_ptr; | ||
102 | |||
103 | #define HEAP_SIZE 0x10000 | ||
104 | |||
105 | #include "../../../../lib/inflate.c" | ||
106 | |||
107 | void *memset(void *s, int c, size_t n) | ||
108 | { | ||
109 | int i; | ||
110 | char *ss = (char *)s; | ||
111 | |||
112 | for (i = 0; i < n; i++) | ||
113 | ss[i] = c; | ||
114 | return s; | ||
115 | } | ||
116 | |||
117 | void *memcpy(void *__dest, __const void *__src, size_t __n) | ||
118 | { | ||
119 | int i; | ||
120 | char *d = (char *)__dest, *s = (char *)__src; | ||
121 | |||
122 | for (i = 0; i < __n; i++) | ||
123 | d[i] = s[i]; | ||
124 | return __dest; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Fill the input buffer. This is called only when the buffer is empty | ||
129 | * and at least one byte is really needed. | ||
130 | */ | ||
131 | static int fill_inbuf(void) | ||
132 | { | ||
133 | if (insize != 0) | ||
134 | error("ran out of input data"); | ||
135 | |||
136 | inbuf = input_data; | ||
137 | insize = input_len; | ||
138 | inptr = 1; | ||
139 | return inbuf[0]; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
144 | * (Used for the decompressed data only.) | ||
145 | */ | ||
146 | static void flush_window(void) | ||
147 | { | ||
148 | ulg c = crc; /* temporary variable */ | ||
149 | unsigned n; | ||
150 | uch *in, *out, ch; | ||
151 | |||
152 | in = window; | ||
153 | out = &output_data[output_ptr]; | ||
154 | for (n = 0; n < outcnt; n++) { | ||
155 | ch = *out++ = *in++; | ||
156 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
157 | } | ||
158 | crc = c; | ||
159 | bytes_out += (ulg)outcnt; | ||
160 | output_ptr += (ulg)outcnt; | ||
161 | outcnt = 0; | ||
162 | } | ||
163 | |||
164 | static void error(char *x) | ||
165 | { | ||
166 | puts("\nERROR\n"); | ||
167 | puts(x); | ||
168 | puts("\n\n -- System halted"); | ||
169 | |||
170 | while (1) /* Halt */ | ||
171 | ; | ||
172 | } | ||
173 | |||
174 | void decompress_kernel(void) | ||
175 | { | ||
176 | output_data = (void *) (CONFIG_NIOS2_MEM_BASE | | ||
177 | CONFIG_NIOS2_KERNEL_REGION_BASE); | ||
178 | output_ptr = 0; | ||
179 | free_mem_ptr = (unsigned long)&_end; | ||
180 | free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; | ||
181 | |||
182 | console_init(); | ||
183 | makecrc(); | ||
184 | puts("Uncompressing Linux... "); | ||
185 | gunzip(); | ||
186 | puts("Ok, booting the kernel.\n"); | ||
187 | } | ||
diff --git a/arch/nios2/boot/compressed/vmlinux.lds.S b/arch/nios2/boot/compressed/vmlinux.lds.S new file mode 100644 index 000000000000..e867b3756059 --- /dev/null +++ b/arch/nios2/boot/compressed/vmlinux.lds.S | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <asm-generic/vmlinux.lds.h> | ||
20 | |||
21 | OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2") | ||
22 | |||
23 | OUTPUT_ARCH(nios) | ||
24 | ENTRY(_start) /* Defined in head.S */ | ||
25 | |||
26 | SECTIONS | ||
27 | { | ||
28 | . = (CONFIG_NIOS2_MEM_BASE + CONFIG_NIOS2_BOOT_LINK_OFFSET) | \ | ||
29 | CONFIG_NIOS2_KERNEL_REGION_BASE; | ||
30 | |||
31 | _text = .; | ||
32 | .text : { *(.text) } = 0 | ||
33 | .rodata : { *(.rodata) *(.rodata.*) } | ||
34 | _etext = .; | ||
35 | |||
36 | . = ALIGN(32 / 8); | ||
37 | .data : { *(.data) } | ||
38 | . = ALIGN(32 / 8); | ||
39 | _got = .; | ||
40 | .got : { | ||
41 | *(.got.plt) | ||
42 | *(.igot.plt) | ||
43 | *(.got) | ||
44 | *(.igot) | ||
45 | } | ||
46 | _egot = .; | ||
47 | _edata = .; | ||
48 | |||
49 | . = ALIGN(32 / 8); | ||
50 | __bss_start = .; | ||
51 | .bss : { *(.bss) *(.sbss) } | ||
52 | . = ALIGN(32 / 8); | ||
53 | _ebss = .; | ||
54 | end = . ; | ||
55 | _end = . ; | ||
56 | |||
57 | got_len = (_egot - _got); | ||
58 | } | ||
diff --git a/arch/nios2/boot/compressed/vmlinux.scr b/arch/nios2/boot/compressed/vmlinux.scr new file mode 100644 index 000000000000..28c42f1d127e --- /dev/null +++ b/arch/nios2/boot/compressed/vmlinux.scr | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | SECTIONS | ||
20 | { | ||
21 | .data : { | ||
22 | input_len = .; | ||
23 | LONG(input_data_end - input_data) input_data = .; | ||
24 | *(.data) | ||
25 | . = ALIGN(4); | ||
26 | input_data_end = .; | ||
27 | } | ||
28 | } | ||
diff --git a/arch/nios2/configs/3c120_defconfig b/arch/nios2/configs/3c120_defconfig index 87541f0a5d6e..9451940678a0 100644 --- a/arch/nios2/configs/3c120_defconfig +++ b/arch/nios2/configs/3c120_defconfig | |||
@@ -22,6 +22,7 @@ CONFIG_NIOS2_DCACHE_SIZE=0x8000 | |||
22 | CONFIG_NIOS2_ICACHE_SIZE=0x8000 | 22 | CONFIG_NIOS2_ICACHE_SIZE=0x8000 |
23 | # CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set | 23 | # CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set |
24 | CONFIG_NIOS2_PASS_CMDLINE=y | 24 | CONFIG_NIOS2_PASS_CMDLINE=y |
25 | CONFIG_NIOS2_BOOT_LINK_OFFSET=0x00800000 | ||
25 | CONFIG_NET=y | 26 | CONFIG_NET=y |
26 | CONFIG_PACKET=y | 27 | CONFIG_PACKET=y |
27 | CONFIG_UNIX=y | 28 | CONFIG_UNIX=y |
diff --git a/arch/nios2/include/asm/kgdb.h b/arch/nios2/include/asm/kgdb.h new file mode 100644 index 000000000000..8fd5e3b66c57 --- /dev/null +++ b/arch/nios2/include/asm/kgdb.h | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Altera Corporation | ||
3 | * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> | ||
4 | * | ||
5 | * Based on the code posted by Kazuyasu on the Altera Forum at: | ||
6 | * http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef _ASM_NIOS2_KGDB_H | ||
24 | #define _ASM_NIOS2_KGDB_H | ||
25 | |||
26 | #define CACHE_FLUSH_IS_SAFE 1 | ||
27 | #define BUFMAX 2048 | ||
28 | |||
29 | enum regnames { | ||
30 | GDB_R0 = 0, | ||
31 | GDB_AT, | ||
32 | GDB_R2, | ||
33 | GDB_R3, | ||
34 | GDB_R4, | ||
35 | GDB_R5, | ||
36 | GDB_R6, | ||
37 | GDB_R7, | ||
38 | GDB_R8, | ||
39 | GDB_R9, | ||
40 | GDB_R10, | ||
41 | GDB_R11, | ||
42 | GDB_R12, | ||
43 | GDB_R13, | ||
44 | GDB_R14, | ||
45 | GDB_R15, | ||
46 | GDB_R16, | ||
47 | GDB_R17, | ||
48 | GDB_R18, | ||
49 | GDB_R19, | ||
50 | GDB_R20, | ||
51 | GDB_R21, | ||
52 | GDB_R22, | ||
53 | GDB_R23, | ||
54 | GDB_ET, | ||
55 | GDB_BT, | ||
56 | GDB_GP, | ||
57 | GDB_SP, | ||
58 | GDB_FP, | ||
59 | GDB_EA, | ||
60 | GDB_BA, | ||
61 | GDB_RA, | ||
62 | GDB_PC, | ||
63 | GDB_STATUS, | ||
64 | GDB_ESTATUS, | ||
65 | GDB_BSTATUS, | ||
66 | GDB_IENABLE, | ||
67 | GDB_IPENDING, | ||
68 | GDB_CPUID, | ||
69 | GDB_CTL6, | ||
70 | GDB_EXCEPTION, | ||
71 | GDB_PTEADDR, | ||
72 | GDB_TLBACC, | ||
73 | GDB_TLBMISC, | ||
74 | GDB_ECCINJ, | ||
75 | GDB_BADADDR, | ||
76 | GDB_CONFIG, | ||
77 | GDB_MPUBASE, | ||
78 | GDB_MPUACC, | ||
79 | /* do not change the last entry or anything below! */ | ||
80 | GDB_NUMREGBYTES /* number of registers */ | ||
81 | }; | ||
82 | |||
83 | #define GDB_SIZEOF_REG sizeof(u32) | ||
84 | #define DBG_MAX_REG_NUM (49) | ||
85 | #define NUMREGBYTES (DBG_MAX_REG_NUM * sizeof(GDB_SIZEOF_REG)) | ||
86 | |||
87 | #define BREAK_INSTR_SIZE 4 | ||
88 | static inline void arch_kgdb_breakpoint(void) | ||
89 | { | ||
90 | __asm__ __volatile__("trap 30\n"); | ||
91 | } | ||
92 | |||
93 | #endif /* _ASM_NIOS2_KGDB_H */ | ||
diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h index 3bd349473b06..c2ba45c159c7 100644 --- a/arch/nios2/include/asm/processor.h +++ b/arch/nios2/include/asm/processor.h | |||
@@ -85,9 +85,6 @@ static inline void exit_thread(void) | |||
85 | 85 | ||
86 | extern unsigned long get_wchan(struct task_struct *p); | 86 | extern unsigned long get_wchan(struct task_struct *p); |
87 | 87 | ||
88 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
89 | #define prepare_to_copy(tsk) do { } while (0) | ||
90 | |||
91 | #define task_pt_regs(p) \ | 88 | #define task_pt_regs(p) \ |
92 | ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) | 89 | ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) |
93 | 90 | ||
diff --git a/arch/nios2/include/asm/prom.h b/arch/nios2/include/asm/prom.h new file mode 100644 index 000000000000..75fffb42cfa5 --- /dev/null +++ b/arch/nios2/include/asm/prom.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright Altera Corporation (C) <2015>. All rights reserved | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ASM_NIOS2_PROM_H__ | ||
18 | #define __ASM_NIOS2_PROM_H__ | ||
19 | |||
20 | extern unsigned long __init of_early_console(void); | ||
21 | |||
22 | #endif | ||
diff --git a/arch/nios2/kernel/Makefile b/arch/nios2/kernel/Makefile index 8ae76823ff93..1aae25703657 100644 --- a/arch/nios2/kernel/Makefile +++ b/arch/nios2/kernel/Makefile | |||
@@ -20,5 +20,7 @@ obj-y += syscall_table.o | |||
20 | obj-y += time.o | 20 | obj-y += time.o |
21 | obj-y += traps.o | 21 | obj-y += traps.o |
22 | 22 | ||
23 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
24 | obj-$(CONFIG_KGDB) += kgdb.o | ||
23 | obj-$(CONFIG_MODULES) += module.o | 25 | obj-$(CONFIG_MODULES) += module.o |
24 | obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP) += misaligned.o | 26 | obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP) += misaligned.o |
diff --git a/arch/nios2/kernel/early_printk.c b/arch/nios2/kernel/early_printk.c new file mode 100644 index 000000000000..c08e4c1486fc --- /dev/null +++ b/arch/nios2/kernel/early_printk.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Early printk for Nios2. | ||
3 | * | ||
4 | * Copyright (C) 2015, Altera Corporation | ||
5 | * Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch> | ||
6 | * Copyright (C) 2009, Wind River Systems Inc | ||
7 | * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/console.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | #include <asm/prom.h> | ||
20 | |||
21 | static unsigned long base_addr; | ||
22 | |||
23 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) | ||
24 | |||
25 | #define ALTERA_JTAGUART_DATA_REG 0 | ||
26 | #define ALTERA_JTAGUART_CONTROL_REG 4 | ||
27 | #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000 | ||
28 | #define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400 | ||
29 | |||
30 | #define JUART_GET_CR() \ | ||
31 | __builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG)) | ||
32 | #define JUART_SET_CR(v) \ | ||
33 | __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v) | ||
34 | #define JUART_SET_TX(v) \ | ||
35 | __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v) | ||
36 | |||
37 | static void early_console_write(struct console *con, const char *s, unsigned n) | ||
38 | { | ||
39 | unsigned long status; | ||
40 | |||
41 | while (n-- && *s) { | ||
42 | while (((status = JUART_GET_CR()) | ||
43 | & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { | ||
44 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | ||
45 | if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) | ||
46 | return; /* no connection activity */ | ||
47 | #endif | ||
48 | } | ||
49 | JUART_SET_TX(*s); | ||
50 | s++; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | #elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | ||
55 | |||
56 | #define ALTERA_UART_TXDATA_REG 4 | ||
57 | #define ALTERA_UART_STATUS_REG 8 | ||
58 | #define ALTERA_UART_STATUS_TRDY 0x0040 | ||
59 | |||
60 | #define UART_GET_SR() \ | ||
61 | __builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG)) | ||
62 | #define UART_SET_TX(v) \ | ||
63 | __builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v) | ||
64 | |||
65 | static void early_console_putc(char c) | ||
66 | { | ||
67 | while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY)) | ||
68 | ; | ||
69 | |||
70 | UART_SET_TX(c); | ||
71 | } | ||
72 | |||
73 | static void early_console_write(struct console *con, const char *s, unsigned n) | ||
74 | { | ||
75 | while (n-- && *s) { | ||
76 | early_console_putc(*s); | ||
77 | if (*s == '\n') | ||
78 | early_console_putc('\r'); | ||
79 | s++; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | #else | ||
84 | # error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \ | ||
85 | selected | ||
86 | #endif | ||
87 | |||
88 | static struct console early_console_prom = { | ||
89 | .name = "early", | ||
90 | .write = early_console_write, | ||
91 | .flags = CON_PRINTBUFFER | CON_BOOT, | ||
92 | .index = -1 | ||
93 | }; | ||
94 | |||
95 | void __init setup_early_printk(void) | ||
96 | { | ||
97 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) || \ | ||
98 | defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | ||
99 | base_addr = of_early_console(); | ||
100 | #else | ||
101 | base_addr = 0; | ||
102 | #endif | ||
103 | |||
104 | if (!base_addr) | ||
105 | return; | ||
106 | |||
107 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | ||
108 | /* Clear activity bit so BYPASS doesn't stall if we've used JTAG for | ||
109 | * downloading the kernel. This might cause early data to be lost even | ||
110 | * if the JTAG terminal is running. | ||
111 | */ | ||
112 | JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK); | ||
113 | #endif | ||
114 | |||
115 | early_console = &early_console_prom; | ||
116 | register_console(early_console); | ||
117 | pr_info("early_console initialized at 0x%08lx\n", base_addr); | ||
118 | } | ||
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 0bdfd13ff98b..7729bd3f2e79 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S | |||
@@ -121,7 +121,11 @@ trap_table: | |||
121 | .word instruction_trap /* 27 */ | 121 | .word instruction_trap /* 27 */ |
122 | .word instruction_trap /* 28 */ | 122 | .word instruction_trap /* 28 */ |
123 | .word instruction_trap /* 29 */ | 123 | .word instruction_trap /* 29 */ |
124 | .word instruction_trap /* 30 */ | 124 | #ifdef CONFIG_KGDB |
125 | .word handle_kgdb_breakpoint /* 30 KGDB breakpoint */ | ||
126 | #else | ||
127 | .word instruction_trap /* 30 */ | ||
128 | #endif | ||
125 | .word handle_breakpoint /* 31 */ | 129 | .word handle_breakpoint /* 31 */ |
126 | 130 | ||
127 | .text | 131 | .text |
@@ -445,6 +449,12 @@ handle_diverror: | |||
445 | call handle_diverror_c | 449 | call handle_diverror_c |
446 | br ret_from_exception | 450 | br ret_from_exception |
447 | 451 | ||
452 | #ifdef CONFIG_KGDB | ||
453 | handle_kgdb_breakpoint: | ||
454 | call kgdb_breakpoint_c | ||
455 | br ret_from_exception | ||
456 | #endif | ||
457 | |||
448 | /* | 458 | /* |
449 | * Beware - when entering resume, prev (the current task) is | 459 | * Beware - when entering resume, prev (the current task) is |
450 | * in r4, next (the new task) is in r5, don't change these | 460 | * in r4, next (the new task) is in r5, don't change these |
diff --git a/arch/nios2/kernel/kgdb.c b/arch/nios2/kernel/kgdb.c new file mode 100644 index 000000000000..117859122d1c --- /dev/null +++ b/arch/nios2/kernel/kgdb.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Nios2 KGDB support | ||
3 | * | ||
4 | * Copyright (C) 2015 Altera Corporation | ||
5 | * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> | ||
6 | * | ||
7 | * Based on the code posted by Kazuyasu on the Altera Forum at: | ||
8 | * http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20 | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | * | ||
23 | */ | ||
24 | #include <linux/ptrace.h> | ||
25 | #include <linux/kgdb.h> | ||
26 | #include <linux/kdebug.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | static int wait_for_remote_debugger; | ||
30 | |||
31 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | ||
32 | { | ||
33 | { "zero", GDB_SIZEOF_REG, -1 }, | ||
34 | { "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, r1) }, | ||
35 | { "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r2) }, | ||
36 | { "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r3) }, | ||
37 | { "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r4) }, | ||
38 | { "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r5) }, | ||
39 | { "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r6) }, | ||
40 | { "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r7) }, | ||
41 | { "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r8) }, | ||
42 | { "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r9) }, | ||
43 | { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10) }, | ||
44 | { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11) }, | ||
45 | { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12) }, | ||
46 | { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13) }, | ||
47 | { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14) }, | ||
48 | { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15) }, | ||
49 | { "r16", GDB_SIZEOF_REG, -1 }, | ||
50 | { "r17", GDB_SIZEOF_REG, -1 }, | ||
51 | { "r18", GDB_SIZEOF_REG, -1 }, | ||
52 | { "r19", GDB_SIZEOF_REG, -1 }, | ||
53 | { "r20", GDB_SIZEOF_REG, -1 }, | ||
54 | { "r21", GDB_SIZEOF_REG, -1 }, | ||
55 | { "r22", GDB_SIZEOF_REG, -1 }, | ||
56 | { "r23", GDB_SIZEOF_REG, -1 }, | ||
57 | { "et", GDB_SIZEOF_REG, -1 }, | ||
58 | { "bt", GDB_SIZEOF_REG, -1 }, | ||
59 | { "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp) }, | ||
60 | { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) }, | ||
61 | { "fp", GDB_SIZEOF_REG, offsetof(struct pt_regs, fp) }, | ||
62 | { "ea", GDB_SIZEOF_REG, -1 }, | ||
63 | { "ba", GDB_SIZEOF_REG, -1 }, | ||
64 | { "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, ra) }, | ||
65 | { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, ea) }, | ||
66 | { "status", GDB_SIZEOF_REG, -1 }, | ||
67 | { "estatus", GDB_SIZEOF_REG, offsetof(struct pt_regs, estatus) }, | ||
68 | { "bstatus", GDB_SIZEOF_REG, -1 }, | ||
69 | { "ienable", GDB_SIZEOF_REG, -1 }, | ||
70 | { "ipending", GDB_SIZEOF_REG, -1}, | ||
71 | { "cpuid", GDB_SIZEOF_REG, -1 }, | ||
72 | { "ctl6", GDB_SIZEOF_REG, -1 }, | ||
73 | { "exception", GDB_SIZEOF_REG, -1 }, | ||
74 | { "pteaddr", GDB_SIZEOF_REG, -1 }, | ||
75 | { "tlbacc", GDB_SIZEOF_REG, -1 }, | ||
76 | { "tlbmisc", GDB_SIZEOF_REG, -1 }, | ||
77 | { "eccinj", GDB_SIZEOF_REG, -1 }, | ||
78 | { "badaddr", GDB_SIZEOF_REG, -1 }, | ||
79 | { "config", GDB_SIZEOF_REG, -1 }, | ||
80 | { "mpubase", GDB_SIZEOF_REG, -1 }, | ||
81 | { "mpuacc", GDB_SIZEOF_REG, -1 }, | ||
82 | }; | ||
83 | |||
84 | char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) | ||
85 | { | ||
86 | if (regno >= DBG_MAX_REG_NUM || regno < 0) | ||
87 | return NULL; | ||
88 | |||
89 | if (dbg_reg_def[regno].offset != -1) | ||
90 | memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, | ||
91 | dbg_reg_def[regno].size); | ||
92 | else | ||
93 | memset(mem, 0, dbg_reg_def[regno].size); | ||
94 | |||
95 | return dbg_reg_def[regno].name; | ||
96 | } | ||
97 | |||
98 | int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) | ||
99 | { | ||
100 | if (regno >= DBG_MAX_REG_NUM || regno < 0) | ||
101 | return -EINVAL; | ||
102 | |||
103 | if (dbg_reg_def[regno].offset != -1) | ||
104 | memcpy((void *)regs + dbg_reg_def[regno].offset, mem, | ||
105 | dbg_reg_def[regno].size); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | ||
111 | { | ||
112 | memset((char *)gdb_regs, 0, NUMREGBYTES); | ||
113 | gdb_regs[GDB_SP] = p->thread.kregs->sp; | ||
114 | gdb_regs[GDB_PC] = p->thread.kregs->ea; | ||
115 | } | ||
116 | |||
117 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) | ||
118 | { | ||
119 | regs->ea = pc; | ||
120 | } | ||
121 | |||
122 | int kgdb_arch_handle_exception(int vector, int signo, int err_code, | ||
123 | char *remcom_in_buffer, char *remcom_out_buffer, | ||
124 | struct pt_regs *regs) | ||
125 | { | ||
126 | char *ptr; | ||
127 | unsigned long addr; | ||
128 | |||
129 | switch (remcom_in_buffer[0]) { | ||
130 | case 's': | ||
131 | case 'c': | ||
132 | /* handle the optional parameters */ | ||
133 | ptr = &remcom_in_buffer[1]; | ||
134 | if (kgdb_hex2long(&ptr, &addr)) | ||
135 | regs->ea = addr; | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | return -1; /* this means that we do not want to exit from the handler */ | ||
141 | } | ||
142 | |||
143 | asmlinkage void kgdb_breakpoint_c(struct pt_regs *regs) | ||
144 | { | ||
145 | /* | ||
146 | * The breakpoint entry code has moved the PC on by 4 bytes, so we must | ||
147 | * move it back. This could be done on the host but we do it here | ||
148 | */ | ||
149 | if (!wait_for_remote_debugger) | ||
150 | regs->ea -= 4; | ||
151 | else /* pass the first trap 30 code */ | ||
152 | wait_for_remote_debugger = 0; | ||
153 | |||
154 | kgdb_handle_exception(30, SIGTRAP, 0, regs); | ||
155 | } | ||
156 | |||
157 | int kgdb_arch_init(void) | ||
158 | { | ||
159 | wait_for_remote_debugger = 1; | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | void kgdb_arch_exit(void) | ||
164 | { | ||
165 | /* Nothing to do */ | ||
166 | } | ||
167 | |||
168 | struct kgdb_arch arch_kgdb_ops = { | ||
169 | /* Breakpoint instruction: trap 30 */ | ||
170 | .gdb_bpt_instr = { 0xba, 0x6f, 0x3b, 0x00 }, | ||
171 | }; | ||
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 0522d3378e3f..718dd197909f 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Device tree support | 2 | * Device tree support |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Altera Corporation | 4 | * Copyright (C) 2013, 2015 Altera Corporation |
5 | * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> | 5 | * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> |
6 | * | 6 | * |
7 | * Based on MIPS support for CONFIG_OF device tree support | 7 | * Based on MIPS support for CONFIG_OF device tree support |
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/of_fdt.h> | 30 | #include <linux/of_fdt.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | 32 | ||
33 | #include <asm/prom.h> | ||
33 | #include <asm/sections.h> | 34 | #include <asm/sections.h> |
34 | 35 | ||
35 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | 36 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) |
@@ -63,3 +64,52 @@ void __init early_init_devtree(void *params) | |||
63 | 64 | ||
64 | early_init_dt_scan(params); | 65 | early_init_dt_scan(params); |
65 | } | 66 | } |
67 | |||
68 | #ifdef CONFIG_EARLY_PRINTK | ||
69 | static int __init early_init_dt_scan_serial(unsigned long node, | ||
70 | const char *uname, int depth, void *data) | ||
71 | { | ||
72 | u64 *addr64 = (u64 *) data; | ||
73 | const char *p; | ||
74 | |||
75 | /* only consider serial nodes */ | ||
76 | if (strncmp(uname, "serial", 6) != 0) | ||
77 | return 0; | ||
78 | |||
79 | p = of_get_flat_dt_prop(node, "compatible", NULL); | ||
80 | if (!p) | ||
81 | return 0; | ||
82 | |||
83 | /* | ||
84 | * We found an altera_jtaguart but it wasn't configured for console, so | ||
85 | * skip it. | ||
86 | */ | ||
87 | #ifndef CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE | ||
88 | if (strncmp(p, "altr,juart", 10) == 0) | ||
89 | return 0; | ||
90 | #endif | ||
91 | |||
92 | /* | ||
93 | * Same for altera_uart. | ||
94 | */ | ||
95 | #ifndef CONFIG_SERIAL_ALTERA_UART_CONSOLE | ||
96 | if (strncmp(p, "altr,uart", 9) == 0) | ||
97 | return 0; | ||
98 | #endif | ||
99 | |||
100 | *addr64 = fdt_translate_address((const void *)initial_boot_params, | ||
101 | node); | ||
102 | |||
103 | return *addr64 == OF_BAD_ADDR ? 0 : 1; | ||
104 | } | ||
105 | |||
106 | unsigned long __init of_early_console(void) | ||
107 | { | ||
108 | u64 base = 0; | ||
109 | |||
110 | if (of_scan_flat_dt(early_init_dt_scan_serial, &base)) | ||
111 | return (u32)ioremap(base, 32); | ||
112 | else | ||
113 | return 0; | ||
114 | } | ||
115 | #endif /* CONFIG_EARLY_PRINTK */ | ||
diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c index cb3121f975d4..b101a43d3c5a 100644 --- a/arch/nios2/kernel/setup.c +++ b/arch/nios2/kernel/setup.c | |||
@@ -139,6 +139,10 @@ void __init setup_arch(char **cmdline_p) | |||
139 | 139 | ||
140 | console_verbose(); | 140 | console_verbose(); |
141 | 141 | ||
142 | #ifdef CONFIG_EARLY_PRINTK | ||
143 | setup_early_printk(); | ||
144 | #endif | ||
145 | |||
142 | memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); | 146 | memory_start = PAGE_ALIGN((unsigned long)__pa(_end)); |
143 | memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; | 147 | memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size; |
144 | 148 | ||
diff --git a/arch/nios2/mm/fault.c b/arch/nios2/mm/fault.c index d194c0427b26..0d231adfe576 100644 --- a/arch/nios2/mm/fault.c +++ b/arch/nios2/mm/fault.c | |||
@@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, | |||
47 | struct mm_struct *mm = tsk->mm; | 47 | struct mm_struct *mm = tsk->mm; |
48 | int code = SEGV_MAPERR; | 48 | int code = SEGV_MAPERR; |
49 | int fault; | 49 | int fault; |
50 | unsigned int flags = 0; | 50 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
51 | 51 | ||
52 | cause >>= 2; | 52 | cause >>= 2; |
53 | 53 | ||
@@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, | |||
86 | if (!down_read_trylock(&mm->mmap_sem)) { | 86 | if (!down_read_trylock(&mm->mmap_sem)) { |
87 | if (!user_mode(regs) && !search_exception_tables(regs->ea)) | 87 | if (!user_mode(regs) && !search_exception_tables(regs->ea)) |
88 | goto bad_area_nosemaphore; | 88 | goto bad_area_nosemaphore; |
89 | retry: | ||
89 | down_read(&mm->mmap_sem); | 90 | down_read(&mm->mmap_sem); |
90 | } | 91 | } |
91 | 92 | ||
@@ -132,6 +133,10 @@ survive: | |||
132 | * the fault. | 133 | * the fault. |
133 | */ | 134 | */ |
134 | fault = handle_mm_fault(mm, vma, address, flags); | 135 | fault = handle_mm_fault(mm, vma, address, flags); |
136 | |||
137 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
138 | return; | ||
139 | |||
135 | if (unlikely(fault & VM_FAULT_ERROR)) { | 140 | if (unlikely(fault & VM_FAULT_ERROR)) { |
136 | if (fault & VM_FAULT_OOM) | 141 | if (fault & VM_FAULT_OOM) |
137 | goto out_of_memory; | 142 | goto out_of_memory; |
@@ -141,10 +146,32 @@ survive: | |||
141 | goto do_sigbus; | 146 | goto do_sigbus; |
142 | BUG(); | 147 | BUG(); |
143 | } | 148 | } |
144 | if (fault & VM_FAULT_MAJOR) | 149 | |
145 | tsk->maj_flt++; | 150 | /* |
146 | else | 151 | * Major/minor page fault accounting is only done on the |
147 | tsk->min_flt++; | 152 | * initial attempt. If we go through a retry, it is extremely |
153 | * likely that the page will be found in page cache at that point. | ||
154 | */ | ||
155 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | ||
156 | if (fault & VM_FAULT_MAJOR) | ||
157 | current->maj_flt++; | ||
158 | else | ||
159 | current->min_flt++; | ||
160 | if (fault & VM_FAULT_RETRY) { | ||
161 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | ||
162 | * of starvation. */ | ||
163 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
164 | flags |= FAULT_FLAG_TRIED; | ||
165 | |||
166 | /* | ||
167 | * No need to up_read(&mm->mmap_sem) as we would | ||
168 | * have already released it in __lock_page_or_retry | ||
169 | * in mm/filemap.c. | ||
170 | */ | ||
171 | |||
172 | goto retry; | ||
173 | } | ||
174 | } | ||
148 | 175 | ||
149 | up_read(&mm->mmap_sem); | 176 | up_read(&mm->mmap_sem); |
150 | return; | 177 | return; |