nios2 for v3.20

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.5 (GNU/Linux)
 
 iQIVAwUAVOHU+1WoEK+e3syCAQJOKQ//cMvDMVZkLK6/XddsX+KpBePbqjeBv4tB
 n+GTBsSV3RKNX27k6ZfA5AReFtFKQpXgFfB2aUjBLnVWHwM5sCU/wXwNAGhX8md4
 TgDQqVId3B5+n31lkwgeuTH86zqaObZO5JBfPEiKg8B0tJFifimrtEoFM2tuiDMt
 uAsHzYgsP/r9L/aBgCyJ4AJMmkXxNFSMw1ivvDB2IajRHI+zXK1HahMUHo+hLyMq
 UwHhLmeAu0MEW+GQ7yTS+UMIRYMG87VYP5gD/g+91c7buv8MCxDRUtRkK1uTQAMl
 tZ+067raQhw/UcnF5ZJtoDvDsKtYhcaYGgtiQq9ywTThoUGxuLvJHqW485DinF9Y
 o2ntK9h/d3NNRudFhinKyI3/gxDOQYZNUg/uCfCIofHaHET5xYk1+KmmOd5vdDaD
 rC9yLkQMF5/4vBi0ygULh9+f0C1kinyVH479EsOrf2KewsjhukCGKdSmjKIdsevT
 tZ6LrSp4G83kfOPAb6jot5UdX+XMwGVVBCiy6dJI1SHGmnmyn6UT3MmVocRbS9Kx
 2BTjOnC7c+wmTWxkVDHyy3MwykekqJZNgCRLo0Px1v+FWl5g/iwrEIpkhEjhRivL
 01VC/07P/0PunIv8OnI369CuIWHS9B/fPz6oPHQbLO+n16JqakFWDLS6s1wqu/jM
 1EBvneZNPFc=
 =u6dr
 -----END PGP SIGNATURE-----

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()
This commit is contained in:
Linus Torvalds 2015-02-17 14:23:42 -08:00
commit b0f0c26a2e
21 changed files with 1067 additions and 11 deletions

View File

@ -6876,7 +6876,7 @@ F: drivers/scsi/nsp32*
NIOS2 ARCHITECTURE
M: Ley Foon Tan <lftan@altera.com>
L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
T: git git://git.rocketboards.org/linux-socfpga.git
T: git git://git.rocketboards.org/linux-socfpga-next.git
S: Maintained
F: arch/nios2/

View File

@ -8,6 +8,7 @@ config NIOS2
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_KGDB
select IRQ_DOMAIN
select MODULES_USE_ELF_RELA
select OF
@ -134,6 +135,14 @@ config NIOS2_PASS_CMDLINE
will override "Default kernel command string".
Say N if you are unsure.
config NIOS2_BOOT_LINK_OFFSET
hex "Link address offset for booting"
default "0x00500000"
help
This option allows you to set the link address offset of the zImage.
This can be useful if you are on a board which has a small amount of
memory.
endmenu
menu "Advanced setup"

View File

@ -14,4 +14,15 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
config EARLY_PRINTK
bool "Activate early kernel debugging"
default y
select SERIAL_CORE_CONSOLE
depends on SERIAL_ALTERA_JTAGUART_CONSOLE || SERIAL_ALTERA_UART_CONSOLE
help
Enable early printk on console
This is useful for kernel debugging when your machine crashes very
early before the console code is initialized.
You should normally say N here, unless you want to debug such a crash.
endmenu

View File

@ -24,6 +24,13 @@ $(obj)/vmImage: $(obj)/vmlinux.gz
$(call if_changed,uimage)
@$(kecho) 'Kernel: $@ is ready'
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@$(kecho) 'Kernel: $@ is ready'
$(obj)/compressed/vmlinux: $(obj)/vmlinux.gz FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
# Rule to build device tree blobs
DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE))

View File

@ -0,0 +1,19 @@
#
# create a compressed vmlinux image from the original vmlinux
#
targets := vmlinux head.o misc.o piggy.o vmlinux.lds
asflags-y :=
OBJECTS = $(obj)/head.o $(obj)/misc.o
LDFLAGS_vmlinux := -T
$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:
LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/../vmlinux.gz FORCE
$(call if_changed,ld)

View File

@ -0,0 +1,125 @@
/*
* Copyright (C) 2008-2010 Thomas Chou <thomas@wytron.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/io.h>
#if (defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE))\
|| (defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE))
static void *my_ioremap(unsigned long physaddr)
{
return (void *)(physaddr | CONFIG_NIOS2_IO_REGION_BASE);
}
#endif
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) && defined(JTAG_UART_BASE)
#define ALTERA_JTAGUART_SIZE 8
#define ALTERA_JTAGUART_DATA_REG 0
#define ALTERA_JTAGUART_CONTROL_REG 4
#define ALTERA_JTAGUART_CONTROL_AC_MSK (0x00000400)
#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK (0xFFFF0000)
static void *uartbase;
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
static void jtag_putc(int ch)
{
if (readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK)
writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG);
}
#else
static void jtag_putc(int ch)
{
while ((readl(uartbase + ALTERA_JTAGUART_CONTROL_REG) &
ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0)
;
writeb(ch, uartbase + ALTERA_JTAGUART_DATA_REG);
}
#endif
static int putchar(int ch)
{
jtag_putc(ch);
return ch;
}
static void console_init(void)
{
uartbase = my_ioremap((unsigned long) JTAG_UART_BASE);
writel(ALTERA_JTAGUART_CONTROL_AC_MSK,
uartbase + ALTERA_JTAGUART_CONTROL_REG);
}
#elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) && defined(UART0_BASE)
#define ALTERA_UART_SIZE 32
#define ALTERA_UART_TXDATA_REG 4
#define ALTERA_UART_STATUS_REG 8
#define ALTERA_UART_DIVISOR_REG 16
#define ALTERA_UART_STATUS_TRDY_MSK (0x40)
static unsigned uartbase;
static void uart_putc(int ch)
{
int i;
for (i = 0; (i < 0x10000); i++) {
if (readw(uartbase + ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK)
break;
}
writeb(ch, uartbase + ALTERA_UART_TXDATA_REG);
}
static int putchar(int ch)
{
uart_putc(ch);
if (ch == '\n')
uart_putc('\r');
return ch;
}
static void console_init(void)
{
unsigned int baud, baudclk;
uartbase = (unsigned long) my_ioremap((unsigned long) UART0_BASE);
baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
baudclk = UART0_FREQ / baud;
writew(baudclk, uartbase + ALTERA_UART_DIVISOR_REG);
}
#else
static int putchar(int ch)
{
return ch;
}
static void console_init(void)
{
}
#endif
static int puts(const char *s)
{
while (*s)
putchar(*s++);
return 0;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
*
* Based on arch/nios2/kernel/head.S
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
*/
/*
* This code can be loaded anywhere, eg FLASH ROM as reset vector,
* as long as output does not overlap it.
*/
#include <linux/linkage.h>
#include <asm/cache.h>
.text
.set noat
ENTRY(_start)
wrctl status, r0 /* disable interrupt */
/* invalidate all instruction cache */
movia r1, NIOS2_ICACHE_SIZE
movui r2, NIOS2_ICACHE_LINE_SIZE
1: initi r1
sub r1, r1, r2
bgt r1, r0, 1b
/* invalidate all data cache */
movia r1, NIOS2_DCACHE_SIZE
movui r2, NIOS2_DCACHE_LINE_SIZE
1: initd 0(r1)
sub r1, r1, r2
bgt r1, r0, 1b
nextpc r1 /* Find out where we are */
chkadr:
movia r2, chkadr
beq r1, r2, finish_move /* We are running in correct address,
done */
/* move code, r1: src, r2: dest, r3: last dest */
addi r1, r1, (_start - chkadr) /* Source */
movia r2, _start /* Destination */
movia r3, __bss_start /* End of copy */
1: ldw r8, 0(r1) /* load a word from [r1] */
stw r8, 0(r2) /* stort a word to dest [r2] */
addi r1, r1, 4 /* inc the src addr */
addi r2, r2, 4 /* inc the dest addr */
blt r2, r3, 1b
/* flush the data cache after moving */
movia r1, NIOS2_DCACHE_SIZE
movui r2, NIOS2_DCACHE_LINE_SIZE
1: flushd 0(r1)
sub r1, r1, r2
bgt r1, r0, 1b
movia r1, finish_move
jmp r1 /* jmp to linked address */
finish_move:
/* zero out the .bss segment (uninitialized common data) */
movia r2, __bss_start /* presume nothing is between */
movia r1, _end /* the .bss and _end. */
1: stb r0, 0(r2)
addi r2, r2, 1
bne r1, r2, 1b
/*
* set up the stack pointer, some where higher than _end.
* The stack space must be greater than 32K for decompress.
*/
movia sp, 0x10000
add sp, sp, r1
/* save args passed from u-boot, maybe */
addi sp, sp, -16
stw r4, 0(sp)
stw r5, 4(sp)
stw r6, 8(sp)
stw r7, 12(sp)
/* decompress the kernel */
call decompress_kernel
/* pass saved args to kernel */
ldw r4, 0(sp)
ldw r5, 4(sp)
ldw r6, 8(sp)
ldw r7, 12(sp)
/* flush all data cache after decompressing */
movia r1, NIOS2_DCACHE_SIZE
movui r2, NIOS2_DCACHE_LINE_SIZE
1: flushd 0(r1)
sub r1, r1, r2
bgt r1, r0, 1b
/* flush all instruction cache */
movia r1, NIOS2_ICACHE_SIZE
movui r2, NIOS2_ICACHE_LINE_SIZE
1: flushi r1
sub r1, r1, r2
bgt r1, r0, 1b
flushp
/* jump to start real kernel */
movia r1, (CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE)
jmp r1
.balign 512
fake_headers_as_bzImage:
.short 0
.ascii "HdrS"
.short 0x0202
.short 0
.short 0
.byte 0x00, 0x10
.short 0
.byte 0
.byte 1
.byte 0x00, 0x80
.long 0
.long 0

View File

@ -0,0 +1,187 @@
/*
* Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
*
* This is a collection of several routines from gzip-1.0.3
* adapted for Linux.
*
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
*
* Adapted for SH by Stuart Menefy, Aug 1999
*
* Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
*
* Based on arch/sh/boot/compressed/misc.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/string.h>
/*
* gzip declarations
*/
#define OF(args) args
#define STATIC static
#undef memset
#undef memcpy
#define memzero(s, n) memset((s), 0, (n))
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
#define WSIZE 0x8000 /* Window size must be at least 32k, */
/* and a power of two */
static uch *inbuf; /* input buffer */
static uch window[WSIZE]; /* Sliding window buffer */
static unsigned insize; /* valid bytes in inbuf */
static unsigned inptr; /* index of next byte to be processed in inbuf */
static unsigned outcnt; /* bytes in output buffer */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip
file */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
#ifdef DEBUG
# define Assert(cond, msg) {if (!(cond)) error(msg); }
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ; }
# define Tracevv(x) {if (verbose > 1) fprintf x ; }
# define Tracec(c, x) {if (verbose && (c)) fprintf x ; }
# define Tracecv(c, x) {if (verbose > 1 && (c)) fprintf x ; }
#else
# define Assert(cond, msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c, x)
# define Tracecv(c, x)
#endif
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
extern char input_data[];
extern int input_len;
static long bytes_out;
static uch *output_data;
static unsigned long output_ptr;
#include "console.c"
static void error(char *m);
int puts(const char *);
extern int _end;
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
#define HEAP_SIZE 0x10000
#include "../../../../lib/inflate.c"
void *memset(void *s, int c, size_t n)
{
int i;
char *ss = (char *)s;
for (i = 0; i < n; i++)
ss[i] = c;
return s;
}
void *memcpy(void *__dest, __const void *__src, size_t __n)
{
int i;
char *d = (char *)__dest, *s = (char *)__src;
for (i = 0; i < __n; i++)
d[i] = s[i];
return __dest;
}
/*
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
*/
static int fill_inbuf(void)
{
if (insize != 0)
error("ran out of input data");
inbuf = input_data;
insize = input_len;
inptr = 1;
return inbuf[0];
}
/*
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only.)
*/
static void flush_window(void)
{
ulg c = crc; /* temporary variable */
unsigned n;
uch *in, *out, ch;
in = window;
out = &output_data[output_ptr];
for (n = 0; n < outcnt; n++) {
ch = *out++ = *in++;
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
}
crc = c;
bytes_out += (ulg)outcnt;
output_ptr += (ulg)outcnt;
outcnt = 0;
}
static void error(char *x)
{
puts("\nERROR\n");
puts(x);
puts("\n\n -- System halted");
while (1) /* Halt */
;
}
void decompress_kernel(void)
{
output_data = (void *) (CONFIG_NIOS2_MEM_BASE |
CONFIG_NIOS2_KERNEL_REGION_BASE);
output_ptr = 0;
free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
console_init();
makecrc();
puts("Uncompressing Linux... ");
gunzip();
puts("Ok, booting the kernel.\n");
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <asm-generic/vmlinux.lds.h>
OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2")
OUTPUT_ARCH(nios)
ENTRY(_start) /* Defined in head.S */
SECTIONS
{
. = (CONFIG_NIOS2_MEM_BASE + CONFIG_NIOS2_BOOT_LINK_OFFSET) | \
CONFIG_NIOS2_KERNEL_REGION_BASE;
_text = .;
.text : { *(.text) } = 0
.rodata : { *(.rodata) *(.rodata.*) }
_etext = .;
. = ALIGN(32 / 8);
.data : { *(.data) }
. = ALIGN(32 / 8);
_got = .;
.got : {
*(.got.plt)
*(.igot.plt)
*(.got)
*(.igot)
}
_egot = .;
_edata = .;
. = ALIGN(32 / 8);
__bss_start = .;
.bss : { *(.bss) *(.sbss) }
. = ALIGN(32 / 8);
_ebss = .;
end = . ;
_end = . ;
got_len = (_egot - _got);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
SECTIONS
{
.data : {
input_len = .;
LONG(input_data_end - input_data) input_data = .;
*(.data)
. = ALIGN(4);
input_data_end = .;
}
}

View File

@ -22,6 +22,7 @@ CONFIG_NIOS2_DCACHE_SIZE=0x8000
CONFIG_NIOS2_ICACHE_SIZE=0x8000
# CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set
CONFIG_NIOS2_PASS_CMDLINE=y
CONFIG_NIOS2_BOOT_LINK_OFFSET=0x00800000
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2015 Altera Corporation
* Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
*
* Based on the code posted by Kazuyasu on the Altera Forum at:
* http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _ASM_NIOS2_KGDB_H
#define _ASM_NIOS2_KGDB_H
#define CACHE_FLUSH_IS_SAFE 1
#define BUFMAX 2048
enum regnames {
GDB_R0 = 0,
GDB_AT,
GDB_R2,
GDB_R3,
GDB_R4,
GDB_R5,
GDB_R6,
GDB_R7,
GDB_R8,
GDB_R9,
GDB_R10,
GDB_R11,
GDB_R12,
GDB_R13,
GDB_R14,
GDB_R15,
GDB_R16,
GDB_R17,
GDB_R18,
GDB_R19,
GDB_R20,
GDB_R21,
GDB_R22,
GDB_R23,
GDB_ET,
GDB_BT,
GDB_GP,
GDB_SP,
GDB_FP,
GDB_EA,
GDB_BA,
GDB_RA,
GDB_PC,
GDB_STATUS,
GDB_ESTATUS,
GDB_BSTATUS,
GDB_IENABLE,
GDB_IPENDING,
GDB_CPUID,
GDB_CTL6,
GDB_EXCEPTION,
GDB_PTEADDR,
GDB_TLBACC,
GDB_TLBMISC,
GDB_ECCINJ,
GDB_BADADDR,
GDB_CONFIG,
GDB_MPUBASE,
GDB_MPUACC,
/* do not change the last entry or anything below! */
GDB_NUMREGBYTES /* number of registers */
};
#define GDB_SIZEOF_REG sizeof(u32)
#define DBG_MAX_REG_NUM (49)
#define NUMREGBYTES (DBG_MAX_REG_NUM * sizeof(GDB_SIZEOF_REG))
#define BREAK_INSTR_SIZE 4
static inline void arch_kgdb_breakpoint(void)
{
__asm__ __volatile__("trap 30\n");
}
#endif /* _ASM_NIOS2_KGDB_H */

View File

@ -85,9 +85,6 @@ static inline void exit_thread(void)
extern unsigned long get_wchan(struct task_struct *p);
/* Prepare to copy thread state - unlazy all lazy status */
#define prepare_to_copy(tsk) do { } while (0)
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1)

View File

@ -0,0 +1,22 @@
/*
* Copyright Altera Corporation (C) <2015>. All rights reserved
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_NIOS2_PROM_H__
#define __ASM_NIOS2_PROM_H__
extern unsigned long __init of_early_console(void);
#endif

View File

@ -20,5 +20,7 @@ obj-y += syscall_table.o
obj-y += time.o
obj-y += traps.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP) += misaligned.o

View File

@ -0,0 +1,118 @@
/*
* Early printk for Nios2.
*
* Copyright (C) 2015, Altera Corporation
* Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch>
* Copyright (C) 2009, Wind River Systems Inc
* Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/console.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <asm/prom.h>
static unsigned long base_addr;
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
#define ALTERA_JTAGUART_DATA_REG 0
#define ALTERA_JTAGUART_CONTROL_REG 4
#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
#define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
#define JUART_GET_CR() \
__builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG))
#define JUART_SET_CR(v) \
__builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v)
#define JUART_SET_TX(v) \
__builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v)
static void early_console_write(struct console *con, const char *s, unsigned n)
{
unsigned long status;
while (n-- && *s) {
while (((status = JUART_GET_CR())
& ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0)
return; /* no connection activity */
#endif
}
JUART_SET_TX(*s);
s++;
}
}
#elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
#define ALTERA_UART_TXDATA_REG 4
#define ALTERA_UART_STATUS_REG 8
#define ALTERA_UART_STATUS_TRDY 0x0040
#define UART_GET_SR() \
__builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG))
#define UART_SET_TX(v) \
__builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v)
static void early_console_putc(char c)
{
while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY))
;
UART_SET_TX(c);
}
static void early_console_write(struct console *con, const char *s, unsigned n)
{
while (n-- && *s) {
early_console_putc(*s);
if (*s == '\n')
early_console_putc('\r');
s++;
}
}
#else
# error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \
selected
#endif
static struct console early_console_prom = {
.name = "early",
.write = early_console_write,
.flags = CON_PRINTBUFFER | CON_BOOT,
.index = -1
};
void __init setup_early_printk(void)
{
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) || \
defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
base_addr = of_early_console();
#else
base_addr = 0;
#endif
if (!base_addr)
return;
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
/* Clear activity bit so BYPASS doesn't stall if we've used JTAG for
* downloading the kernel. This might cause early data to be lost even
* if the JTAG terminal is running.
*/
JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK);
#endif
early_console = &early_console_prom;
register_console(early_console);
pr_info("early_console initialized at 0x%08lx\n", base_addr);
}

View File

@ -121,7 +121,11 @@ trap_table:
.word instruction_trap /* 27 */
.word instruction_trap /* 28 */
.word instruction_trap /* 29 */
.word instruction_trap /* 30 */
#ifdef CONFIG_KGDB
.word handle_kgdb_breakpoint /* 30 KGDB breakpoint */
#else
.word instruction_trap /* 30 */
#endif
.word handle_breakpoint /* 31 */
.text
@ -445,6 +449,12 @@ handle_diverror:
call handle_diverror_c
br ret_from_exception
#ifdef CONFIG_KGDB
handle_kgdb_breakpoint:
call kgdb_breakpoint_c
br ret_from_exception
#endif
/*
* Beware - when entering resume, prev (the current task) is
* in r4, next (the new task) is in r5, don't change these

171
arch/nios2/kernel/kgdb.c Normal file
View File

@ -0,0 +1,171 @@
/*
* Nios2 KGDB support
*
* Copyright (C) 2015 Altera Corporation
* Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
*
* Based on the code posted by Kazuyasu on the Altera Forum at:
* http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <linux/ptrace.h>
#include <linux/kgdb.h>
#include <linux/kdebug.h>
#include <linux/io.h>
static int wait_for_remote_debugger;
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
{
{ "zero", GDB_SIZEOF_REG, -1 },
{ "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, r1) },
{ "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r2) },
{ "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r3) },
{ "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r4) },
{ "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r5) },
{ "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r6) },
{ "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r7) },
{ "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r8) },
{ "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r9) },
{ "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10) },
{ "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11) },
{ "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12) },
{ "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13) },
{ "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14) },
{ "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15) },
{ "r16", GDB_SIZEOF_REG, -1 },
{ "r17", GDB_SIZEOF_REG, -1 },
{ "r18", GDB_SIZEOF_REG, -1 },
{ "r19", GDB_SIZEOF_REG, -1 },
{ "r20", GDB_SIZEOF_REG, -1 },
{ "r21", GDB_SIZEOF_REG, -1 },
{ "r22", GDB_SIZEOF_REG, -1 },
{ "r23", GDB_SIZEOF_REG, -1 },
{ "et", GDB_SIZEOF_REG, -1 },
{ "bt", GDB_SIZEOF_REG, -1 },
{ "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp) },
{ "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) },
{ "fp", GDB_SIZEOF_REG, offsetof(struct pt_regs, fp) },
{ "ea", GDB_SIZEOF_REG, -1 },
{ "ba", GDB_SIZEOF_REG, -1 },
{ "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, ra) },
{ "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, ea) },
{ "status", GDB_SIZEOF_REG, -1 },
{ "estatus", GDB_SIZEOF_REG, offsetof(struct pt_regs, estatus) },
{ "bstatus", GDB_SIZEOF_REG, -1 },
{ "ienable", GDB_SIZEOF_REG, -1 },
{ "ipending", GDB_SIZEOF_REG, -1},
{ "cpuid", GDB_SIZEOF_REG, -1 },
{ "ctl6", GDB_SIZEOF_REG, -1 },
{ "exception", GDB_SIZEOF_REG, -1 },
{ "pteaddr", GDB_SIZEOF_REG, -1 },
{ "tlbacc", GDB_SIZEOF_REG, -1 },
{ "tlbmisc", GDB_SIZEOF_REG, -1 },
{ "eccinj", GDB_SIZEOF_REG, -1 },
{ "badaddr", GDB_SIZEOF_REG, -1 },
{ "config", GDB_SIZEOF_REG, -1 },
{ "mpubase", GDB_SIZEOF_REG, -1 },
{ "mpuacc", GDB_SIZEOF_REG, -1 },
};
char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
{
if (regno >= DBG_MAX_REG_NUM || regno < 0)
return NULL;
if (dbg_reg_def[regno].offset != -1)
memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
dbg_reg_def[regno].size);
else
memset(mem, 0, dbg_reg_def[regno].size);
return dbg_reg_def[regno].name;
}
int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
{
if (regno >= DBG_MAX_REG_NUM || regno < 0)
return -EINVAL;
if (dbg_reg_def[regno].offset != -1)
memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
dbg_reg_def[regno].size);
return 0;
}
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
memset((char *)gdb_regs, 0, NUMREGBYTES);
gdb_regs[GDB_SP] = p->thread.kregs->sp;
gdb_regs[GDB_PC] = p->thread.kregs->ea;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
{
regs->ea = pc;
}
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
char *remcom_in_buffer, char *remcom_out_buffer,
struct pt_regs *regs)
{
char *ptr;
unsigned long addr;
switch (remcom_in_buffer[0]) {
case 's':
case 'c':
/* handle the optional parameters */
ptr = &remcom_in_buffer[1];
if (kgdb_hex2long(&ptr, &addr))
regs->ea = addr;
return 0;
}
return -1; /* this means that we do not want to exit from the handler */
}
asmlinkage void kgdb_breakpoint_c(struct pt_regs *regs)
{
/*
* The breakpoint entry code has moved the PC on by 4 bytes, so we must
* move it back. This could be done on the host but we do it here
*/
if (!wait_for_remote_debugger)
regs->ea -= 4;
else /* pass the first trap 30 code */
wait_for_remote_debugger = 0;
kgdb_handle_exception(30, SIGTRAP, 0, regs);
}
int kgdb_arch_init(void)
{
wait_for_remote_debugger = 1;
return 0;
}
void kgdb_arch_exit(void)
{
/* Nothing to do */
}
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: trap 30 */
.gdb_bpt_instr = { 0xba, 0x6f, 0x3b, 0x00 },
};

View File

@ -1,7 +1,7 @@
/*
* Device tree support
*
* Copyright (C) 2013 Altera Corporation
* Copyright (C) 2013, 2015 Altera Corporation
* Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
*
* Based on MIPS support for CONFIG_OF device tree support
@ -30,6 +30,7 @@
#include <linux/of_fdt.h>
#include <linux/io.h>
#include <asm/prom.h>
#include <asm/sections.h>
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
@ -63,3 +64,52 @@ void __init early_init_devtree(void *params)
early_init_dt_scan(params);
}
#ifdef CONFIG_EARLY_PRINTK
static int __init early_init_dt_scan_serial(unsigned long node,
const char *uname, int depth, void *data)
{
u64 *addr64 = (u64 *) data;
const char *p;
/* only consider serial nodes */
if (strncmp(uname, "serial", 6) != 0)
return 0;
p = of_get_flat_dt_prop(node, "compatible", NULL);
if (!p)
return 0;
/*
* We found an altera_jtaguart but it wasn't configured for console, so
* skip it.
*/
#ifndef CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE
if (strncmp(p, "altr,juart", 10) == 0)
return 0;
#endif
/*
* Same for altera_uart.
*/
#ifndef CONFIG_SERIAL_ALTERA_UART_CONSOLE
if (strncmp(p, "altr,uart", 9) == 0)
return 0;
#endif
*addr64 = fdt_translate_address((const void *)initial_boot_params,
node);
return *addr64 == OF_BAD_ADDR ? 0 : 1;
}
unsigned long __init of_early_console(void)
{
u64 base = 0;
if (of_scan_flat_dt(early_init_dt_scan_serial, &base))
return (u32)ioremap(base, 32);
else
return 0;
}
#endif /* CONFIG_EARLY_PRINTK */

View File

@ -139,6 +139,10 @@ void __init setup_arch(char **cmdline_p)
console_verbose();
#ifdef CONFIG_EARLY_PRINTK
setup_early_printk();
#endif
memory_start = PAGE_ALIGN((unsigned long)__pa(_end));
memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size;

View File

@ -47,7 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
struct mm_struct *mm = tsk->mm;
int code = SEGV_MAPERR;
int fault;
unsigned int flags = 0;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
cause >>= 2;
@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
if (!down_read_trylock(&mm->mmap_sem)) {
if (!user_mode(regs) && !search_exception_tables(regs->ea))
goto bad_area_nosemaphore;
retry:
down_read(&mm->mmap_sem);
}
@ -132,6 +133,10 @@ survive:
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, flags);
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
return;
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@ -141,10 +146,32 @@ survive:
goto do_sigbus;
BUG();
}
if (fault & VM_FAULT_MAJOR)
tsk->maj_flt++;
else
tsk->min_flt++;
/*
* Major/minor page fault accounting is only done on the
* initial attempt. If we go through a retry, it is extremely
* likely that the page will be found in page cache at that point.
*/
if (flags & FAULT_FLAG_ALLOW_RETRY) {
if (fault & VM_FAULT_MAJOR)
current->maj_flt++;
else
current->min_flt++;
if (fault & VM_FAULT_RETRY) {
/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
* of starvation. */
flags &= ~FAULT_FLAG_ALLOW_RETRY;
flags |= FAULT_FLAG_TRIED;
/*
* No need to up_read(&mm->mmap_sem) as we would
* have already released it in __lock_page_or_retry
* in mm/filemap.c.
*/
goto retry;
}
}
up_read(&mm->mmap_sem);
return;