reserve= [KNL,BUGS] Force the kernel to ignore some iomem area
+ reservetop= [IA-32]
+ Format: nn[KMG]
+ Reserves a hole at the top of the kernel virtual
+ address space.
+
resume= [SWSUSP]
Specify the partition device for software suspend
Reading from this file will display the current image size limit, which
is set to 500 MB by default.
+
+/sys/power/pm_trace controls the code which saves the last PM event point in
+the RTC across reboots, so that you can debug a machine that just hangs
+during suspend (or more commonly, during resume). Namely, the RTC is only
+used to save the last PM event point if this file contains '1'. Initially it
+contains '0' which may be changed to '1' by writing a string representing a
+nonzero integer into it.
+
+To use this debugging feature you should attempt to suspend the machine, then
+reboot it and run
+
+ dmesg -s 1000000 | grep 'hash matches'
+
+CAUTION: Using it will cause your machine's real-time (CMOS) clock to be
+set to a random invalid time after a resume.
- drop-caches
- zone_reclaim_mode
- min_unmapped_ratio
+- min_slab_ratio
- panic_on_oom
==============================================================
1 = Zone reclaim on
2 = Zone reclaim writes dirty pages out
4 = Zone reclaim swaps pages
-8 = Also do a global slab reclaim pass
zone_reclaim_mode is set during bootup to 1 if it is determined that pages
from remote zones will cause a measurable performance reduction. The
node unless explicitly overridden by memory policies or cpuset
configurations.
-It may be advisable to allow slab reclaim if the system makes heavy
-use of files and builds up large slab caches. However, the slab
-shrink operation is global, may take a long time and free slabs
-in all nodes of the system.
-
=============================================================
min_unmapped_ratio:
This is available only on NUMA kernels.
-A percentage of the file backed pages in each zone. Zone reclaim will only
+A percentage of the total pages in each zone. Zone reclaim will only
occur if more than this percentage of pages are file backed and unmapped.
This is to insure that a minimal amount of local pages is still available for
file I/O even if the node is overallocated.
=============================================================
+min_slab_ratio:
+
+This is available only on NUMA kernels.
+
+A percentage of the total pages in each zone. On Zone reclaim
+(fallback from the local zone occurs) slabs will be reclaimed if more
+than this percentage of pages in a zone are reclaimable slab pages.
+This insures that the slab growth stays under control even in NUMA
+systems that rarely perform global reclaim.
+
+The default is 5 percent.
+
+Note that slab reclaim is triggered in a per zone / node fashion.
+The process of reclaiming slab memory is currently not node specific
+and may not be fast.
+
+=============================================================
+
panic_on_oom
This enables or disables panic on out-of-memory feature. If this is set to 1,
T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
S: Maintained
+AVR32 ARCHITECTURE
+P: Atmel AVR32 Support Team
+M: avr32@atmel.com
+P: Haavard Skinnemoen
+M: hskinnemoen@atmel.com
+W: http://www.atmel.com/products/AVR32/
+W: http://avr32linux.org/
+W: http://avrfreaks.net/
+S: Supported
+
+AVR32/AT32AP MACHINE SUPPORT
+P: Atmel AVR32 Support Team
+M: avr32@atmel.com
+P: Haavard Skinnemoen
+M: hskinnemoen@atmel.com
+S: Supported
+
AX.25 NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
config ALPHA_EV56
prompt "EV56 CPU (speed >= 333MHz)?"
- depends on ALPHA_NORITAKE && ALPHA_PRIMO
+ depends on ALPHA_NORITAKE || ALPHA_PRIMO
config ALPHA_EV56
prompt "EV56 CPU (speed >= 400MHz)?"
void
paging_init(void)
{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
unsigned long dma_pfn, high_pfn;
dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
* Free the page table, if there was one.
*/
if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
- pte_free_kernel(pmd_page_kernel(pmd));
+ pte_free_kernel(pmd_page_vaddr(pmd));
}
addr += PGDIR_SIZE;
--- /dev/null
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux Kernel Configuration"
+
+config AVR32
+ bool
+ default y
+ # With EMBEDDED=n, we get lots of stuff automatically selected
+ # that we usually don't need on AVR32.
+ select EMBEDDED
+ help
+ AVR32 is a high-performance 32-bit RISC microprocessor core,
+ designed for cost-sensitive embedded applications, with particular
+ emphasis on low power consumption and high code density.
+
+ There is an AVR32 Linux project with a web page at
+ http://avr32linux.org/.
+
+config UID16
+ bool
+
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config HARDIRQS_SW_RESEND
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+config GENERIC_TIME
+ bool
+ default y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config GENERIC_BUST_SPINLOCK
+ bool
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+source "init/Kconfig"
+
+menu "System Type and features"
+
+config SUBARCH_AVR32B
+ bool
+config MMU
+ bool
+config PERFORMANCE_COUNTERS
+ bool
+
+config PLATFORM_AT32AP
+ bool
+ select SUBARCH_AVR32B
+ select MMU
+ select PERFORMANCE_COUNTERS
+
+choice
+ prompt "AVR32 CPU type"
+ default CPU_AT32AP7000
+
+config CPU_AT32AP7000
+ bool "AT32AP7000"
+ select PLATFORM_AT32AP
+endchoice
+
+#
+# CPU Daughterboards for ATSTK1000
+config BOARD_ATSTK1002
+ bool
+
+choice
+ prompt "AVR32 board type"
+ default BOARD_ATSTK1000
+
+config BOARD_ATSTK1000
+ bool "ATSTK1000 evaluation board"
+ select BOARD_ATSTK1002 if CPU_AT32AP7000
+endchoice
+
+choice
+ prompt "Boot loader type"
+ default LOADER_U_BOOT
+
+config LOADER_U_BOOT
+ bool "U-Boot (or similar) bootloader"
+endchoice
+
+config LOAD_ADDRESS
+ hex
+ default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
+
+config ENTRY_ADDRESS
+ hex
+ default 0x90000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
+
+config PHYS_OFFSET
+ hex
+ default 0x10000000 if CPU_AT32AP7000=y
+
+source "kernel/Kconfig.preempt"
+
+config HAVE_ARCH_BOOTMEM_NODE
+ bool
+ default n
+
+config ARCH_HAVE_MEMORY_PRESENT
+ bool
+ default n
+
+config NEED_NODE_MEMMAP_SIZE
+ bool
+ default n
+
+config ARCH_FLATMEM_ENABLE
+ bool
+ default y
+
+config ARCH_DISCONTIGMEM_ENABLE
+ bool
+ default n
+
+config ARCH_SPARSEMEM_ENABLE
+ bool
+ default n
+
+source "mm/Kconfig"
+
+config OWNERSHIP_TRACE
+ bool "Ownership trace support"
+ default y
+ help
+ Say Y to generate an Ownership Trace message on every context switch,
+ enabling Nexus-compliant debuggers to keep track of the PID of the
+ currently executing task.
+
+# FPU emulation goes here
+
+source "kernel/Kconfig.hz"
+
+config CMDLINE
+ string "Default kernel command line"
+ default ""
+ help
+ If you don't have a boot loader capable of passing a command line string
+ to the kernel, you may specify one here. As a minimum, you should specify
+ the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
+
+endmenu
+
+menu "Bus options"
+
+config PCI
+ bool
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+endmenu
+
+menu "Executable file formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/avr32/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
--- /dev/null
+menu "Kernel hacking"
+
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
+source "lib/Kconfig.debug"
+
+config KPROBES
+ bool "Kprobes"
+ depends on DEBUG_KERNEL
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+endmenu
--- /dev/null
+#
+# 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.
+#
+# Copyright (C) 2004-2006 Atmel Corporation.
+
+# Default target when executing plain make
+.PHONY: all
+all: uImage vmlinux.elf linux.lst
+
+KBUILD_DEFCONFIG := atstk1002_defconfig
+
+CFLAGS += -pipe -fno-builtin -mno-pic
+AFLAGS += -mrelax -mno-pic
+CFLAGS_MODULE += -mno-relax
+LDFLAGS_vmlinux += --relax
+
+cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000
+
+CFLAGS += $(cpuflags-y)
+AFLAGS += $(cpuflags-y)
+
+CHECKFLAGS += -D__avr32__
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+head-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/head.o
+head-y += arch/avr32/kernel/head.o
+core-$(CONFIG_PLATFORM_AT32AP) += arch/avr32/mach-at32ap/
+core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
+core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
+core-y += arch/avr32/kernel/
+core-y += arch/avr32/mm/
+libs-y += arch/avr32/lib/ #$(LIBGCC)
+
+archincdir-$(CONFIG_PLATFORM_AT32AP) := arch-at32ap
+
+include/asm-avr32/.arch: $(wildcard include/config/platform/*.h) include/config/auto.conf
+ @echo ' SYMLINK include/asm-avr32/arch -> include/asm-avr32/$(archincdir-y)'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-avr32
+ $(Q)ln -fsn $(srctree)/include/asm-avr32/$(archincdir-y) include/asm-avr32/arch
+else
+ $(Q)ln -fsn $(archincdir-y) include/asm-avr32/arch
+endif
+ @touch $@
+
+archprepare: include/asm-avr32/.arch
+
+BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec
+
+.PHONY: $(BOOT_TARGETS) install
+
+boot := arch/$(ARCH)/boot/images
+
+ KBUILD_IMAGE := $(boot)/uImage
+vmlinux.elf: KBUILD_IMAGE := $(boot)/vmlinux.elf
+vmlinux.cso: KBUILD_IMAGE := $(boot)/vmlinux.cso
+uImage.srec: KBUILD_IMAGE := $(boot)/uImage.srec
+uImage: KBUILD_IMAGE := $(boot)/uImage
+
+quiet_cmd_listing = LST $@
+ cmd_listing = avr32-linux-objdump $(OBJDUMPFLAGS) -lS $< > $@
+quiet_cmd_disasm = DIS $@
+ cmd_disasm = avr32-linux-objdump $(OBJDUMPFLAGS) -d $< > $@
+
+vmlinux.elf vmlinux.bin uImage.srec uImage vmlinux.cso: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+install: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
+
+linux.s: vmlinux
+ $(call if_changed,disasm)
+
+linux.lst: vmlinux
+ $(call if_changed,listing)
+
+define archhelp
+ @echo '* vmlinux.elf - ELF image with load address 0'
+ @echo ' vmlinux.cso - PathFinder CSO image'
+ @echo ' uImage - Create a bootable image for U-Boot'
+endef
--- /dev/null
+obj-y += setup.o spi.o flash.o
+obj-$(CONFIG_BOARD_ATSTK1002) += atstk1002.o
--- /dev/null
+/*
+ * ATSTK1002 daughterboard-specific init code
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+
+#include <asm/arch/board.h>
+
+struct eth_platform_data __initdata eth0_data = {
+ .valid = 1,
+ .mii_phy_addr = 0x10,
+ .is_rmii = 0,
+ .hw_addr = { 0x6a, 0x87, 0x71, 0x14, 0xcd, 0xcb },
+};
+
+extern struct lcdc_platform_data atstk1000_fb0_data;
+
+static int __init atstk1002_init(void)
+{
+ at32_add_system_devices();
+
+ at32_add_device_usart(1); /* /dev/ttyS0 */
+ at32_add_device_usart(2); /* /dev/ttyS1 */
+ at32_add_device_usart(3); /* /dev/ttyS2 */
+
+ at32_add_device_eth(0, ð0_data);
+ at32_add_device_spi(0);
+ at32_add_device_lcdc(0, &atstk1000_fb0_data);
+
+ return 0;
+}
+postcore_initcall(atstk1002_init);
--- /dev/null
+/*
+ * ATSTK1000 board-specific flash initialization
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/arch/smc.h>
+
+static struct smc_config flash_config __initdata = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 40,
+ .ncs_write_setup = 0,
+ .nwe_setup = 10,
+
+ .ncs_read_pulse = 80,
+ .nrd_pulse = 40,
+ .ncs_write_pulse = 65,
+ .nwe_pulse = 55,
+
+ .read_cycle = 120,
+ .write_cycle = 120,
+
+ .bus_width = 2,
+ .nrd_controlled = 1,
+ .nwe_controlled = 1,
+ .byte_write = 1,
+};
+
+static struct mtd_partition flash_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0x00000000,
+ .size = 0x00020000, /* 128 KiB */
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "root",
+ .offset = 0x00020000,
+ .size = 0x007d0000,
+ },
+ {
+ .name = "env",
+ .offset = 0x007f0000,
+ .size = 0x00010000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct physmap_flash_data flash_data = {
+ .width = 2,
+ .nr_parts = ARRAY_SIZE(flash_parts),
+ .parts = flash_parts,
+};
+
+static struct resource flash_resource = {
+ .start = 0x00000000,
+ .end = 0x007fffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .resource = &flash_resource,
+ .num_resources = 1,
+ .dev = {
+ .platform_data = &flash_data,
+ },
+};
+
+/* This needs to be called after the SMC has been initialized */
+static int __init atstk1000_flash_init(void)
+{
+ int ret;
+
+ ret = smc_set_configuration(0, &flash_config);
+ if (ret < 0) {
+ printk(KERN_ERR "atstk1000: failed to set NOR flash timing\n");
+ return ret;
+ }
+
+ platform_device_register(&flash_device);
+
+ return 0;
+}
+device_initcall(atstk1000_flash_init);
--- /dev/null
+/*
+ * ATSTK1000 board-specific setup code.
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+
+#include <asm/setup.h>
+
+#include <asm/arch/board.h>
+
+/* Initialized by bootloader-specific startup code. */
+struct tag *bootloader_tags __initdata;
+
+struct lcdc_platform_data __initdata atstk1000_fb0_data;
+
+asmlinkage void __init board_early_init(void)
+{
+ extern void sdram_init(void);
+
+#ifdef CONFIG_LOADER_STANDALONE
+ sdram_init();
+#endif
+}
+
+void __init board_setup_fbmem(unsigned long fbmem_start,
+ unsigned long fbmem_size)
+{
+ if (!fbmem_size)
+ return;
+
+ if (!fbmem_start) {
+ void *fbmem;
+
+ fbmem = alloc_bootmem_low_pages(fbmem_size);
+ fbmem_start = __pa(fbmem);
+ } else {
+ pg_data_t *pgdat;
+
+ for_each_online_pgdat(pgdat) {
+ if (fbmem_start >= pgdat->bdata->node_boot_start
+ && fbmem_start <= pgdat->bdata->node_low_pfn)
+ reserve_bootmem_node(pgdat, fbmem_start,
+ fbmem_size);
+ }
+ }
+
+ printk("%luKiB framebuffer memory at address 0x%08lx\n",
+ fbmem_size >> 10, fbmem_start);
+ atstk1000_fb0_data.fbmem_start = fbmem_start;
+ atstk1000_fb0_data.fbmem_size = fbmem_size;
+}
--- /dev/null
+/*
+ * ATSTK1000 SPI devices
+ *
+ * Copyright (C) 2005 Atmel Norway
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "ltv350qv",
+ .max_speed_hz = 16000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ },
+};
+
+static int board_init_spi(void)
+{
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ return 0;
+}
+arch_initcall(board_init_spi);
--- /dev/null
+#
+# Copyright (C) 2004-2006 Atmel Corporation
+#
+# 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.
+#
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+extra-y := vmlinux.bin vmlinux.gz
+
+OBJCOPYFLAGS_vmlinux.bin := -O binary
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A avr32 -O linux -T kernel \
+ -C gzip -a $(CONFIG_LOAD_ADDRESS) -e $(CONFIG_ENTRY_ADDRESS) \
+ -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
+targets += uImage uImage.srec
+$(obj)/uImage: $(obj)/vmlinux.gz
+ $(call if_changed,uimage)
+ @echo ' Image $@ is ready'
+
+OBJCOPYFLAGS_uImage.srec := -I binary -O srec
+$(obj)/uImage.srec: $(obj)/uImage
+ $(call if_changed,objcopy)
+
+OBJCOPYFLAGS_vmlinux.elf := --change-section-lma .text-0x80000000 \
+ --change-section-lma __ex_table-0x80000000 \
+ --change-section-lma .rodata-0x80000000 \
+ --change-section-lma .data-0x80000000 \
+ --change-section-lma .init-0x80000000 \
+ --change-section-lma .bss-0x80000000 \
+ --change-section-lma .initrd-0x80000000 \
+ --change-section-lma __param-0x80000000 \
+ --change-section-lma __ksymtab-0x80000000 \
+ --change-section-lma __ksymtab_gpl-0x80000000 \
+ --change-section-lma __kcrctab-0x80000000 \
+ --change-section-lma __kcrctab_gpl-0x80000000 \
+ --change-section-lma __ksymtab_strings-0x80000000 \
+ --change-section-lma .got-0x80000000 \
+ --set-start 0xa0000000
+$(obj)/vmlinux.elf: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+quiet_cmd_sfdwarf = SFDWARF $@
+ cmd_sfdwarf = sfdwarf $< TO $@ GNUAVR IW $(SFDWARF_FLAGS) > $(obj)/sfdwarf.log
+
+$(obj)/vmlinux.cso: $(obj)/vmlinux.elf FORCE
+ $(call if_changed,sfdwarf)
+
+install: $(BOOTIMAGE)
+ sh $(srctree)/install-kernel.sh $<
+
+# Generated files to be removed upon make clean
+clean-files := vmlinux* uImage uImage.srec
--- /dev/null
+extra-y := head.o
+
+obj-y := empty.o
--- /dev/null
+/* Empty file */
--- /dev/null
+/*
+ * Startup code for use with the u-boot bootloader.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/setup.h>
+
+ /*
+ * The kernel is loaded where we want it to be and all caches
+ * have just been flushed. We get two parameters from u-boot:
+ *
+ * r12 contains a magic number (ATAG_MAGIC)
+ * r11 points to a tag table providing information about
+ * the system.
+ */
+ .section .init.text,"ax"
+ .global _start
+_start:
+ /* Check if the boot loader actually provided a tag table */
+ lddpc r0, magic_number
+ cp.w r12, r0
+ brne no_tag_table
+
+ /* Initialize .bss */
+ lddpc r2, bss_start_addr
+ lddpc r3, end_addr
+ mov r0, 0
+ mov r1, 0
+1: st.d r2++, r0
+ cp r2, r3
+ brlo 1b
+
+ /*
+ * Save the tag table address for later use. This must be done
+ * _after_ .bss has been initialized...
+ */
+ lddpc r0, tag_table_addr
+ st.w r0[0], r11
+
+ /* Jump to loader-independent setup code */
+ rjmp kernel_entry
+
+ .align 2
+magic_number:
+ .long ATAG_MAGIC
+tag_table_addr:
+ .long bootloader_tags
+bss_start_addr:
+ .long __bss_start
+end_addr:
+ .long _end
+
+no_tag_table:
+ sub r12, pc, (. - 2f)
+ bral panic
+2: .asciz "Boot loader didn't provide correct magic number\n"
--- /dev/null
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-rc1
+# Tue Jul 11 12:41:36 2006
+#
+CONFIG_AVR32=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+# CONFIG_SLAB is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System Type and features
+#
+CONFIG_SUBARCH_AVR32B=y
+CONFIG_MMU=y
+CONFIG_PERFORMANCE_COUNTERS=y
+CONFIG_PLATFORM_AT32AP=y
+CONFIG_CPU_AT32AP7000=y
+CONFIG_BOARD_ATSTK1002=y
+CONFIG_BOARD_ATSTK1000=y
+CONFIG_LOADER_U_BOOT=y
+CONFIG_LOAD_ADDRESS=0x10000000
+CONFIG_ENTRY_ADDRESS=0x90000000
+CONFIG_PHYS_OFFSET=0x10000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HAVE_ARCH_BOOTMEM_NODE is not set
+# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set
+# CONFIG_NEED_NODE_MEMMAP_SIZE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_SPARSEMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_OWNERSHIP_TRACE is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_CMDLINE=""
+
+#
+# Bus options
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACB=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=m
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=m
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SIDSA=m
+CONFIG_FB_SIDSA_DEFAULT_BPP=24
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+CONFIG_LCD_LTV350QV=m
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_KPROBES=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
--- /dev/null
+#
+# Makefile for the Linux/AVR32 kernel.
+#
+
+extra-y := head.o vmlinux.lds
+
+obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
+obj-y += syscall_table.o syscall-stubs.o irq.o
+obj-y += setup.o traps.o semaphore.o ptrace.o
+obj-y += signal.o sys_avr32.o process.o time.o
+obj-y += init_task.o switch_to.o cpu.o
+obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
+obj-$(CONFIG_KPROBES) += kprobes.o
+
+USE_STANDARD_AS_RULE := true
+
+%.lds: %.lds.c FORCE
+ $(call if_changed_dep,cpp_lds_S)
--- /dev/null
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/thread_info.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+ DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+ OFFSET(TI_task, thread_info, task);
+ OFFSET(TI_exec_domain, thread_info, exec_domain);
+ OFFSET(TI_flags, thread_info, flags);
+ OFFSET(TI_cpu, thread_info, cpu);
+ OFFSET(TI_preempt_count, thread_info, preempt_count);
+ OFFSET(TI_restart_block, thread_info, restart_block);
+}
--- /dev/null
+/*
+ * Export AVR32-specific functions for loadable modules.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+
+#include <asm/checksum.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+
+/*
+ * GCC functions
+ */
+extern unsigned long long __avr32_lsl64(unsigned long long u, unsigned long b);
+extern unsigned long long __avr32_lsr64(unsigned long long u, unsigned long b);
+extern unsigned long long __avr32_asr64(unsigned long long u, unsigned long b);
+EXPORT_SYMBOL(__avr32_lsl64);
+EXPORT_SYMBOL(__avr32_lsr64);
+EXPORT_SYMBOL(__avr32_asr64);
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+
+/*
+ * Userspace access stuff.
+ */
+EXPORT_SYMBOL(copy_from_user);
+EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_generic);
+
+/* Delay loops (lib/delay.S) */
+EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__const_udelay);
+
+/* Bit operations (lib/findbit.S) */
+EXPORT_SYMBOL(find_first_zero_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(find_first_bit);
+EXPORT_SYMBOL(find_next_bit);
+EXPORT_SYMBOL(generic_find_next_zero_le_bit);
--- /dev/null
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+#include <linux/param.h>
+#include <linux/errno.h>
+
+#include <asm/setup.h>
+#include <asm/sysreg.h>
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+#ifdef CONFIG_PERFORMANCE_COUNTERS
+
+/*
+ * XXX: If/when a SMP-capable implementation of AVR32 will ever be
+ * made, we must make sure that the code executes on the correct CPU.
+ */
+static ssize_t show_pc0event(struct sys_device *dev, char *buf)
+{
+ unsigned long pccr;
+
+ pccr = sysreg_read(PCCR);
+ return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
+}
+static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf || val > 0x3f)
+ return -EINVAL;
+ val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff);
+ sysreg_write(PCCR, val);
+ return count;
+}
+static ssize_t show_pc0count(struct sys_device *dev, char *buf)
+{
+ unsigned long pcnt0;
+
+ pcnt0 = sysreg_read(PCNT0);
+ return sprintf(buf, "%lu\n", pcnt0);
+}
+static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ sysreg_write(PCNT0, val);
+
+ return count;
+}
+
+static ssize_t show_pc1event(struct sys_device *dev, char *buf)
+{
+ unsigned long pccr;
+
+ pccr = sysreg_read(PCCR);
+ return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
+}
+static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf || val > 0x3f)
+ return -EINVAL;
+ val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff);
+ sysreg_write(PCCR, val);
+ return count;
+}
+static ssize_t show_pc1count(struct sys_device *dev, char *buf)
+{
+ unsigned long pcnt1;
+
+ pcnt1 = sysreg_read(PCNT1);
+ return sprintf(buf, "%lu\n", pcnt1);
+}
+static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ sysreg_write(PCNT1, val);
+
+ return count;
+}
+
+static ssize_t show_pccycles(struct sys_device *dev, char *buf)
+{
+ unsigned long pccnt;
+
+ pccnt = sysreg_read(PCCNT);
+ return sprintf(buf, "%lu\n", pccnt);
+}
+static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ sysreg_write(PCCNT, val);
+
+ return count;
+}
+
+static ssize_t show_pcenable(struct sys_device *dev, char *buf)
+{
+ unsigned long pccr;
+
+ pccr = sysreg_read(PCCR);
+ return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
+}
+static ssize_t store_pcenable(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned long pccr, val;
+ char *endp;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+ if (val)
+ val = 1;
+
+ pccr = sysreg_read(PCCR);
+ pccr = (pccr & ~1UL) | val;
+ sysreg_write(PCCR, pccr);
+
+ return count;
+}
+
+static SYSDEV_ATTR(pc0event, 0600, show_pc0event, store_pc0event);
+static SYSDEV_ATTR(pc0count, 0600, show_pc0count, store_pc0count);
+static SYSDEV_ATTR(pc1event, 0600, show_pc1event, store_pc1event);
+static SYSDEV_ATTR(pc1count, 0600, show_pc1count, store_pc1count);
+static SYSDEV_ATTR(pccycles, 0600, show_pccycles, store_pccycles);
+static SYSDEV_ATTR(pcenable, 0600, show_pcenable, store_pcenable);
+
+#endif /* CONFIG_PERFORMANCE_COUNTERS */
+
+static int __init topology_init(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ register_cpu(c, cpu);
+
+#ifdef CONFIG_PERFORMANCE_COUNTERS
+ sysdev_create_file(&c->sysdev, &attr_pc0event);
+ sysdev_create_file(&c->sysdev, &attr_pc0count);
+ sysdev_create_file(&c->sysdev, &attr_pc1event);
+ sysdev_create_file(&c->sysdev, &attr_pc1count);
+ sysdev_create_file(&c->sysdev, &attr_pccycles);
+ sysdev_create_file(&c->sysdev, &attr_pcenable);
+#endif
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
+
+static const char *cpu_names[] = {
+ "Morgan",
+ "AP7000",
+};
+#define NR_CPU_NAMES ARRAY_SIZE(cpu_names)
+
+static const char *arch_names[] = {
+ "AVR32A",
+ "AVR32B",
+};
+#define NR_ARCH_NAMES ARRAY_SIZE(arch_names)
+
+static const char *mmu_types[] = {
+ "No MMU",
+ "ITLB and DTLB",
+ "Shared TLB",
+ "MPU"
+};
+
+void __init setup_processor(void)
+{
+ unsigned long config0, config1;
+ unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type;
+ unsigned tmp;
+
+ config0 = sysreg_read(CONFIG0); /* 0x0000013e; */
+ config1 = sysreg_read(CONFIG1); /* 0x01f689a2; */
+ cpu_id = config0 >> 24;
+ cpu_rev = (config0 >> 16) & 0xff;
+ arch_id = (config0 >> 13) & 0x07;
+ arch_rev = (config0 >> 10) & 0x07;
+ mmu_type = (config0 >> 7) & 0x03;
+
+ boot_cpu_data.arch_type = arch_id;
+ boot_cpu_data.cpu_type = cpu_id;
+ boot_cpu_data.arch_revision = arch_rev;
+ boot_cpu_data.cpu_revision = cpu_rev;
+ boot_cpu_data.tlb_config = mmu_type;
+
+ tmp = (config1 >> 13) & 0x07;
+ if (tmp) {
+ boot_cpu_data.icache.ways = 1 << ((config1 >> 10) & 0x07);
+ boot_cpu_data.icache.sets = 1 << ((config1 >> 16) & 0x0f);
+ boot_cpu_data.icache.linesz = 1 << (tmp + 1);
+ }
+ tmp = (config1 >> 3) & 0x07;
+ if (tmp) {
+ boot_cpu_data.dcache.ways = 1 << (config1 & 0x07);
+ boot_cpu_data.dcache.sets = 1 << ((config1 >> 6) & 0x0f);
+ boot_cpu_data.dcache.linesz = 1 << (tmp + 1);
+ }
+
+ if ((cpu_id >= NR_CPU_NAMES) || (arch_id >= NR_ARCH_NAMES)) {
+ printk ("Unknown CPU configuration (ID %02x, arch %02x), "
+ "continuing anyway...\n",
+ cpu_id, arch_id);
+ return;
+ }
+
+ printk ("CPU: %s [%02x] revision %d (%s revision %d)\n",
+ cpu_names[cpu_id], cpu_id, cpu_rev,
+ arch_names[arch_id], arch_rev);
+ printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]);
+ printk ("CPU: features:");
+ if (config0 & (1 << 6))
+ printk(" fpu");
+ if (config0 & (1 << 5))
+ printk(" java");
+ if (config0 & (1 << 4))
+ printk(" perfctr");
+ if (config0 & (1 << 3))
+ printk(" ocd");
+ printk("\n");
+}
+
+#ifdef CONFIG_PROC_FS
+static int c_show(struct seq_file *m, void *v)
+{
+ unsigned int icache_size, dcache_size;
+ unsigned int cpu = smp_processor_id();
+
+ icache_size = boot_cpu_data.icache.ways *
+ boot_cpu_data.icache.sets *
+ boot_cpu_data.icache.linesz;
+ dcache_size = boot_cpu_data.dcache.ways *
+ boot_cpu_data.dcache.sets *
+ boot_cpu_data.dcache.linesz;
+
+ seq_printf(m, "processor\t: %d\n", cpu);
+
+ if (boot_cpu_data.arch_type < NR_ARCH_NAMES)
+ seq_printf(m, "cpu family\t: %s revision %d\n",
+ arch_names[boot_cpu_data.arch_type],
+ boot_cpu_data.arch_revision);
+ if (boot_cpu_data.cpu_type < NR_CPU_NAMES)
+ seq_printf(m, "cpu type\t: %s revision %d\n",
+ cpu_names[boot_cpu_data.cpu_type],
+ boot_cpu_data.cpu_revision);
+
+ seq_printf(m, "i-cache\t\t: %dK (%u ways x %u sets x %u)\n",
+ icache_size >> 10,
+ boot_cpu_data.icache.ways,
+ boot_cpu_data.icache.sets,
+ boot_cpu_data.icache.linesz);
+ seq_printf(m, "d-cache\t\t: %dK (%u ways x %u sets x %u)\n",
+ dcache_size >> 10,
+ boot_cpu_data.dcache.ways,
+ boot_cpu_data.dcache.sets,
+ boot_cpu_data.dcache.linesz);
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ boot_cpu_data.loops_per_jiffy / (500000/HZ),
+ (boot_cpu_data.loops_per_jiffy / (5000/HZ)) % 100);
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+
+}
+
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = c_show
+};
+#endif /* CONFIG_PROC_FS */
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This file contains the low-level entry-points into the kernel, that is,
+ * exception handlers, debug trap handlers, interrupt handlers and the
+ * system call handler.
+ */
+#include <linux/errno.h>
+
+#include <asm/asm.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
+#include <asm/ocd.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/sysreg.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+#ifdef CONFIG_PREEMPT
+# define preempt_stop mask_interrupts
+#else
+# define preempt_stop
+# define fault_resume_kernel fault_restore_all
+#endif
+
+#define __MASK(x) ((1 << (x)) - 1)
+#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
+ (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
+
+ .section .ex.text,"ax",@progbits
+ .align 2
+exception_vectors:
+ bral handle_critical
+ .align 2
+ bral handle_critical
+ .align 2
+ bral do_bus_error_write
+ .align 2
+ bral do_bus_error_read
+ .align 2
+ bral do_nmi_ll
+ .align 2
+ bral handle_address_fault
+ .align 2
+ bral handle_protection_fault
+ .align 2
+ bral handle_debug
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral do_fpe_ll
+ .align 2
+ bral do_illegal_opcode_ll
+ .align 2
+ bral handle_address_fault
+ .align 2
+ bral handle_address_fault
+ .align 2
+ bral handle_protection_fault
+ .align 2
+ bral handle_protection_fault
+ .align 2
+ bral do_dtlb_modified
+
+ /*
+ * r0 : PGD/PT/PTE
+ * r1 : Offending address
+ * r2 : Scratch register
+ * r3 : Cause (5, 12 or 13)
+ */
+#define tlbmiss_save pushm r0-r3
+#define tlbmiss_restore popm r0-r3
+
+ .section .tlbx.ex.text,"ax",@progbits
+ .global itlb_miss
+itlb_miss:
+ tlbmiss_save
+ rjmp tlb_miss_common
+
+ .section .tlbr.ex.text,"ax",@progbits
+dtlb_miss_read:
+ tlbmiss_save
+ rjmp tlb_miss_common
+
+ .section .tlbw.ex.text,"ax",@progbits
+dtlb_miss_write:
+ tlbmiss_save
+
+ .global tlb_miss_common
+tlb_miss_common:
+ mfsr r0, SYSREG_PTBR
+ mfsr r1, SYSREG_TLBEAR
+
+ /* Is it the vmalloc space? */
+ bld r1, 31
+ brcs handle_vmalloc_miss
+
+ /* First level lookup */
+pgtbl_lookup:
+ lsr r2, r1, PGDIR_SHIFT
+ ld.w r0, r0[r2 << 2]
+ bld r0, _PAGE_BIT_PRESENT
+ brcc page_table_not_present
+
+ /* TODO: Check access rights on page table if necessary */
+
+ /* Translate to virtual address in P1. */
+ andl r0, 0xf000
+ sbr r0, 31
+
+ /* Second level lookup */
+ lsl r1, (32 - PGDIR_SHIFT)
+ lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
+ add r2, r0, r1 << 2
+ ld.w r1, r2[0]
+ bld r1, _PAGE_BIT_PRESENT
+ brcc page_not_present
+
+ /* Mark the page as accessed */
+ sbr r1, _PAGE_BIT_ACCESSED
+ st.w r2[0], r1
+
+ /* Drop software flags */
+ andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
+ mtsr SYSREG_TLBELO, r1
+
+ /* Figure out which entry we want to replace */
+ mfsr r0, SYSREG_TLBARLO
+ clz r2, r0
+ brcc 1f
+ mov r1, -1 /* All entries have been accessed, */
+ mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */
+ mov r2, 0 /* and start at 0 */
+1: mfsr r1, SYSREG_MMUCR
+ lsl r2, 14
+ andl r1, 0x3fff, COH
+ or r1, r2
+ mtsr SYSREG_MMUCR, r1
+
+ tlbw
+
+ tlbmiss_restore
+ rete
+
+handle_vmalloc_miss:
+ /* Simply do the lookup in init's page table */
+ mov r0, lo(swapper_pg_dir)
+ orh r0, hi(swapper_pg_dir)
+ rjmp pgtbl_lookup
+
+
+ /* --- System Call --- */
+
+ .section .scall.text,"ax",@progbits
+system_call:
+ pushm r12 /* r12_orig */
+ stmts --sp, r0-lr
+ zero_fp
+ mfsr r0, SYSREG_RAR_SUP
+ mfsr r1, SYSREG_RSR_SUP
+ stm --sp, r0-r1
+
+ /* check for syscall tracing */
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ bld r1, TIF_SYSCALL_TRACE
+ brcs syscall_trace_enter
+
+syscall_trace_cont:
+ cp.w r8, NR_syscalls
+ brhs syscall_badsys
+
+ lddpc lr, syscall_table_addr
+ ld.w lr, lr[r8 << 2]
+ mov r8, r5 /* 5th argument (6th is pushed by stub) */
+ icall lr
+
+ .global syscall_return
+syscall_return:
+ get_thread_info r0
+ mask_interrupts /* make sure we don't miss an interrupt
+ setting need_resched or sigpending
+ between sampling and the rets */
+
+ /* Store the return value so that the correct value is loaded below */
+ stdsp sp[REG_R12], r12
+
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_ALLWORK_MASK, COH
+ brne syscall_exit_work
+
+syscall_exit_cont:
+ popm r8-r9
+ mtsr SYSREG_RAR_SUP, r8
+ mtsr SYSREG_RSR_SUP, r9
+ ldmts sp++, r0-lr
+ sub sp, -4 /* r12_orig */
+ rets
+
+ .align 2
+syscall_table_addr:
+ .long sys_call_table
+
+syscall_badsys:
+ mov r12, -ENOSYS
+ rjmp syscall_return
+
+ .global ret_from_fork
+ret_from_fork:
+ rcall schedule_tail
+
+ /* check for syscall tracing */
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_ALLWORK_MASK, COH
+ brne syscall_exit_work
+ rjmp syscall_exit_cont
+
+syscall_trace_enter:
+ pushm r8-r12
+ rcall syscall_trace
+ popm r8-r12
+ rjmp syscall_trace_cont
+
+syscall_exit_work:
+ bld r1, TIF_SYSCALL_TRACE
+ brcc 1f
+ unmask_interrupts
+ rcall syscall_trace
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+
+1: bld r1, TIF_NEED_RESCHED
+ brcc 2f
+ unmask_interrupts
+ rcall schedule
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
+ tst r1, r2
+ breq 3f
+ unmask_interrupts
+ mov r12, sp
+ mov r11, r0
+ rcall do_notify_resume
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+3: bld r1, TIF_BREAKPOINT
+ brcc syscall_exit_cont
+ mfsr r3, SYSREG_TLBEHI
+ lddsp r2, sp[REG_PC]
+ andl r3, 0xff, COH
+ lsl r3, 1
+ sbr r3, 30
+ sbr r3, 0
+ mtdr DBGREG_BWA2A, r2
+ mtdr DBGREG_BWC2A, r3
+ rjmp syscall_exit_cont
+
+
+ /* The slow path of the TLB miss handler */
+page_table_not_present:
+page_not_present:
+ tlbmiss_restore
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_page_fault
+ rjmp ret_from_exception
+
+ /* This function expects to find offending PC in SYSREG_RAR_EX */
+save_full_context_ex:
+ mfsr r8, SYSREG_RSR_EX
+ mov r12, r8
+ andh r8, (MODE_MASK >> 16), COH
+ mfsr r11, SYSREG_RAR_EX
+ brne 2f
+
+1: pushm r11, r12 /* PC and SR */
+ unmask_exceptions
+ ret r12
+
+2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
+ stdsp sp[4], r10 /* replace saved SP */
+ rjmp 1b
+
+ /* Low-level exception handlers */
+handle_critical:
+ pushm r12
+ pushm r0-r12
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_critical_exception
+
+ /* We should never get here... */
+bad_return:
+ sub r12, pc, (. - 1f)
+ bral panic
+ .align 2
+1: .asciz "Return from critical exception!"
+
+ .align 1
+do_bus_error_write:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mov r11, 1
+ rjmp 1f
+
+do_bus_error_read:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mov r11, 0
+1: mfsr r12, SYSREG_BEAR
+ mov r10, sp
+ rcall do_bus_error
+ rjmp ret_from_exception
+
+ .align 1
+do_nmi_ll:
+ sub sp, 4
+ stmts --sp, r0-lr
+ /* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_nmi
+ rjmp bad_return
+
+handle_address_fault:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_address_exception
+ rjmp ret_from_exception
+
+handle_protection_fault:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_page_fault
+ rjmp ret_from_exception
+
+ .align 1
+do_illegal_opcode_ll:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ mfsr r12, SYSREG_ECR
+ mov r11, sp
+ rcall do_illegal_opcode
+ rjmp ret_from_exception
+
+do_dtlb_modified:
+ pushm r0-r3
+ mfsr r1, SYSREG_TLBEAR
+ mfsr r0, SYSREG_PTBR
+ lsr r2, r1, PGDIR_SHIFT
+ ld.w r0, r0[r2 << 2]
+ lsl r1, (32 - PGDIR_SHIFT)
+ lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
+
+ /* Translate to virtual address in P1 */
+ andl r0, 0xf000
+ sbr r0, 31
+ add r2, r0, r1 << 2
+ ld.w r3, r2[0]
+ sbr r3, _PAGE_BIT_DIRTY
+ mov r0, r3
+ st.w r2[0], r3
+
+ /* The page table is up-to-date. Update the TLB entry as well */
+ andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
+ mtsr SYSREG_TLBELO, r0
+
+ /* MMUCR[DRP] is updated automatically, so let's go... */
+ tlbw
+
+ popm r0-r3
+ rete
+
+do_fpe_ll:
+ sub sp, 4
+ stmts --sp, r0-lr
+ rcall save_full_context_ex
+ unmask_interrupts
+ mov r12, 26
+ mov r11, sp
+ rcall do_fpe
+ rjmp ret_from_exception
+
+ret_from_exception:
+ mask_interrupts
+ lddsp r4, sp[REG_SR]
+ andh r4, (MODE_MASK >> 16), COH
+ brne fault_resume_kernel
+
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_WORK_MASK, COH
+ brne fault_exit_work
+
+fault_resume_user:
+ popm r8-r9
+ mask_exceptions
+ mtsr SYSREG_RAR_EX, r8
+ mtsr SYSREG_RSR_EX, r9
+ ldmts sp++, r0-lr
+ sub sp, -4
+ rete
+
+fault_resume_kernel:
+#ifdef CONFIG_PREEMPT
+ get_thread_info r0
+ ld.w r2, r0[TI_preempt_count]
+ cp.w r2, 0
+ brne 1f
+ ld.w r1, r0[TI_flags]
+ bld r1, TIF_NEED_RESCHED
+ brcc 1f
+ lddsp r4, sp[REG_SR]
+ bld r4, SYSREG_GM_OFFSET
+ brcs 1f
+ rcall preempt_schedule_irq
+1:
+#endif
+
+ popm r8-r9
+ mask_exceptions
+ mfsr r1, SYSREG_SR
+ mtsr SYSREG_RAR_EX, r8
+ mtsr SYSREG_RSR_EX, r9
+ popm lr
+ sub sp, -4 /* ignore SP */
+ popm r0-r12
+ sub sp, -4 /* ignore r12_orig */
+ rete
+
+irq_exit_work:
+ /* Switch to exception mode so that we can share the same code. */
+ mfsr r8, SYSREG_SR
+ cbr r8, SYSREG_M0_OFFSET
+ orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
+ mtsr SYSREG_SR, r8
+ sub pc, -2
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+
+fault_exit_work:
+ bld r1, TIF_NEED_RESCHED
+ brcc 1f
+ unmask_interrupts
+ rcall schedule
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp fault_exit_work
+
+1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
+ tst r1, r2
+ breq 2f
+ unmask_interrupts
+ mov r12, sp
+ mov r11, r0
+ rcall do_notify_resume
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp fault_exit_work
+
+2: bld r1, TIF_BREAKPOINT
+ brcc fault_resume_user
+ mfsr r3, SYSREG_TLBEHI
+ lddsp r2, sp[REG_PC]
+ andl r3, 0xff, COH
+ lsl r3, 1
+ sbr r3, 30
+ sbr r3, 0
+ mtdr DBGREG_BWA2A, r2
+ mtdr DBGREG_BWC2A, r3
+ rjmp fault_resume_user
+
+ /* If we get a debug trap from privileged context we end up here */
+handle_debug_priv:
+ /* Fix up LR and SP in regs. r11 contains the mode we came from */
+ mfsr r8, SYSREG_SR
+ mov r9, r8
+ andh r8, hi(~MODE_MASK)
+ or r8, r11
+ mtsr SYSREG_SR, r8
+ sub pc, -2
+ stdsp sp[REG_LR], lr
+ mtsr SYSREG_SR, r9
+ sub pc, -2
+ sub r10, sp, -FRAME_SIZE_FULL
+ stdsp sp[REG_SP], r10
+ mov r12, sp
+ rcall do_debug_priv
+
+ /* Now, put everything back */
+ ssrf SR_EM_BIT
+ popm r10, r11
+ mtsr SYSREG_RAR_DBG, r10
+ mtsr SYSREG_RSR_DBG, r11
+ mfsr r8, SYSREG_SR
+ mov r9, r8
+ andh r8, hi(~MODE_MASK)
+ andh r11, hi(MODE_MASK)
+ or r8, r11
+ mtsr SYSREG_SR, r8
+ sub pc, -2
+ popm lr
+ mtsr SYSREG_SR, r9
+ sub pc, -2
+ sub sp, -4 /* skip SP */
+ popm r0-r12
+ sub sp, -4
+ retd
+
+ /*
+ * At this point, everything is masked, that is, interrupts,
+ * exceptions and debugging traps. We might get called from
+ * interrupt or exception context in some rare cases, but this
+ * will be taken care of by do_debug(), so we're not going to
+ * do a 100% correct context save here.
+ */
+handle_debug:
+ sub sp, 4 /* r12_orig */
+ stmts --sp, r0-lr
+ mfsr r10, SYSREG_RAR_DBG
+ mfsr r11, SYSREG_RSR_DBG
+ unmask_exceptions
+ pushm r10,r11
+ andh r11, (MODE_MASK >> 16), COH
+ brne handle_debug_priv
+
+ mov r12, sp
+ rcall do_debug
+
+ lddsp r10, sp[REG_SR]
+ andh r10, (MODE_MASK >> 16), COH
+ breq debug_resume_user
+
+debug_restore_all:
+ popm r10,r11
+ mask_exceptions
+ mtsr SYSREG_RSR_DBG, r11
+ mtsr SYSREG_RAR_DBG, r10
+ ldmts sp++, r0-lr
+ sub sp, -4
+ retd
+
+debug_resume_user:
+ get_thread_info r0
+ mask_interrupts
+
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_DBGWORK_MASK, COH
+ breq debug_restore_all
+
+1: bld r1, TIF_NEED_RESCHED
+ brcc 2f
+ unmask_interrupts
+ rcall schedule
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
+ tst r1, r2
+ breq 3f
+ unmask_interrupts
+ mov r12, sp
+ mov r11, r0
+ rcall do_notify_resume
+ mask_interrupts
+ ld.w r1, r0[TI_flags]
+ rjmp 1b
+
+3: bld r1, TIF_SINGLE_STEP
+ brcc debug_restore_all
+ mfdr r2, DBGREG_DC
+ sbr r2, DC_SS_BIT
+ mtdr DBGREG_DC, r2
+ rjmp debug_restore_all
+
+ .set rsr_int0, SYSREG_RSR_INT0
+ .set rsr_int1, SYSREG_RSR_INT1
+ .set rsr_int2, SYSREG_RSR_INT2
+ .set rsr_int3, SYSREG_RSR_INT3
+ .set rar_int0, SYSREG_RAR_INT0
+ .set rar_int1, SYSREG_RAR_INT1
+ .set rar_int2, SYSREG_RAR_INT2
+ .set rar_int3, SYSREG_RAR_INT3
+
+ .macro IRQ_LEVEL level
+ .type irq_level\level, @function
+irq_level\level:
+ sub sp, 4 /* r12_orig */
+ stmts --sp,r0-lr
+ mfsr r8, rar_int\level
+ mfsr r9, rsr_int\level
+ pushm r8-r9
+
+ mov r11, sp
+ mov r12, \level
+
+ rcall do_IRQ
+
+ lddsp r4, sp[REG_SR]
+ andh r4, (MODE_MASK >> 16), COH
+#ifdef CONFIG_PREEMPT
+ brne 2f
+#else
+ brne 1f
+#endif
+
+ get_thread_info r0
+ ld.w r1, r0[TI_flags]
+ andl r1, _TIF_WORK_MASK, COH
+ brne irq_exit_work
+
+1: popm r8-r9
+ mtsr rar_int\level, r8
+ mtsr rsr_int\level, r9
+ ldmts sp++,r0-lr
+ sub sp, -4 /* ignore r12_orig */
+ rete
+
+#ifdef CONFIG_PREEMPT
+2:
+ get_thread_info r0
+ ld.w r2, r0[TI_preempt_count]
+ cp.w r2, 0
+ brne 1b
+ ld.w r1, r0[TI_flags]
+ bld r1, TIF_NEED_RESCHED
+ brcc 1b
+ lddsp r4, sp[REG_SR]
+ bld r4, SYSREG_GM_OFFSET
+ brcs 1b
+ rcall preempt_schedule_irq
+ rjmp 1b
+#endif
+ .endm
+
+ .section .irq.text,"ax",@progbits
+
+ .global irq_level0
+ .global irq_level1
+ .global irq_level2
+ .global irq_level3
+ IRQ_LEVEL 0
+ IRQ_LEVEL 1
+ IRQ_LEVEL 2
+ IRQ_LEVEL 3
--- /dev/null
+/*
+ * Non-board-specific low-level startup code
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/sysreg.h>
+
+ .section .init.text,"ax"
+ .global kernel_entry
+kernel_entry:
+ /* Initialize status register */
+ lddpc r0, init_sr
+ mtsr SYSREG_SR, r0
+
+ /* Set initial stack pointer */
+ lddpc sp, stack_addr
+ sub sp, -THREAD_SIZE
+
+#ifdef CONFIG_FRAME_POINTER
+ /* Mark last stack frame */
+ mov lr, 0
+ mov r7, 0
+#endif
+
+ /* Set up the PIO, SDRAM controller, early printk, etc. */
+ rcall board_early_init
+
+ /* Start the show */
+ lddpc pc, kernel_start_addr
+
+ .align 2
+init_sr:
+ .long 0x007f0000 /* Supervisor mode, everything masked */
+stack_addr:
+ .long init_thread_union
+kernel_start_addr:
+ .long start_kernel
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure. Must be aligned on an 8192-byte boundary.
+ */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on arch/i386/kernel/irq.c
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ *
+ * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/sysdev.h>
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ %u\n", irq);
+}
+
+#ifdef CONFIG_PROC_FS
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *)v, cpu;
+ struct irqaction *action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_puts(p, " ");
+ for_each_online_cpu(cpu)
+ seq_printf(p, "CPU%d ", cpu);
+ seq_putc(p, '\n');
+ }
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto unlock;
+
+ seq_printf(p, "%3d: ", i);
+ for_each_online_cpu(cpu)
+ seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+ seq_printf(p, " %s", action->name);
+ for (action = action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+ unlock:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * Kernel Probes (KProbes)
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * Based on arch/ppc64/kernel/kprobes.c
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/ocd.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe);
+static unsigned long kprobe_status;
+static struct pt_regs jprobe_saved_regs;
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+ int ret = 0;
+
+ if ((unsigned long)p->addr & 0x01) {
+ printk("Attempt to register kprobe at an unaligned address\n");
+ ret = -EINVAL;
+ }
+
+ /* XXX: Might be a good idea to check if p->addr is a valid
+ * kernel address as well... */
+
+ if (!ret) {
+ pr_debug("copy kprobe at %p\n", p->addr);
+ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
+ }
+
+ return ret;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ pr_debug("arming kprobe at %p\n", p->addr);
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+ pr_debug("disarming kprobe at %p\n", p->addr);
+ *p->addr = p->opcode;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long dc;
+
+ pr_debug("preparing to singlestep over %p (PC=%08lx)\n",
+ p->addr, regs->pc);
+
+ BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D)));
+
+ dc = __mfdr(DBGREG_DC);
+ dc |= DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ /*
+ * We must run the instruction from its original location
+ * since it may actually reference PC.
+ *
+ * TODO: Do the instruction replacement directly in icache.
+ */
+ *p->addr = p->opcode;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long dc;
+
+ pr_debug("resuming execution at PC=%08lx\n", regs->pc);
+
+ dc = __mfdr(DBGREG_DC);
+ dc &= ~DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long)p->addr,
+ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+static void __kprobes set_current_kprobe(struct kprobe *p)
+{
+ __get_cpu_var(current_kprobe) = p;
+}
+
+static int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *p;
+ void *addr = (void *)regs->pc;
+ int ret = 0;
+
+ pr_debug("kprobe_handler: kprobe_running=%d\n",
+ kprobe_running());
+
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
+ preempt_disable();
+
+ /* Check that we're not recursing */
+ if (kprobe_running()) {
+ p = get_kprobe(addr);
+ if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ printk("FIXME: kprobe hit while single-stepping!\n");
+ goto no_kprobe;
+ }
+
+ printk("FIXME: kprobe hit while handling another kprobe\n");
+ goto no_kprobe;
+ } else {
+ p = kprobe_running();
+ if (p->break_handler && p->break_handler(p, regs))
+ goto ss_probe;
+ }
+ /* If it's not ours, can't be delete race, (we hold lock). */
+ goto no_kprobe;
+ }
+
+ p = get_kprobe(addr);
+ if (!p)
+ goto no_kprobe;
+
+ kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p);
+ if (p->pre_handler && p->pre_handler(p, regs))
+ /* handler has already set things up, so skip ss setup */
+ return 1;
+
+ss_probe:
+ prepare_singlestep(p, regs);
+ kprobe_status = KPROBE_HIT_SS;
+ return 1;
+
+no_kprobe:
+ return ret;
+}
+
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *cur = kprobe_running();
+
+ pr_debug("post_kprobe_handler, cur=%p\n", cur);
+
+ if (!cur)
+ return 0;
+
+ if (cur->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
+ }
+
+ resume_execution(cur, regs);
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+
+ return 1;
+}
+
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ struct kprobe *cur = kprobe_running();
+
+ pr_debug("kprobe_fault_handler: trapnr=%d\n", trapnr);
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+ return 1;
+
+ if (kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs);
+ preempt_enable_no_resched();
+ }
+ return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+ pr_debug("kprobe_exceptions_notify: val=%lu, data=%p\n",
+ val, data);
+
+ switch (val) {
+ case DIE_BREAKPOINT:
+ if (kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_SSTEP:
+ if (post_kprobe_handler(args->regs))
+ ret = NOTIFY_STOP;
+ break;
+ case DIE_FAULT:
+ if (kprobe_running()
+ && kprobe_fault_handler(args->regs, args->trapnr))
+ ret = NOTIFY_STOP;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+ memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
+
+ /*
+ * TODO: We should probably save some of the stack here as
+ * well, since gcc may pass arguments on the stack for certain
+ * functions (lots of arguments, large aggregates, varargs)
+ */
+
+ /* setup return addr to the jprobe handler routine */
+ regs->pc = (unsigned long)jp->entry;
+ return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+ asm volatile("breakpoint" ::: "memory");
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ /*
+ * FIXME - we should ideally be validating that we got here 'cos
+ * of the "trap" in jprobe_return() above, before restoring the
+ * saved regs...
+ */
+ memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
+ return 1;
+}
+
+int __init arch_init_kprobes(void)
+{
+ printk("KPROBES: Enabling monitor mode (MM|DBE)...\n");
+ __mtdr(DBGREG_DC, DC_MM | DC_DBE);
+
+ /* TODO: Register kretprobe trampoline */
+ return 0;
+}
--- /dev/null
+/*
+ * AVR32-specific kernel module loader
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * GOT initialization parts are based on the s390 version
+ * Copyright (C) 2002, 2003 IBM Deutschland Entwicklung GmbH,
+ * IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/moduleloader.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(mod->arch.syminfo);
+ mod->arch.syminfo = NULL;
+
+ vfree(module_region);
+ /* FIXME: if module_region == mod->init_region, trim exception
+ * table entries. */
+}
+
+static inline int check_rela(Elf32_Rela *rela, struct module *module,
+ char *strings, Elf32_Sym *symbols)
+{
+ struct mod_arch_syminfo *info;
+
+ info = module->arch.syminfo + ELF32_R_SYM(rela->r_info);
+ switch (ELF32_R_TYPE(rela->r_info)) {
+ case R_AVR32_GOT32:
+ case R_AVR32_GOT16:
+ case R_AVR32_GOT8:
+ case R_AVR32_GOT21S:
+ case R_AVR32_GOT18SW: /* mcall */
+ case R_AVR32_GOT16S: /* ld.w */
+ if (rela->r_addend != 0) {
+ printk(KERN_ERR
+ "GOT relocation against %s at offset %u with addend\n",
+ strings + symbols[ELF32_R_SYM(rela->r_info)].st_name,
+ rela->r_offset);
+ return -ENOEXEC;
+ }
+ if (info->got_offset == -1UL) {
+ info->got_offset = module->arch.got_size;
+ module->arch.got_size += sizeof(void *);
+ }
+ pr_debug("GOT[%3lu] %s\n", info->got_offset,
+ strings + symbols[ELF32_R_SYM(rela->r_info)].st_name);
+ break;
+ }
+
+ return 0;
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+ char *secstrings, struct module *module)
+{
+ Elf32_Shdr *symtab;
+ Elf32_Sym *symbols;
+ Elf32_Rela *rela;
+ char *strings;
+ int nrela, i, j;
+ int ret;
+
+ /* Find the symbol table */
+ symtab = NULL;
+ for (i = 0; i < hdr->e_shnum; i++)
+ switch (sechdrs[i].sh_type) {
+ case SHT_SYMTAB:
+ symtab = &sechdrs[i];
+ break;
+ }
+ if (!symtab) {
+ printk(KERN_ERR "module %s: no symbol table\n", module->name);
+ return -ENOEXEC;
+ }
+
+ /* Allocate room for one syminfo structure per symbol. */
+ module->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym);
+ module->arch.syminfo = vmalloc(module->arch.nsyms
+ * sizeof(struct mod_arch_syminfo));
+ if (!module->arch.syminfo)
+ return -ENOMEM;
+
+ symbols = (void *)hdr + symtab->sh_offset;
+ strings = (void *)hdr + sechdrs[symtab->sh_link].sh_offset;
+ for (i = 0; i < module->arch.nsyms; i++) {
+ if (symbols[i].st_shndx == SHN_UNDEF &&
+ strcmp(strings + symbols[i].st_name,
+ "_GLOBAL_OFFSET_TABLE_") == 0)
+ /* "Define" it as absolute. */
+ symbols[i].st_shndx = SHN_ABS;
+ module->arch.syminfo[i].got_offset = -1UL;
+ module->arch.syminfo[i].got_initialized = 0;
+ }
+
+ /* Allocate GOT entries for symbols that need it. */
+ module->arch.got_size = 0;
+ for (i = 0; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_type != SHT_RELA)
+ continue;
+ nrela = sechdrs[i].sh_size / sizeof(Elf32_Rela);
+ rela = (void *)hdr + sechdrs[i].sh_offset;
+ for (j = 0; j < nrela; j++) {
+ ret = check_rela(rela + j, module,
+ strings, symbols);
+ if (ret)
+ goto out_free_syminfo;
+ }
+ }
+
+ /*
+ * Increase core size to make room for GOT and set start
+ * offset for GOT.
+ */
+ module->core_size = ALIGN(module->core_size, 4);
+ module->arch.got_offset = module->core_size;
+ module->core_size += module->arch.got_size;
+
+ return 0;
+
+out_free_syminfo:
+ vfree(module->arch.syminfo);
+ module->arch.syminfo = NULL;
+
+ return ret;
+}
+
+static inline int reloc_overflow(struct module *module, const char *reloc_name,
+ Elf32_Addr relocation)
+{
+ printk(KERN_ERR "module %s: Value %lx does not fit relocation %s\n",
+ module->name, (unsigned long)relocation, reloc_name);
+ return -ENOEXEC;
+}
+
+#define get_u16(loc) (*((uint16_t *)loc))
+#define put_u16(loc, val) (*((uint16_t *)loc) = (val))
+
+int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relindex,
+ struct module *module)
+{
+ Elf32_Shdr *symsec = sechdrs + symindex;
+ Elf32_Shdr *relsec = sechdrs + relindex;
+ Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
+ Elf32_Rela *rel = (void *)relsec->sh_addr;
+ unsigned int i;
+ int ret = 0;
+
+ for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
+ struct mod_arch_syminfo *info;
+ Elf32_Sym *sym;
+ Elf32_Addr relocation;
+ uint32_t *location;
+ uint32_t value;
+
+ location = (void *)dstsec->sh_addr + rel->r_offset;
+ sym = (Elf32_Sym *)symsec->sh_addr + ELF32_R_SYM(rel->r_info);
+ relocation = sym->st_value + rel->r_addend;
+
+ info = module->arch.syminfo + ELF32_R_SYM(rel->r_info);
+
+ /* Initialize GOT entry if necessary */
+ switch (ELF32_R_TYPE(rel->r_info)) {
+ case R_AVR32_GOT32:
+ case R_AVR32_GOT16:
+ case R_AVR32_GOT8:
+ case R_AVR32_GOT21S:
+ case R_AVR32_GOT18SW:
+ case R_AVR32_GOT16S:
+ if (!info->got_initialized) {
+ Elf32_Addr *gotent;
+
+ gotent = (module->module_core
+ + module->arch.got_offset
+ + info->got_offset);
+ *gotent = relocation;
+ info->got_initialized = 1;
+ }
+
+ relocation = info->got_offset;
+ break;
+ }
+
+ switch (ELF32_R_TYPE(rel->r_info)) {
+ case R_AVR32_32:
+ case R_AVR32_32_CPENT:
+ *location = relocation;
+ break;
+ case R_AVR32_22H_PCREL:
+ relocation -= (Elf32_Addr)location;
+ if ((relocation & 0xffe00001) != 0
+ && (relocation & 0xffc00001) != 0xffc00000)
+ return reloc_overflow(module,
+ "R_AVR32_22H_PCREL",
+ relocation);
+ relocation >>= 1;
+
+ value = *location;
+ value = ((value & 0xe1ef0000)
+ | (relocation & 0xffff)
+ | ((relocation & 0x10000) << 4)
+ | ((relocation & 0x1e0000) << 8));
+ *location = value;
+ break;
+ case R_AVR32_11H_PCREL:
+ relocation -= (Elf32_Addr)location;
+ if ((relocation & 0xfffffc01) != 0
+ && (relocation & 0xfffff801) != 0xfffff800)
+ return reloc_overflow(module,
+ "R_AVR32_11H_PCREL",
+ relocation);
+ value = get_u16(location);
+ value = ((value & 0xf00c)
+ | ((relocation & 0x1fe) << 3)
+ | ((relocation & 0x600) >> 9));
+ put_u16(location, value);
+ break;
+ case R_AVR32_9H_PCREL:
+ relocation -= (Elf32_Addr)location;
+ if ((relocation & 0xffffff01) != 0
+ && (relocation & 0xfffffe01) != 0xfffffe00)
+ return reloc_overflow(module,
+ "R_AVR32_9H_PCREL",
+ relocation);
+ value = get_u16(location);
+ value = ((value & 0xf00f)
+ | ((relocation & 0x1fe) << 3));
+ put_u16(location, value);
+ break;
+ case R_AVR32_9UW_PCREL:
+ relocation -= ((Elf32_Addr)location) & 0xfffffffc;
+ if ((relocation & 0xfffffc03) != 0)
+ return reloc_overflow(module,
+ "R_AVR32_9UW_PCREL",
+ relocation);
+ value = get_u16(location);
+ value = ((value & 0xf80f)
+ | ((relocation & 0x1fc) << 2));
+ put_u16(location, value);
+ break;
+ case R_AVR32_GOTPC:
+ /*
+ * R6 = PC - (PC - GOT)
+ *
+ * At this point, relocation contains the
+ * value of PC. Just subtract the value of
+ * GOT, and we're done.
+ */
+ pr_debug("GOTPC: PC=0x%lx, got_offset=0x%lx, core=0x%p\n",
+ relocation, module->arch.got_offset,
+ module->module_core);
+ relocation -= ((unsigned long)module->module_core
+ + module->arch.got_offset);
+ *location = relocation;
+ break;
+ case R_AVR32_GOT18SW:
+ if ((relocation & 0xfffe0003) != 0
+ && (relocation & 0xfffc0003) != 0xffff0000)
+ return reloc_overflow(module, "R_AVR32_GOT18SW",
+ relocation);
+ relocation >>= 2;
+ /* fall through */
+ case R_AVR32_GOT16S:
+ if ((relocation & 0xffff8000) != 0
+ && (relocation & 0xffff0000) != 0xffff0000)
+ return reloc_overflow(module, "R_AVR32_GOT16S",
+ relocation);
+ pr_debug("GOT reloc @ 0x%lx -> %lu\n",
+ rel->r_offset, relocation);
+ value = *location;
+ value = ((value & 0xffff0000)
+ | (relocation & 0xffff));
+ *location = value;
+ break;
+
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ module->name, ELF32_R_TYPE(rel->r_info));
+ return -ENOEXEC;
+ }
+ }
+
+ return ret;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relindex,
+ struct module *module)
+{
+ printk(KERN_ERR "module %s: REL relocations are not supported\n",
+ module->name);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ struct module *module)
+{
+ vfree(module->arch.syminfo);
+ module->arch.syminfo = NULL;
+
+ return 0;
+}
+
+void module_arch_cleanup(struct module *module)
+{
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/fs.h>
+#include <linux/ptrace.h>
+#include <linux/reboot.h>
+#include <linux/unistd.h>
+
+#include <asm/sysreg.h>
+#include <asm/ocd.h>
+
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ /* TODO: Enter sleep mode */
+ while (!need_resched())
+ cpu_relax();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+}
+
+void machine_restart(char *cmd)
+{
+ __mtdr(DBGREG_DC, DC_DBE);
+ __mtdr(DBGREG_DC, DC_RES);
+ while (1) ;
+}
+
+/*
+ * PC is actually discarded when returning from a system call -- the
+ * return address must be stored in LR. This function will make sure
+ * LR points to do_exit before starting the thread.
+ *
+ * Also, when returning from fork(), r12 is 0, so we must copy the
+ * argument as well.
+ *
+ * r0 : The argument to the main thread function
+ * r1 : The address of do_exit
+ * r2 : The address of the main thread function
+ */
+asmlinkage extern void kernel_thread_helper(void);
+__asm__(" .type kernel_thread_helper, @function\n"
+ "kernel_thread_helper:\n"
+ " mov r12, r0\n"
+ " mov lr, r2\n"
+ " mov pc, r1\n"
+ " .size kernel_thread_helper, . - kernel_thread_helper");
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+
+ regs.r0 = (unsigned long)arg;
+ regs.r1 = (unsigned long)fn;
+ regs.r2 = (unsigned long)do_exit;
+ regs.lr = (unsigned long)kernel_thread_helper;
+ regs.pc = (unsigned long)kernel_thread_helper;
+ regs.sr = MODE_SUPERVISOR;
+
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
+ 0, ®s, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Free current thread data structures etc
+ */
+void exit_thread(void)
+{
+ /* nothing to do */
+}
+
+void flush_thread(void)
+{
+ /* nothing to do */
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+ /* do nothing */
+}
+
+static const char *cpu_modes[] = {
+ "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
+ "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
+};
+
+void show_regs(struct pt_regs *regs)
+{
+ unsigned long sp = regs->sp;
+ unsigned long lr = regs->lr;
+ unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT;
+
+ if (!user_mode(regs))
+ sp = (unsigned long)regs + FRAME_SIZE_FULL;
+
+ print_symbol("PC is at %s\n", instruction_pointer(regs));
+ print_symbol("LR is at %s\n", lr);
+ printk("pc : [<%08lx>] lr : [<%08lx>] %s\n"
+ "sp : %08lx r12: %08lx r11: %08lx\n",
+ instruction_pointer(regs),
+ lr, print_tainted(), sp, regs->r12, regs->r11);
+ printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
+ regs->r10, regs->r9, regs->r8);
+ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
+ regs->r7, regs->r6, regs->r5, regs->r4);
+ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
+ regs->r3, regs->r2, regs->r1, regs->r0);
+ printk("Flags: %c%c%c%c%c\n",
+ regs->sr & SR_Q ? 'Q' : 'q',
+ regs->sr & SR_V ? 'V' : 'v',
+ regs->sr & SR_N ? 'N' : 'n',
+ regs->sr & SR_Z ? 'Z' : 'z',
+ regs->sr & SR_C ? 'C' : 'c');
+ printk("Mode bits: %c%c%c%c%c%c%c%c%c\n",
+ regs->sr & SR_H ? 'H' : 'h',
+ regs->sr & SR_R ? 'R' : 'r',
+ regs->sr & SR_J ? 'J' : 'j',
+ regs->sr & SR_EM ? 'E' : 'e',
+ regs->sr & SR_I3M ? '3' : '.',
+ regs->sr & SR_I2M ? '2' : '.',
+ regs->sr & SR_I1M ? '1' : '.',
+ regs->sr & SR_I0M ? '0' : '.',
+ regs->sr & SR_GM ? 'G' : 'g');
+ printk("CPU Mode: %s\n", cpu_modes[mode]);
+
+ show_trace(NULL, (unsigned long *)sp, regs);
+}
+EXPORT_SYMBOL(show_regs);
+
+/* Fill in the fpu structure for a core dump. This is easy -- we don't have any */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+ /* Not valid */
+ return 0;
+}
+
+asmlinkage void ret_from_fork(void);
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs;
+
+ childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1;
+ *childregs = *regs;
+
+ if (user_mode(regs))
+ childregs->sp = usp;
+ else
+ childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE;
+
+ childregs->r12 = 0; /* Set return value for child */
+
+ p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
+ p->thread.cpu_context.ksp = (unsigned long)childregs;
+ p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
+
+ return 0;
+}
+
+/* r12-r8 are dummy parameters to force the compiler to use the stack */
+asmlinkage int sys_fork(struct pt_regs *regs)
+{
+ return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+ unsigned long parent_tidptr,
+ unsigned long child_tidptr, struct pt_regs *regs)
+{
+ if (!newsp)
+ newsp = regs->sp;
+ return do_fork(clone_flags, newsp, regs, 0,
+ (int __user *)parent_tidptr,
+ (int __user *)child_tidptr);
+}
+
+asmlinkage int sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs,
+ 0, NULL, NULL);
+}
+
+asmlinkage int sys_execve(char __user *ufilename, char __user *__user *uargv,
+ char __user *__user *uenvp, struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname(ufilename);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename, uargv, uenvp, regs);
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+
+out:
+ return error;
+}
+
+
+/*
+ * This function is supposed to answer the question "who called
+ * schedule()?"
+ */
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long pc;
+ unsigned long stack_page;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ stack_page = (unsigned long)p->thread_info;
+ BUG_ON(!stack_page);
+
+ /*
+ * The stored value of PC is either the address right after
+ * the call to __switch_to() or ret_from_fork.
+ */
+ pc = thread_saved_pc(p);
+ if (in_sched_functions(pc)) {
+#ifdef CONFIG_FRAME_POINTER
+ unsigned long fp = p->thread.cpu_context.r7;
+ BUG_ON(fp < stack_page || fp > (THREAD_SIZE + stack_page));
+ pc = *(unsigned long *)fp;
+#else
+ /*
+ * We depend on the frame size of schedule here, which
+ * is actually quite ugly. It might be possible to
+ * determine the frame size automatically at build
+ * time by doing this:
+ * - compile sched.c
+ * - disassemble the resulting sched.o
+ * - look for 'sub sp,??' shortly after '<schedule>:'
+ */
+ unsigned long sp = p->thread.cpu_context.ksp + 16;
+ BUG_ON(sp < stack_page || sp > (THREAD_SIZE + stack_page));
+ pc = *(unsigned long *)sp;
+#endif
+ }
+
+ return pc;
+}
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#undef DEBUG
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/user.h>
+#include <linux/security.h>
+#include <linux/unistd.h>
+#include <linux/notifier.h>
+
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <asm/ocd.h>
+#include <asm/mmu_context.h>
+#include <asm/kdebug.h>
+
+static struct pt_regs *get_user_regs(struct task_struct *tsk)
+{
+ return (struct pt_regs *)((unsigned long) tsk->thread_info +
+ THREAD_SIZE - sizeof(struct pt_regs));
+}
+
+static void ptrace_single_step(struct task_struct *tsk)
+{
+ pr_debug("ptrace_single_step: pid=%u, SR=0x%08lx\n",
+ tsk->pid, tsk->thread.cpu_context.sr);
+ if (!(tsk->thread.cpu_context.sr & SR_D)) {
+ /*
+ * Set a breakpoint at the current pc to force the
+ * process into debug mode. The syscall/exception
+ * exit code will set a breakpoint at the return
+ * address when this flag is set.
+ */
+ pr_debug("ptrace_single_step: Setting TIF_BREAKPOINT\n");
+ set_tsk_thread_flag(tsk, TIF_BREAKPOINT);
+ }
+
+ /* The monitor code will do the actual step for us */
+ set_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching
+ *
+ * Make sure any single step bits, etc. are not set
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ clear_tsk_thread_flag(child, TIF_SINGLE_STEP);
+}
+
+/*
+ * Handle hitting a breakpoint
+ */
+static void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = (void __user *)instruction_pointer(regs);
+
+ pr_debug("ptrace_break: Sending SIGTRAP to PID %u (pc = 0x%p)\n",
+ tsk->pid, info.si_addr);
+ force_sig_info(SIGTRAP, &info, tsk);
+}
+
+/*
+ * Read the word at offset "offset" into the task's "struct user". We
+ * actually access the pt_regs struct stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long offset,
+ unsigned long __user *data)
+{
+ unsigned long *regs;
+ unsigned long value;
+
+ pr_debug("ptrace_read_user(%p, %#lx, %p)\n",
+ tsk, offset, data);
+
+ if (offset & 3 || offset >= sizeof(struct user)) {
+ printk("ptrace_read_user: invalid offset 0x%08lx\n", offset);
+ return -EIO;
+ }
+
+ regs = (unsigned long *)get_user_regs(tsk);
+
+ value = 0;
+ if (offset < sizeof(struct pt_regs))
+ value = regs[offset / sizeof(regs[0])];
+
+ return put_user(value, data);
+}
+
+/*
+ * Write the word "value" to offset "offset" into the task's "struct
+ * user". We actually access the pt_regs struct stored on the kernel
+ * stack.
+ */
+static int ptrace_write_user(struct task_struct *tsk, unsigned long offset,
+ unsigned long value)
+{
+ unsigned long *regs;
+
+ if (offset & 3 || offset >= sizeof(struct user)) {
+ printk("ptrace_write_user: invalid offset 0x%08lx\n", offset);
+ return -EIO;
+ }
+
+ if (offset >= sizeof(struct pt_regs))
+ return 0;
+
+ regs = (unsigned long *)get_user_regs(tsk);
+ regs[offset / sizeof(regs[0])] = value;
+
+ return 0;
+}
+
+static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
+{
+ struct pt_regs *regs = get_user_regs(tsk);
+
+ return copy_to_user(uregs, regs, sizeof(*regs)) ? -EFAULT : 0;
+}
+
+static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
+{
+ struct pt_regs newregs;
+ int ret;
+
+ ret = -EFAULT;
+ if (copy_from_user(&newregs, uregs, sizeof(newregs)) == 0) {
+ struct pt_regs *regs = get_user_regs(tsk);
+
+ ret = -EINVAL;
+ if (valid_user_regs(&newregs)) {
+ *regs = newregs;
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ unsigned long tmp;
+ int ret;
+
+ pr_debug("arch_ptrace(%ld, %ld, %#lx, %#lx)\n",
+ request, child->pid, addr, data);
+
+ pr_debug("ptrace: Enabling monitor mode...\n");
+ __mtdr(DBGREG_DC, __mfdr(DBGREG_DC) | DC_MM | DC_DBE);
+
+ switch (request) {
+ /* Read the word at location addr in the child process */
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+ ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ if (ret == sizeof(tmp))
+ ret = put_user(tmp, (unsigned long __user *)data);
+ else
+ ret = -EIO;
+ break;
+
+ case PTRACE_PEEKUSR:
+ ret = ptrace_read_user(child, addr,
+ (unsigned long __user *)data);
+ break;
+
+ /* Write the word in data at location addr */
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEDATA:
+ ret = access_process_vm(child, addr, &data, sizeof(data), 1);
+ if (ret == sizeof(data))
+ ret = 0;
+ else
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR:
+ ret = ptrace_write_user(child, addr, data);
+ break;
+
+ /* continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ /* restart after signal */
+ case PTRACE_CONT:
+ ret = -EIO;
+ if (!valid_signal(data))
+ break;
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->exit_code = data;
+ /* XXX: Are we sure no breakpoints are active here? */
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ /*
+ * Make the child exit. Best I can do is send it a
+ * SIGKILL. Perhaps it should be put in the status that it
+ * wants to exit.
+ */
+ case PTRACE_KILL:
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE)
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+
+ /*
+ * execute single instruction.
+ */
+ case PTRACE_SINGLESTEP:
+ ret = -EIO;
+ if (!valid_signal(data))
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ ptrace_single_step(child);
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ /* Detach a process that was attached */
+ case PTRACE_DETACH:
+ ret = ptrace_detach(child, data);
+ break;
+
+ case PTRACE_GETREGS:
+ ret = ptrace_getregs(child, (void __user *)data);
+ break;
+
+ case PTRACE_SETREGS:
+ ret = ptrace_setregs(child, (const void __user *)data);
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+ pr_debug("sys_ptrace returning %d (DC = 0x%08lx)\n", ret, __mfdr(DBGREG_DC));
+ return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+ pr_debug("syscall_trace called\n");
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+
+ pr_debug("syscall_trace: notifying parent\n");
+ /* The 0x80 provides a way for the tracing parent to
+ * distinguish between a syscall stop and SIGTRAP delivery */
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it
+ * will do for normal use. strace only continues with a
+ * signal if the stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ pr_debug("syscall_trace: sending signal %d to PID %u\n",
+ current->exit_code, current->pid);
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
+
+asmlinkage void do_debug_priv(struct pt_regs *regs)
+{
+ unsigned long dc, ds;
+ unsigned long die_val;
+
+ ds = __mfdr(DBGREG_DS);
+
+ pr_debug("do_debug_priv: pc = %08lx, ds = %08lx\n", regs->pc, ds);
+
+ if (ds & DS_SSS)
+ die_val = DIE_SSTEP;
+ else
+ die_val = DIE_BREAKPOINT;
+
+ if (notify_die(die_val, regs, 0, SIGTRAP) == NOTIFY_STOP)
+ return;
+
+ if (likely(ds & DS_SSS)) {
+ extern void itlb_miss(void);
+ extern void tlb_miss_common(void);
+ struct thread_info *ti;
+
+ dc = __mfdr(DBGREG_DC);
+ dc &= ~DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ ti = current_thread_info();
+ ti->flags |= _TIF_BREAKPOINT;
+
+ /* The TLB miss handlers don't check thread flags */
+ if ((regs->pc >= (unsigned long)&itlb_miss)
+ && (regs->pc <= (unsigned long)&tlb_miss_common)) {
+ __mtdr(DBGREG_BWA2A, sysreg_read(RAR_EX));
+ __mtdr(DBGREG_BWC2A, 0x40000001 | (get_asid() << 1));
+ }
+
+ /*
+ * If we're running in supervisor mode, the breakpoint
+ * will take us where we want directly, no need to
+ * single step.
+ */
+ if ((regs->sr & MODE_MASK) != MODE_SUPERVISOR)
+ ti->flags |= TIF_SINGLE_STEP;
+ } else {
+ panic("Unable to handle debug trap at pc = %08lx\n",
+ regs->pc);
+ }
+}
+
+/*
+ * Handle breakpoints, single steps and other debuggy things. To keep
+ * things simple initially, we run with interrupts and exceptions
+ * disabled all the time.
+ */
+asmlinkage void do_debug(struct pt_regs *regs)
+{
+ unsigned long dc, ds;
+
+ ds = __mfdr(DBGREG_DS);
+ pr_debug("do_debug: pc = %08lx, ds = %08lx\n", regs->pc, ds);
+
+ if (test_thread_flag(TIF_BREAKPOINT)) {
+ pr_debug("TIF_BREAKPOINT set\n");
+ /* We're taking care of it */
+ clear_thread_flag(TIF_BREAKPOINT);
+ __mtdr(DBGREG_BWC2A, 0);
+ }
+
+ if (test_thread_flag(TIF_SINGLE_STEP)) {
+ pr_debug("TIF_SINGLE_STEP set, ds = 0x%08lx\n", ds);
+ if (ds & DS_SSS) {
+ dc = __mfdr(DBGREG_DC);
+ dc &= ~DC_SS;
+ __mtdr(DBGREG_DC, dc);
+
+ clear_thread_flag(TIF_SINGLE_STEP);
+ ptrace_break(current, regs);
+ }
+ } else {
+ /* regular breakpoint */
+ ptrace_break(current, regs);
+ }
+}
--- /dev/null
+/*
+ * AVR32 sempahore implementation.
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on linux/arch/i386/kernel/semaphore.c
+ * Copyright (C) 1999 Linus Torvalds
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+#include <asm/semaphore.h>
+#include <asm/atomic.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to acquire the semaphore, while the "sleeping"
+ * variable is a count of such acquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is protected
+ * by the spinlock in the semaphore's waitqueue head.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ * - only on a boundary condition do we need to care. When we go
+ * from a negative count to a non-negative, we wake people up.
+ * - when we go from a non-negative count to a negative do we
+ * (a) synchronize with the "sleeper" count and (b) make sure
+ * that we're on the wakeup list before we synchronize so that
+ * we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+ wake_up(&sem->wait);
+}
+EXPORT_SYMBOL(__up);
+
+void __sched __down(struct semaphore *sem)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ unsigned long flags;
+
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+ sem->sleepers++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock in
+ * the wait_queue_head.
+ */
+ if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+ schedule();
+
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ tsk->state = TASK_UNINTERRUPTIBLE;
+ }
+ remove_wait_queue_locked(&sem->wait, &wait);
+ wake_up_locked(&sem->wait);
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+ tsk->state = TASK_RUNNING;
+}
+EXPORT_SYMBOL(__down);
+
+int __sched __down_interruptible(struct semaphore *sem)
+{
+ int retval = 0;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+ unsigned long flags;
+
+ tsk->state = TASK_INTERRUPTIBLE;
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+ sem->sleepers++;
+ for (;;) {
+ int sleepers = sem->sleepers;
+
+ /*
+ * With signals pending, this turns into the trylock
+ * failure case - we won't be sleeping, and we can't
+ * get the lock as it has contention. Just correct the
+ * count and exit.
+ */
+ if (signal_pending(current)) {
+ retval = -EINTR;
+ sem->sleepers = 0;
+ atomic_add(sleepers, &sem->count);
+ break;
+ }
+
+ /*
+ * Add "everybody else" into it. They aren't
+ * playing, because we own the spinlock in
+ * the wait_queue_head.
+ */
+ if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+ sem->sleepers = 0;
+ break;
+ }
+ sem->sleepers = 1; /* us - see -1 above */
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+ schedule();
+
+ spin_lock_irqsave(&sem->wait.lock, flags);
+ tsk->state = TASK_INTERRUPTIBLE;
+ }
+ remove_wait_queue_locked(&sem->wait, &wait);
+ wake_up_locked(&sem->wait);
+ spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+ tsk->state = TASK_RUNNING;
+ return retval;
+}
+EXPORT_SYMBOL(__down_interruptible);
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/console.h>
+#include <linux/ioport.h>
+#include <linux/bootmem.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/root_dev.h>
+#include <linux/cpu.h>
+
+#include <asm/sections.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/sysreg.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/init.h>
+
+extern int root_mountflags;
+
+/*
+ * Bootloader-provided information about physical memory
+ */
+struct tag_mem_range *mem_phys;
+struct tag_mem_range *mem_reserved;
+struct tag_mem_range *mem_ramdisk;
+
+/*
+ * Initialize loops_per_jiffy as 5000000 (500MIPS).
+ * Better make it too large than too small...
+ */
+struct avr32_cpuinfo boot_cpu_data = {
+ .loops_per_jiffy = 5000000
+};
+EXPORT_SYMBOL(boot_cpu_data);
+
+static char command_line[COMMAND_LINE_SIZE];
+
+/*
+ * Should be more than enough, but if you have a _really_ complex
+ * setup, you might need to increase the size of this...
+ */
+static struct tag_mem_range __initdata mem_range_cache[32];
+static unsigned mem_range_next_free;
+
+/*
+ * Standard memory resources
+ */
+static struct resource mem_res[] = {
+ {
+ .name = "Kernel code",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .name = "Kernel data",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#define kernel_code mem_res[0]
+#define kernel_data mem_res[1]
+
+/*
+ * Early framebuffer allocation. Works as follows:
+ * - If fbmem_size is zero, nothing will be allocated or reserved.
+ * - If fbmem_start is zero when setup_bootmem() is called,
+ * fbmem_size bytes will be allocated from the bootmem allocator.
+ * - If fbmem_start is nonzero, an area of size fbmem_size will be
+ * reserved at the physical address fbmem_start if necessary. If
+ * the area isn't in a memory region known to the kernel, it will
+ * be left alone.
+ *
+ * Board-specific code may use these variables to set up platform data
+ * for the framebuffer driver if fbmem_size is nonzero.
+ */
+static unsigned long __initdata fbmem_start;
+static unsigned long __initdata fbmem_size;
+
+/*
+ * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for
+ * use as framebuffer.
+ *
+ * "fbmem=xxx[kKmM]@yyy[kKmM]" defines a memory region of size xxx and
+ * starting at yyy to be reserved for use as framebuffer.
+ *
+ * The kernel won't verify that the memory region starting at yyy
+ * actually contains usable RAM.
+ */
+static int __init early_parse_fbmem(char *p)
+{
+ fbmem_size = memparse(p, &p);
+ if (*p == '@')
+ fbmem_start = memparse(p, &p);
+ return 0;
+}
+early_param("fbmem", early_parse_fbmem);
+
+static inline void __init resource_init(void)
+{
+ struct tag_mem_range *region;
+
+ kernel_code.start = __pa(init_mm.start_code);
+ kernel_code.end = __pa(init_mm.end_code - 1);
+ kernel_data.start = __pa(init_mm.end_code);
+ kernel_data.end = __pa(init_mm.brk - 1);
+
+ for (region = mem_phys; region; region = region->next) {
+ struct resource *res;
+ unsigned long phys_start, phys_end;
+
+ if (region->size == 0)
+ continue;
+
+ phys_start = region->addr;
+ phys_end = phys_start + region->size - 1;
+
+ res = alloc_bootmem_low(sizeof(*res));
+ res->name = "System RAM";
+ res->start = phys_start;
+ res->end = phys_end;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+ request_resource (&iomem_resource, res);
+
+ if (kernel_code.start >= res->start &&
+ kernel_code.end <= res->end)
+ request_resource (res, &kernel_code);
+ if (kernel_data.start >= res->start &&
+ kernel_data.end <= res->end)
+ request_resource (res, &kernel_data);
+ }
+}
+
+static int __init parse_tag_core(struct tag *tag)
+{
+ if (tag->hdr.size > 2) {
+ if ((tag->u.core.flags & 1) == 0)
+ root_mountflags &= ~MS_RDONLY;
+ ROOT_DEV = new_decode_dev(tag->u.core.rootdev);
+ }
+ return 0;
+}
+__tagtable(ATAG_CORE, parse_tag_core);
+
+static int __init parse_tag_mem_range(struct tag *tag,
+ struct tag_mem_range **root)
+{
+ struct tag_mem_range *cur, **pprev;
+ struct tag_mem_range *new;
+
+ /*
+ * Ignore zero-sized entries. If we're running standalone, the
+ * SDRAM code may emit such entries if something goes
+ * wrong...
+ */
+ if (tag->u.mem_range.size == 0)
+ return 0;
+
+ /*
+ * Copy the data so the bootmem init code doesn't need to care
+ * about it.
+ */
+ if (mem_range_next_free >=
+ (sizeof(mem_range_cache) / sizeof(mem_range_cache[0])))
+ panic("Physical memory map too complex!\n");
+
+ new = &mem_range_cache[mem_range_next_free++];
+ *new = tag->u.mem_range;
+
+ pprev = root;
+ cur = *root;
+ while (cur) {
+ pprev = &cur->next;
+ cur = cur->next;
+ }
+
+ *pprev = new;
+ new->next = NULL;
+
+ return 0;
+}
+
+static int __init parse_tag_mem(struct tag *tag)
+{
+ return parse_tag_mem_range(tag, &mem_phys);
+}
+__tagtable(ATAG_MEM, parse_tag_mem);
+
+static int __init parse_tag_cmdline(struct tag *tag)
+{
+ strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+ return 0;
+}
+__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
+
+static int __init parse_tag_rdimg(struct tag *tag)
+{
+ return parse_tag_mem_range(tag, &mem_ramdisk);
+}
+__tagtable(ATAG_RDIMG, parse_tag_rdimg);
+
+static int __init parse_tag_clock(struct tag *tag)
+{
+ /*
+ * We'll figure out the clocks by peeking at the system
+ * manager regs directly.
+ */
+ return 0;
+}
+__tagtable(ATAG_CLOCK, parse_tag_clock);
+
+static int __init parse_tag_rsvd_mem(struct tag *tag)
+{
+ return parse_tag_mem_range(tag, &mem_reserved);
+}
+__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
+
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+#if 0
+ const struct platform_device *pdev;
+
+ /*
+ * We really need a bus type that supports "classes"...this
+ * will do for now (until we must handle other kinds of
+ * ethernet controllers)
+ */
+ pdev = platform_get_device("macb", tag->u.ethernet.mac_index);
+ if (pdev && pdev->dev.platform_data) {
+ struct eth_platform_data *data = pdev->dev.platform_data;
+
+ data->valid = 1;
+ data->mii_phy_addr = tag->u.ethernet.mii_phy_addr;
+ memcpy(data->hw_addr, tag->u.ethernet.hw_address,
+ sizeof(data->hw_addr));
+ }
+#endif
+ return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+/*
+ * Scan the tag table for this tag, and call its parse function. The
+ * tag table is built by the linker from all the __tagtable
+ * declarations.
+ */
+static int __init parse_tag(struct tag *tag)
+{
+ extern struct tagtable __tagtable_begin, __tagtable_end;
+ struct tagtable *t;
+
+ for (t = &__tagtable_begin; t < &__tagtable_end; t++)
+ if (tag->hdr.tag == t->tag) {
+ t->parse(tag);
+ break;
+ }
+
+ return t < &__tagtable_end;
+}
+
+/*
+ * Parse all tags in the list we got from the boot loader
+ */
+static void __init parse_tags(struct tag *t)
+{
+ for (; t->hdr.tag != ATAG_NONE; t = tag_next(t))
+ if (!parse_tag(t))
+ printk(KERN_WARNING
+ "Ignoring unrecognised tag 0x%08x\n",
+ t->hdr.tag);
+}
+
+void __init setup_arch (char **cmdline_p)
+{
+ struct clk *cpu_clk;
+
+ parse_tags(bootloader_tags);
+
+ setup_processor();
+ setup_platform();
+
+ cpu_clk = clk_get(NULL, "cpu");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_WARNING "Warning: Unable to get CPU clock\n");
+ } else {
+ unsigned long cpu_hz = clk_get_rate(cpu_clk);
+
+ /*
+ * Well, duh, but it's probably a good idea to
+ * increment the use count.
+ */
+ clk_enable(cpu_clk);
+
+ boot_cpu_data.clk = cpu_clk;
+ boot_cpu_data.loops_per_jiffy = cpu_hz * 4;
+ printk("CPU: Running at %lu.%03lu MHz\n",
+ ((cpu_hz + 500) / 1000) / 1000,
+ ((cpu_hz + 500) / 1000) % 1000);
+ }
+
+ init_mm.start_code = (unsigned long) &_text;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
+ strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+ parse_early_param();
+
+ setup_bootmem();
+
+ board_setup_fbmem(fbmem_start, fbmem_size);
+
+#ifdef CONFIG_VT
+ conswitchp = &dummy_con;
+#endif
+
+ paging_init();
+
+ resource_init();
+}
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on linux/arch/sh/kernel/signal.c
+ * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/suspend.h>
+
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->sp);
+}
+
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ unsigned long retcode;
+};
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+{
+ int err = 0;
+
+#define COPY(x) err |= __get_user(regs->x, &sc->x)
+ COPY(sr);
+ COPY(pc);
+ COPY(lr);
+ COPY(sp);
+ COPY(r12);
+ COPY(r11);
+ COPY(r10);
+ COPY(r9);
+ COPY(r8);
+ COPY(r7);
+ COPY(r6);
+ COPY(r5);
+ COPY(r4);
+ COPY(r3);
+ COPY(r2);
+ COPY(r1);
+ COPY(r0);
+#undef COPY
+
+ /*
+ * Don't allow anyone to pretend they're running in supervisor
+ * mode or something...
+ */
+ err |= !valid_user_regs(regs);
+
+ return err;
+}
+
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ sigset_t set;
+
+ frame = (struct rt_sigframe __user *)regs->sp;
+ pr_debug("SIG return: frame = %p\n", frame);
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+
+ pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n",
+ regs->pc, regs->lr, regs->sp);
+
+ return regs->r12;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static int
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
+{
+ int err = 0;
+
+#define COPY(x) err |= __put_user(regs->x, &sc->x)
+ COPY(sr);
+ COPY(pc);
+ COPY(lr);
+ COPY(sp);
+ COPY(r12);
+ COPY(r11);
+ COPY(r10);
+ COPY(r9);
+ COPY(r8);
+ COPY(r7);
+ COPY(r6);
+ COPY(r5);
+ COPY(r4);
+ COPY(r3);
+ COPY(r2);
+ COPY(r1);
+ COPY(r0);
+#undef COPY
+
+ return err;
+}
+
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
+{
+ unsigned long sp = regs->sp;
+
+ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void __user *)((sp - framesize) & ~3);
+}
+
+static int
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ err = -EFAULT;
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto out;
+
+ /*
+ * Set up the return code:
+ *
+ * mov r8, __NR_rt_sigreturn
+ * scall
+ *
+ * Note: This will blow up since we're using a non-executable
+ * stack. Better use SA_RESTORER.
+ */
+#if __NR_rt_sigreturn > 127
+# error __NR_rt_sigreturn must be < 127 to fit in a short mov
+#endif
+ err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
+ &frame->retcode);
+
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Set up the ucontext */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(NULL, &frame->uc.uc_link);
+ err |= __put_user((void __user *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->sp),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto out;
+
+ regs->r12 = sig;
+ regs->r11 = (unsigned long) &frame->info;
+ regs->r10 = (unsigned long) &frame->uc;
+ regs->sp = (unsigned long) frame;
+ if (ka->sa.sa_flags & SA_RESTORER)
+ regs->lr = (unsigned long)ka->sa.sa_restorer;
+ else {
+ printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
+ current->comm, current->pid);
+ regs->lr = (unsigned long) &frame->retcode;
+ }
+
+ pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
+ current->comm, current->pid, sig, regs->sp,
+ regs->pc, ka->sa.sa_handler, regs->lr);
+
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+
+out:
+ return err;
+}
+
+static inline void restart_syscall(struct pt_regs *regs)
+{
+ if (regs->r12 == -ERESTART_RESTARTBLOCK)
+ regs->r8 = __NR_restart_syscall;
+ else
+ regs->r12 = regs->r12_orig;
+ regs->pc -= 2;
+}
+
+static inline void
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *oldset, struct pt_regs *regs, int syscall)
+{
+ int ret;
+
+ /*
+ * Set up the stack frame
+ */
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+ /*
+ * Check that the resulting registers are sane
+ */
+ ret |= !valid_user_regs(regs);
+
+ /*
+ * Block the signal if we were unsuccessful.
+ */
+ if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked, ¤t->blocked,
+ &ka->sa.sa_mask);
+ sigaddset(¤t->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+
+ if (ret == 0)
+ return;
+
+ force_sigsegv(sig, current);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it
+ * doesn't want to handle. Thus you cannot kill init even with a
+ * SIGKILL even by mistake.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+
+ /*
+ * We want the common case to go fast, which is why we may in
+ * certain cases get here from kernel mode. Just return
+ * without doing anything if so.
+ */
+ if (!user_mode(regs))
+ return 0;
+
+ if (try_to_freeze()) {
+ signr = 0;
+ if (!signal_pending(current))
+ goto no_signal;
+ }
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = ¤t->saved_sigmask;
+ else if (!oldset)
+ oldset = ¤t->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+no_signal:
+ if (syscall) {
+ switch (regs->r12) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ if (signr > 0) {
+ regs->r12 = -EINTR;
+ break;
+ }
+ /* fall through */
+ case -ERESTARTSYS:
+ if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) {
+ regs->r12 = -EINTR;
+ break;
+ }
+ /* fall through */
+ case -ERESTARTNOINTR:
+ restart_syscall(regs);
+ }
+ }
+
+ if (signr == 0) {
+ /* No signal to deliver -- put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+ }
+ return 0;
+ }
+
+ handle_signal(signr, &ka, &info, oldset, regs, syscall);
+ return 1;
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
+{
+ int syscall = 0;
+
+ if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
+ syscall = 1;
+
+ if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs, ¤t->blocked, syscall);
+}
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/sysreg.h>
+
+ .text
+ .global __switch_to
+ .type __switch_to, @function
+
+ /* Switch thread context from "prev" to "next", returning "last"
+ * r12 : prev
+ * r11 : &prev->thread + 1
+ * r10 : &next->thread
+ */
+__switch_to:
+ stm --r11, r0,r1,r2,r3,r4,r5,r6,r7,sp,lr
+ mfsr r9, SYSREG_SR
+ st.w --r11, r9
+ ld.w r8, r10++
+ /*
+ * schedule() may have been called from a mode with a different
+ * set of registers. Make sure we don't lose anything here.
+ */
+ pushm r10,r12
+ mtsr SYSREG_SR, r8
+ frs /* flush the return stack */
+ sub pc, -2 /* flush the pipeline */
+ popm r10,r12
+ ldm r10++, r0,r1,r2,r3,r4,r5,r6,r7,sp,pc
+ .size __switch_to, . - __switch_to
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/unistd.h>
+
+#include <asm/mman.h>
+#include <asm/uaccess.h>
+
+asmlinkage int sys_pipe(unsigned long __user *filedes)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(filedes, fd, sizeof(fd)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset)
+{
+ int error = -EBADF;
+ struct file *file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ return error;
+ }
+
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, offset);
+ up_write(¤t->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+ return error;
+}
--- /dev/null
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Stubs for syscalls that require access to pt_regs or that take more
+ * than five parameters.
+ */
+
+#define ARG6 r3
+
+ .text
+ .global __sys_rt_sigsuspend
+ .type __sys_rt_sigsuspend,@function
+__sys_rt_sigsuspend:
+ mov r10, sp
+ rjmp sys_rt_sigsuspend
+
+ .global __sys_sigaltstack
+ .type __sys_sigaltstack,@function
+__sys_sigaltstack:
+ mov r10, sp
+ rjmp sys_sigaltstack
+
+ .global __sys_rt_sigreturn
+ .type __sys_rt_sigreturn,@function
+__sys_rt_sigreturn:
+ mov r12, sp
+ rjmp sys_rt_sigreturn
+
+ .global __sys_fork
+ .type __sys_fork,@function
+__sys_fork:
+ mov r12, sp
+ rjmp sys_fork
+
+ .global __sys_clone
+ .type __sys_clone,@function
+__sys_clone:
+ mov r8, sp
+ rjmp sys_clone
+
+ .global __sys_vfork
+ .type __sys_vfork,@function
+__sys_vfork:
+ mov r12, sp
+ rjmp sys_vfork
+
+ .global __sys_execve
+ .type __sys_execve,@function
+__sys_execve:
+ mov r9, sp
+ rjmp sys_execve
+
+ .global __sys_mmap2
+ .type __sys_mmap2,@function
+__sys_mmap2:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_mmap2
+ sub sp, -4
+ popm pc
+
+ .global __sys_sendto
+ .type __sys_sendto,@function
+__sys_sendto:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_sendto
+ sub sp, -4
+ popm pc
+
+ .global __sys_recvfrom
+ .type __sys_recvfrom,@function
+__sys_recvfrom:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_recvfrom
+ sub sp, -4
+ popm pc
+
+ .global __sys_pselect6
+ .type __sys_pselect6,@function
+__sys_pselect6:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_pselect6
+ sub sp, -4
+ popm pc
+
+ .global __sys_splice
+ .type __sys_splice,@function
+__sys_splice:
+ pushm lr
+ st.w --sp, ARG6
+ rcall sys_splice
+ sub sp, -4
+ popm pc
--- /dev/null
+/*
+ * AVR32 system call table
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl sys_ni_syscall
+#endif
+
+#if !defined(CONFIG_SYSV_IPC)
+# define sys_ipc sys_ni_syscall
+#endif
+
+ .section .rodata,"a",@progbits
+ .type sys_call_table,@object
+ .global sys_call_table
+ .align 2
+sys_call_table:
+ .long sys_restart_syscall
+ .long sys_exit
+ .long __sys_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_umask
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long __sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_chown
+ .long sys_lchown
+ .long sys_lseek
+ .long sys_llseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_umount
+ .long sys_setuid
+ .long sys_getuid
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_pause
+ .long sys_utime
+ .long sys_newstat /* 30 */
+ .long sys_newfstat
+ .long sys_newlstat
+ .long sys_access
+ .long sys_chroot
+ .long sys_sync /* 35 */
+ .long sys_fsync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long __sys_clone
+ .long sys_brk /* 45 */
+ .long sys_setgid
+ .long sys_getgid
+ .long sys_getcwd
+ .long sys_geteuid
+ .long sys_getegid /* 50 */
+ .long sys_acct
+ .long sys_setfsuid
+ .long sys_setfsgid
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_setpgid
+ .long sys_mremap
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setreuid /* 60 */
+ .long sys_setregid
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_rt_sigaction
+ .long __sys_rt_sigreturn
+ .long sys_rt_sigprocmask
+ .long sys_rt_sigpending /* 70 */
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long __sys_rt_sigsuspend
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups /* 80 */
+ .long sys_setgroups
+ .long sys_select
+ .long sys_symlink
+ .long sys_fchdir
+ .long sys_readlink /* 85 */
+ .long sys_pread64
+ .long sys_pwrite64
+ .long sys_swapon
+ .long sys_reboot
+ .long __sys_mmap2 /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_wait4
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_vhangup
+ .long __sys_sigaltstack
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_swapoff
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_sendfile
+ .long sys_setdomainname /* 110 */
+ .long sys_newuname
+ .long sys_adjtimex
+ .long sys_mprotect
+ .long __sys_vfork
+ .long sys_init_module /* 115 */
+ .long sys_delete_module
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_bdflush
+ .long sys_sysfs /* 120 */
+ .long sys_personality
+ .long sys_ni_syscall /* reserved for afs_syscall */
+ .long sys_getdents
+ .long sys_flock
+ .long sys_msync /* 125 */
+ .long sys_readv
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl /* 130 */
+ .long sys_mlock
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam /* 135 */
+ .long sys_sched_getparam
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max /* 140 */
+ .long sys_sched_get_priority_min
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_poll
+ .long sys_nfsservctl /* 145 */
+ .long sys_setresgid
+ .long sys_getresgid
+ .long sys_prctl
+ .long sys_socket
+ .long sys_bind /* 150 */
+ .long sys_connect
+ .long sys_listen
+ .long sys_accept
+ .long sys_getsockname
+ .long sys_getpeername /* 155 */
+ .long sys_socketpair
+ .long sys_send
+ .long sys_recv
+ .long __sys_sendto
+ .long __sys_recvfrom /* 160 */
+ .long sys_shutdown
+ .long sys_setsockopt
+ .long sys_getsockopt
+ .long sys_sendmsg
+ .long sys_recvmsg /* 165 */
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64
+ .long sys_lstat64
+ .long sys_fstat64 /* 170 */
+ .long sys_pivot_root
+ .long sys_mincore
+ .long sys_madvise
+ .long sys_getdents64
+ .long sys_fcntl64 /* 175 */
+ .long sys_gettid
+ .long sys_readahead
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr /* 180 */
+ .long sys_getxattr
+ .long sys_lgetxattr
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr /* 185 */
+ .long sys_flistxattr
+ .long sys_removexattr
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_tkill /* 190 */
+ .long sys_sendfile64
+ .long sys_futex
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_capget /* 195 */
+ .long sys_capset
+ .long sys_io_setup
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit /* 200 */
+ .long sys_io_cancel
+ .long sys_fadvise64
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create /* 205 */
+ .long sys_epoll_ctl
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create /* 210 */
+ .long sys_timer_settime
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime /* 215 */
+ .long sys_clock_gettime
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64 /* 220 */
+ .long sys_tgkill
+ .long sys_ni_syscall /* reserved for TUX */
+ .long sys_utimes
+ .long sys_fadvise64_64
+ .long sys_cacheflush /* 225 */
+ .long sys_ni_syscall /* sys_vserver */
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 230 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_kexec_load
+ .long sys_waitid
+ .long sys_add_key /* 235 */
+ .long sys_request_key
+ .long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get
+ .long sys_inotify_init /* 240 */
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_openat
+ .long sys_mkdirat
+ .long sys_mknodat /* 245 */
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_fstatat64
+ .long sys_unlinkat
+ .long sys_renameat /* 250 */
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat
+ .long sys_fchmodat
+ .long sys_faccessat /* 255 */
+ .long __sys_pselect6
+ .long sys_ppoll
+ .long sys_unshare
+ .long sys_set_robust_list
+ .long sys_get_robust_list /* 260 */
+ .long __sys_splice
+ .long sys_sync_file_range
+ .long sys_tee
+ .long sys_vmsplice
+ .long sys_ni_syscall /* r8 is saturated at nr_syscalls */
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Based on MIPS implementation arch/mips/kernel/time.c
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/sysdev.h>
+
+#include <asm/div64.h>
+#include <asm/sysreg.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+static cycle_t read_cycle_count(void)
+{
+ return (cycle_t)sysreg_read(COUNT);
+}
+
+static struct clocksource clocksource_avr32 = {
+ .name = "avr32",
+ .rating = 350,
+ .read = read_cycle_count,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 16,
+ .is_continuous = 1,
+};
+
+/*
+ * By default we provide the null RTC ops
+ */
+static unsigned long null_rtc_get_time(void)
+{
+ return mktime(2004, 1, 1, 0, 0, 0);
+}
+
+static int null_rtc_set_time(unsigned long sec)
+{
+ return 0;
+}
+
+static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
+
+/* how many counter cycles in a jiffy? */
+static unsigned long cycles_per_jiffy;
+
+/* cycle counter value at the previous timer interrupt */
+static unsigned int timerhi, timerlo;
+
+/* the count value for the next timer interrupt */
+static unsigned int expirelo;
+
+static void avr32_timer_ack(void)
+{
+ unsigned int count;
+
+ /* Ack this timer interrupt and set the next one */
+ expirelo += cycles_per_jiffy;
+ if (expirelo == 0) {
+ printk(KERN_DEBUG "expirelo == 0\n");
+ sysreg_write(COMPARE, expirelo + 1);
+ } else {
+ sysreg_write(COMPARE, expirelo);
+ }
+
+ /* Check to see if we have missed any timer interrupts */
+ count = sysreg_read(COUNT);
+ if ((count - expirelo) < 0x7fffffff) {
+ expirelo = count + cycles_per_jiffy;
+ sysreg_write(COMPARE, expirelo);
+ }
+}
+
+static unsigned int avr32_hpt_read(void)
+{
+ return sysreg_read(COUNT);
+}
+
+/*
+ * Taken from MIPS c0_hpt_timer_init().
+ *
+ * Why is it so complicated, and what is "count"? My assumption is
+ * that `count' specifies the "reference cycle", i.e. the cycle since
+ * reset that should mean "zero". The reason COUNT is written twice is
+ * probably to make sure we don't get any timer interrupts while we
+ * are messing with the counter.
+ */
+static void avr32_hpt_init(unsigned int count)
+{
+ count = sysreg_read(COUNT) - count;
+ expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+ sysreg_write(COUNT, expirelo - cycles_per_jiffy);
+ sysreg_write(COMPARE, expirelo);
+ sysreg_write(COUNT, count);
+}
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ /* There must be better ways...? */
+ return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+/*
+ * local_timer_interrupt() does profiling and process accounting on a
+ * per-CPU basis.
+ *
+ * In UP mode, it is invoked from the (global) timer_interrupt.
+ */
+static void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (current->pid)
+ profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(regs));
+}
+
+static irqreturn_t
+timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int count;
+
+ /* ack timer interrupt and try to set next interrupt */
+ count = avr32_hpt_read();
+ avr32_timer_ack();
+
+ /* Update timerhi/timerlo for intra-jiffy calibration */
+ timerhi += count < timerlo; /* Wrap around */
+ timerlo = count;
+
+ /*
+ * Call the generic timer interrupt handler
+ */
+ write_seqlock(&xtime_lock);
+ do_timer(regs);
+ write_sequnlock(&xtime_lock);
+
+ /*
+ * In UP mode, we call local_timer_interrupt() to do profiling
+ * and process accounting.
+ *
+ * SMP is not supported yet.
+ */
+ local_timer_interrupt(irq, dev_id, regs);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction timer_irqaction = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .name = "timer",
+};
+
+void __init time_init(void)
+{
+ unsigned long mult, shift, count_hz;
+ int ret;
+
+ xtime.tv_sec = rtc_get_time();
+ xtime.tv_nsec = 0;
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+ printk("Before time_init: count=%08lx, compare=%08lx\n",
+ (unsigned long)sysreg_read(COUNT),
+ (unsigned long)sysreg_read(COMPARE));
+
+ count_hz = clk_get_rate(boot_cpu_data.clk);
+ shift = clocksource_avr32.shift;
+ mult = clocksource_hz2mult(count_hz, shift);
+ clocksource_avr32.mult = mult;
+
+ printk("Cycle counter: mult=%lu, shift=%lu\n", mult, shift);
+
+ {
+ u64 tmp;
+
+ tmp = TICK_NSEC;
+ tmp <<= shift;
+ tmp += mult / 2;
+ do_div(tmp, mult);
+
+ cycles_per_jiffy = tmp;
+ }
+
+ /* This sets up the high precision timer for the first interrupt. */
+ avr32_hpt_init(avr32_hpt_read());
+
+ printk("After time_init: count=%08lx, compare=%08lx\n",
+ (unsigned long)sysreg_read(COUNT),
+ (unsigned long)sysreg_read(COMPARE));
+
+ ret = clocksource_register(&clocksource_avr32);
+ if (ret)
+ printk(KERN_ERR
+ "timer: could not register clocksource: %d\n", ret);
+
+ ret = setup_irq(0, &timer_irqaction);
+ if (ret)
+ printk("timer: could not request IRQ 0: %d\n", ret);
+}
+
+static struct sysdev_class timer_class = {
+ set_kset_name("timer"),
+};
+
+static struct sys_device timer_device = {
+ .id = 0,
+ .cls = &timer_class,
+};
+
+static int __init init_timer_sysfs(void)
+{
+ int err = sysdev_class_register(&timer_class);
+ if (!err)
+ err = sysdev_register(&timer_device);
+ return err;
+}
+
+device_initcall(init_timer_sysfs);
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#undef DEBUG
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/notifier.h>
+
+#include <asm/traps.h>
+#include <asm/sysreg.h>
+#include <asm/addrspace.h>
+#include <asm/ocd.h>
+#include <asm/mmu_context.h>
+#include <asm/uaccess.h>
+
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+ unsigned long p;
+ int i;
+
+ printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+ for (p = bottom & ~31; p < top; ) {
+ printk("%04lx: ", p & 0xffff);
+
+ for (i = 0; i < 8; i++, p += 4) {
+ unsigned int val;
+
+ if (p < bottom || p >= top)
+ printk(" ");
+ else {
+ if (__get_user(val, (unsigned int __user *)p)) {
+ printk("\n");
+ goto out;
+ }
+ printk("%08x ", val);
+ }
+ }
+ printk("\n");
+ }
+
+out:
+ return;
+}
+
+#ifdef CONFIG_FRAME_POINTER
+static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ unsigned long __user *fp;
+ unsigned long __user *last_fp = NULL;
+
+ if (regs) {
+ fp = (unsigned long __user *)regs->r7;
+ } else if (tsk == current) {
+ register unsigned long __user *real_fp __asm__("r7");
+ fp = real_fp;
+ } else {
+ fp = (unsigned long __user *)tsk->thread.cpu_context.r7;
+ }
+
+ /*
+ * Walk the stack until (a) we get an exception, (b) the frame
+ * pointer becomes zero, or (c) the frame pointer gets stuck
+ * at the same value.
+ */
+ while (fp && fp != last_fp) {
+ unsigned long lr, new_fp = 0;
+
+ last_fp = fp;
+ if (__get_user(lr, fp))
+ break;
+ if (fp && __get_user(new_fp, fp + 1))
+ break;
+ fp = (unsigned long __user *)new_fp;
+
+ printk(" [<%08lx>] ", lr);
+ print_symbol("%s\n", lr);
+ }
+ printk("\n");
+}
+#else
+static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ unsigned long addr;
+
+ while (!kstack_end(sp)) {
+ addr = *sp++;
+ if (kernel_text_address(addr)) {
+ printk(" [<%08lx>] ", addr);
+ print_symbol("%s\n", addr);
+ }
+ }
+}
+#endif
+
+void show_trace(struct task_struct *tsk, unsigned long *sp,
+ struct pt_regs *regs)
+{
+ if (regs &&
+ (((regs->sr & MODE_MASK) == MODE_EXCEPTION) ||
+ ((regs->sr & MODE_MASK) == MODE_USER)))
+ return;
+
+ printk ("Call trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+
+ __show_trace(tsk, sp, regs);
+ printk("\n");
+}
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+ unsigned long stack;
+
+ if (!tsk)
+ tsk = current;
+ if (sp == 0) {
+ if (tsk == current) {
+ register unsigned long *real_sp __asm__("sp");
+ sp = real_sp;
+ } else {
+ sp = (unsigned long *)tsk->thread.cpu_context.ksp;
+ }
+ }
+
+ stack = (unsigned long)sp;
+ dump_mem("Stack: ", stack,
+ THREAD_SIZE + (unsigned long)tsk->thread_info);
+ show_trace(tsk, sp, NULL);
+}
+
+void dump_stack(void)
+{
+ show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+ATOMIC_NOTIFIER_HEAD(avr32_die_chain);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ pr_debug("register_die_notifier: %p\n", nb);
+
+ return atomic_notifier_chain_register(&avr32_die_chain, nb);
+}
+EXPORT_SYMBOL(register_die_notifier);
+
+int unregister_die_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&avr32_die_chain, nb);
+}
+EXPORT_SYMBOL(unregister_die_notifier);
+
+static DEFINE_SPINLOCK(die_lock);
+
+void __die(const char *str, struct pt_regs *regs, unsigned long err,
+ const char *file, const char *func, unsigned long line)
+{
+ struct task_struct *tsk = current;
+ static int die_counter;
+
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+
+ printk(KERN_ALERT "%s", str);
+ if (file && func)
+ printk(" in %s:%s, line %ld", file, func, line);
+ printk("[#%d]:\n", ++die_counter);
+ print_modules();
+ show_regs(regs);
+ printk("Process %s (pid: %d, stack limit = 0x%p)\n",
+ tsk->comm, tsk->pid, tsk->thread_info + 1);
+
+ if (!user_mode(regs) || in_interrupt()) {
+ dump_mem("Stack: ", regs->sp,
+ THREAD_SIZE + (unsigned long)tsk->thread_info);
+ }
+
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+}
+
+void __die_if_kernel(const char *str, struct pt_regs *regs, unsigned long err,
+ const char *file, const char *func, unsigned long line)
+{
+ if (!user_mode(regs))
+ __die(str, regs, err, file, func, line);
+}
+
+asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
+{
+#ifdef CONFIG_SUBARCH_AVR32B
+ /*
+ * The exception entry always saves RSR_EX. For NMI, this is
+ * wrong; it should be RSR_NMI
+ */
+ regs->sr = sysreg_read(RSR_NMI);
+#endif
+
+ printk("NMI taken!!!!\n");
+ die("NMI", regs, ecr);
+ BUG();
+}
+
+asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)
+{
+ printk("Unable to handle critical exception %lu at pc = %08lx!\n",
+ ecr, regs->pc);
+ die("Oops", regs, ecr);
+ BUG();
+}
+
+asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ die_if_kernel("Oops: Address exception in kernel mode", regs, ecr);
+
+#ifdef DEBUG
+ if (ecr == ECR_ADDR_ALIGN_X)
+ pr_debug("Instruction Address Exception at pc = %08lx\n",
+ regs->pc);
+ else if (ecr == ECR_ADDR_ALIGN_R)
+ pr_debug("Data Address Exception (Read) at pc = %08lx\n",
+ regs->pc);
+ else if (ecr == ECR_ADDR_ALIGN_W)
+ pr_debug("Data Address Exception (Write) at pc = %08lx\n",
+ regs->pc);
+ else
+ BUG();
+
+ show_regs(regs);
+#endif
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void __user *)regs->pc;
+
+ force_sig_info(SIGBUS, &info, current);
+}
+
+/* This way of handling undefined instructions is stolen from ARM */
+static LIST_HEAD(undef_hook);
+static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
+
+void register_undef_hook(struct undef_hook *hook)
+{
+ spin_lock_irq(&undef_lock);
+ list_add(&hook->node, &undef_hook);
+ spin_unlock_irq(&undef_lock);
+}
+
+void unregister_undef_hook(struct undef_hook *hook)
+{
+ spin_lock_irq(&undef_lock);
+ list_del(&hook->node);
+ spin_unlock_irq(&undef_lock);
+}
+
+static int do_cop_absent(u32 insn)
+{
+ int cop_nr;
+ u32 cpucr;
+ if ( (insn & 0xfdf00000) == 0xf1900000 )
+ /* LDC0 */
+ cop_nr = 0;
+ else
+ cop_nr = (insn >> 13) & 0x7;
+
+ /* Try enabling the coprocessor */
+ cpucr = sysreg_read(CPUCR);
+ cpucr |= (1 << (24 + cop_nr));
+ sysreg_write(CPUCR, cpucr);
+
+ cpucr = sysreg_read(CPUCR);
+ if ( !(cpucr & (1 << (24 + cop_nr))) ){
+ printk("Coprocessor #%i not found!\n", cop_nr);
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_BUG
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
+{
+ char *file;
+ u16 line;
+ char c;
+
+ if (__get_user(line, (u16 __user *)(regs->pc + 2)))
+ return;
+ if (__get_user(file, (char * __user *)(regs->pc + 4))
+ || (unsigned long)file < PAGE_OFFSET
+ || __get_user(c, file))
+ file = "<bad filename>";
+
+ printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
+}
+#else
+static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
+{
+
+}
+#endif
+#endif
+
+asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
+{
+ u32 insn;
+ struct undef_hook *hook;
+ siginfo_t info;
+ void __user *pc;
+
+ if (!user_mode(regs))
+ goto kernel_trap;
+
+ local_irq_enable();
+
+ pc = (void __user *)instruction_pointer(regs);
+ if (__get_user(insn, (u32 __user *)pc))
+ goto invalid_area;
+
+ if (ecr == ECR_COPROC_ABSENT) {
+ if (do_cop_absent(insn) == 0)
+ return;
+ }
+
+ spin_lock_irq(&undef_lock);
+ list_for_each_entry(hook, &undef_hook, node) {
+ if ((insn & hook->insn_mask) == hook->insn_val) {
+ if (hook->fn(regs, insn) == 0) {
+ spin_unlock_irq(&undef_lock);
+ return;
+ }
+ }
+ }
+ spin_unlock_irq(&undef_lock);
+
+invalid_area:
+
+#ifdef DEBUG
+ printk("Illegal instruction at pc = %08lx\n", regs->pc);
+ if (regs->pc < TASK_SIZE) {
+ unsigned long ptbr, pgd, pte, *p;
+
+ ptbr = sysreg_read(PTBR);
+ p = (unsigned long *)ptbr;
+ pgd = p[regs->pc >> 22];
+ p = (unsigned long *)((pgd & 0x1ffff000) | 0x80000000);
+ pte = p[(regs->pc >> 12) & 0x3ff];
+ printk("page table: 0x%08lx -> 0x%08lx -> 0x%08lx\n", ptbr, pgd, pte);
+ }
+#endif
+
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_addr = (void __user *)regs->pc;
+ switch (ecr) {
+ case ECR_ILLEGAL_OPCODE:
+ case ECR_UNIMPL_INSTRUCTION:
+ info.si_code = ILL_ILLOPC;
+ break;
+ case ECR_PRIVILEGE_VIOLATION:
+ info.si_code = ILL_PRVOPC;
+ break;
+ case ECR_COPROC_ABSENT:
+ info.si_code = ILL_COPROC;
+ break;
+ default:
+ BUG();
+ }
+
+ force_sig_info(SIGILL, &info, current);
+ return;
+
+kernel_trap:
+#ifdef CONFIG_BUG
+ if (__kernel_text_address(instruction_pointer(regs))) {
+ insn = *(u16 *)instruction_pointer(regs);
+ if (insn == AVR32_BUG_OPCODE) {
+ do_bug_verbose(regs, insn);
+ die("Kernel BUG", regs, 0);
+ return;
+ }
+ }
+#endif
+
+ die("Oops: Illegal instruction in kernel code", regs, ecr);
+}
+
+asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ printk("Floating-point exception at pc = %08lx\n", regs->pc);
+
+ /* We have no FPU... */
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_addr = (void __user *)regs->pc;
+ info.si_code = ILL_COPROC;
+
+ force_sig_info(SIGILL, &info, current);
+}
+
+
+void __init trap_init(void)
+{
+
+}
--- /dev/null
+/*
+ * AVR32 linker script for the Linux kernel
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define LOAD_OFFSET 0x00000000
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT("elf32-avr32", "elf32-avr32", "elf32-avr32")
+OUTPUT_ARCH(avr32)
+ENTRY(_start)
+
+/* Big endian */
+jiffies = jiffies_64 + 4;
+
+SECTIONS
+{
+ . = CONFIG_ENTRY_ADDRESS;
+ .init : AT(ADDR(.init) - LOAD_OFFSET) {
+ _stext = .;
+ __init_begin = .;
+ _sinittext = .;
+ *(.text.reset)
+ *(.init.text)
+ _einittext = .;
+ . = ALIGN(4);
+ __tagtable_begin = .;
+ *(.taglist)
+ __tagtable_end = .;
+ *(.init.data)
+ . = ALIGN(16);
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ . = ALIGN(4);
+ __initcall_start = .;
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ __initcall_end = .;
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ __security_initcall_start = .;
+ *(.security_initcall.init)
+ __security_initcall_end = .;
+ . = ALIGN(32);
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+ }
+
+ . = ALIGN(8192);
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ _evba = .;
+ _text = .;
+ *(.ex.text)
+ . = 0x50;
+ *(.tlbx.ex.text)
+ . = 0x60;
+ *(.tlbr.ex.text)
+ . = 0x70;
+ *(.tlbw.ex.text)
+ . = 0x100;
+ *(.scall.text)
+ *(.irq.text)
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ _etext = .;
+ } = 0xd703d703
+
+ . = ALIGN(4);
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ RODATA
+
+ . = ALIGN(8192);
+
+ .data : AT(ADDR(.data) - LOAD_OFFSET) {
+ _data = .;
+ _sdata = .;
+ /*
+ * First, the init task union, aligned to an 8K boundary.
+ */
+ *(.data.init_task)
+
+ /* Then, the cacheline aligned data */
+ . = ALIGN(32);
+ *(.data.cacheline_aligned)
+
+ /* And the rest... */
+ *(.data.rel*)
+ *(.data)
+ CONSTRUCTORS
+
+ _edata = .;
+ }
+
+
+ . = ALIGN(8);
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+ __bss_start = .;
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(8);
+ __bss_stop = .;
+ _end = .;
+ }
+
+ /* When something in the kernel is NOT compiled as a module, the module
+ * cleanup code and data are put into these segments. Both can then be
+ * thrown away, as cleanup code is never called unless it's a module.
+ */
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
+
+ DWARF_DEBUG
+}
--- /dev/null
+#
+# Makefile for AVR32-specific library files
+#
+
+lib-y := copy_user.o clear_user.o
+lib-y += strncpy_from_user.o strnlen_user.o
+lib-y += delay.o memset.o memcpy.o findbit.o
+lib-y += csum_partial.o csum_partial_copy_generic.o
+lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o
+lib-y += __avr32_lsl64.o __avr32_lsr64.o __avr32_asr64.o
--- /dev/null
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /*
+ * DWtype __avr32_asr64(DWtype u, word_type b)
+ */
+ .text
+ .global __avr32_asr64
+ .type __avr32_asr64,@function
+__avr32_asr64:
+ cp.w r12, 0
+ reteq r12
+
+ rsub r9, r12, 32
+ brle 1f
+
+ lsl r8, r11, r9
+ lsr r10, r10, r12
+ asr r11, r11, r12
+ or r10, r8
+ retal r12
+
+1: neg r9
+ asr r10, r11, r9
+ asr r11, 31
+ retal r12
--- /dev/null
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /*
+ * DWtype __avr32_lsl64(DWtype u, word_type b)
+ */
+ .text
+ .global __avr32_lsl64
+ .type __avr32_lsl64,@function
+__avr32_lsl64:
+ cp.w r12, 0
+ reteq r12
+
+ rsub r9, r12, 32
+ brle 1f
+
+ lsr r8, r10, r9
+ lsl r10, r10, r12
+ lsl r11, r11, r12
+ or r11, r8
+ retal r12
+
+1: neg r9
+ lsl r11, r10, r9
+ mov r10, 0
+ retal r12
--- /dev/null
+/*
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /*
+ * DWtype __avr32_lsr64(DWtype u, word_type b)
+ */
+ .text
+ .global __avr32_lsr64
+ .type __avr32_lsr64,@function
+__avr32_lsr64:
+ cp.w r12, 0
+ reteq r12
+
+ rsub r9, r12, 32
+ brle 1f
+
+ lsl r8, r11, r9
+ lsr r11, r11, r12
+ lsr r10, r10, r12
+ or r10, r8
+ retal r12
+
+1: neg r9
+ lsr r10, r11, r9
+ mov r11, 0
+ retal r12
--- /dev/null
+/*
+ * Copyright 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/asm.h>
+
+ .text
+ .align 1
+ .global clear_user
+ .type clear_user, "function"
+clear_user:
+ branch_if_kernel r8, __clear_user
+ ret_if_privileged r8, r12, r11, r11
+
+ .global __clear_user
+ .type __clear_user, "function"
+__clear_user:
+ mov r9, r12
+ mov r8, 0
+ andl r9, 3, COH
+ brne 5f
+
+1: sub r11, 4
+ brlt 2f
+
+10: st.w r12++, r8
+ sub r11, 4
+ brge 10b
+
+2: sub r11, -4
+ reteq 0
+
+ /* Unaligned count or address */
+ bld r11, 1
+ brcc 12f
+11: st.h r12++, r8
+ sub r11, 2
+ reteq 0
+12: st.b r12++, r8
+ retal 0
+
+ /* Unaligned address */
+5: cp.w r11, 4
+ brlt 2b
+
+ lsl r9, 2
+ add pc, pc, r9
+13: st.b r12++, r8
+ sub r11, 1
+14: st.b r12++, r8
+ sub r11, 1
+15: st.b r12++, r8
+ sub r11, 1
+ rjmp 1b
+
+ .size clear_user, . - clear_user
+ .size __clear_user, . - __clear_user
+
+ .section .fixup, "ax"
+ .align 1
+18: sub r11, -4
+19: retal r11
+
+ .section __ex_table, "a"
+ .align 2
+ .long 10b, 18b
+ .long 11b, 19b
+ .long 12b, 19b
+ .long 13b, 19b
+ .long 14b, 19b
+ .long 15b, 19b
--- /dev/null
+/*
+ * Copy to/from userspace with optional address space checking.
+ *
+ * Copyright 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/asm.h>
+
+ /*
+ * __kernel_size_t
+ * __copy_user(void *to, const void *from, __kernel_size_t n)
+ *
+ * Returns the number of bytes not copied. Might be off by
+ * max 3 bytes if we get a fault in the main loop.
+ *
+ * The address-space checking functions simply fall through to
+ * the non-checking version.
+ */
+ .text
+ .align 1
+ .global copy_from_user
+ .type copy_from_user, @function
+copy_from_user:
+ branch_if_kernel r8, __copy_user
+ ret_if_privileged r8, r11, r10, r10
+ rjmp __copy_user
+ .size copy_from_user, . - copy_from_user
+
+ .global copy_to_user
+ .type copy_to_user, @function
+copy_to_user:
+ branch_if_kernel r8, __copy_user
+ ret_if_privileged r8, r12, r10, r10
+ .size copy_to_user, . - copy_to_user
+
+ .global __copy_user
+ .type __copy_user, @function
+__copy_user:
+ mov r9, r11
+ andl r9, 3, COH
+ brne 6f
+
+ /* At this point, from is word-aligned */
+1: sub r10, 4
+ brlt 3f
+
+2:
+10: ld.w r8, r11++
+11: st.w r12++, r8
+ sub r10, 4
+ brge 2b
+
+3: sub r10, -4
+ reteq 0
+
+ /*
+ * Handle unaligned count. Need to be careful with r10 here so
+ * that we return the correct value even if we get a fault
+ */
+4:
+20: ld.ub r8, r11++
+21: st.b r12++, r8
+ sub r10, 1
+ reteq 0
+22: ld.ub r8, r11++
+23: st.b r12++, r8
+ sub r10, 1
+ reteq 0
+24: ld.ub r8, r11++
+25: st.b r12++, r8
+ retal 0
+
+ /* Handle unaligned from-pointer */
+6: cp.w r10, 4
+ brlt 4b
+ rsub r9, r9, 4
+
+30: ld.ub r8, r11++
+31: st.b r12++, r8
+ sub r10, 1
+ sub r9, 1
+ breq 1b
+32: ld.ub r8, r11++
+33: st.b r12++, r8
+ sub r10, 1
+ sub r9, 1
+ breq 1b
+34: ld.ub r8, r11++
+35: st.b r12++, r8
+ sub r10, 1
+ rjmp 1b
+ .size __copy_user, . - __copy_user
+
+ .section .fixup,"ax"
+ .align 1
+19: sub r10, -4
+29: retal r10
+
+ .section __ex_table,"a"
+ .align 2
+ .long 10b, 19b
+ .long 11b, 19b
+ .long 20b, 29b
+ .long 21b, 29b
+ .long 22b, 29b
+ .long 23b, 29b
+ .long 24b, 29b
+ .long 25b, 29b
+ .long 30b, 29b
+ .long 31b, 29b
+ .long 32b, 29b
+ .long 33b, 29b
+ .long 34b, 29b
+ .long 35b, 29b
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+ /*
+ * unsigned int csum_partial(const unsigned char *buff,
+ * int len, unsigned int sum)
+ */
+ .text
+ .global csum_partial
+ .type csum_partial,"function"
+ .align 1
+csum_partial:
+ /* checksum complete words, aligned or not */
+3: sub r11, 4
+ brlt 5f
+4: ld.w r9, r12++
+ add r10, r9
+ acr r10
+ sub r11, 4
+ brge 4b
+
+ /* return if we had a whole number of words */
+5: sub r11, -4
+ reteq r10
+
+ /* checksum any remaining bytes at the end */
+ mov r9, 0
+ mov r8, 0
+ cp r11, 2
+ brlt 6f
+ ld.uh r9, r12++
+ sub r11, 2
+ breq 7f
+ lsl r9, 16
+6: ld.ub r8, r12++
+ lsl r8, 8
+7: or r9, r8
+ add r10, r9
+ acr r10
+
+ retal r10
+ .size csum_partial, . - csum_partial
--- /dev/null
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <asm/errno.h>
+#include <asm/asm.h>
+
+ /*
+ * unsigned int csum_partial_copy_generic(const char *src, char *dst, int len
+ * int sum, int *src_err_ptr,
+ * int *dst_err_ptr)
+ *
+ * Copy src to dst while checksumming, otherwise like csum_partial.
+ */
+
+ .macro ld_src size, reg, ptr
+9999: ld.\size \reg, \ptr
+ .section __ex_table, "a"
+ .long 9999b, fixup_ld_src
+ .previous
+ .endm
+
+ .macro st_dst size, ptr, reg
+9999: st.\size \ptr, \reg
+ .section __ex_table, "a"
+ .long 9999b, fixup_st_dst
+ .previous
+ .endm
+
+ .text
+ .global csum_partial_copy_generic
+ .type csum_partial_copy_generic,"function"
+ .align 1
+csum_partial_copy_generic:
+ pushm r4-r7,lr
+
+ /* The inner loop */
+1: sub r10, 4
+ brlt 5f
+2: ld_src w, r5, r12++
+ st_dst w, r11++, r5
+ add r9, r5
+ acr r9
+ sub r10, 4
+ brge 2b
+
+ /* return if we had a whole number of words */
+5: sub r10, -4
+ brne 7f
+
+6: mov r12, r9
+ popm r4-r7,pc
+
+ /* handle additional bytes at the tail */
+7: mov r5, 0
+ mov r4, 32
+8: ld_src ub, r6, r12++
+ st_dst b, r11++, r6
+ lsl r5, 8
+ sub r4, 8
+ bfins r5, r6, 0, 8
+ sub r10, 1
+ brne 8b
+
+ lsl r5, r5, r4
+ add r9, r5
+ acr r9
+ rjmp 6b
+
+ /* Exception handler */
+ .section .fixup,"ax"
+ .align 1
+fixup_ld_src:
+ mov r9, -EFAULT
+ cp.w r8, 0
+ breq 1f
+ st.w r8[0], r9
+
+1: /*
+ * TODO: zero the complete destination - computing the rest
+ * is too much work
+ */
+
+ mov r9, 0
+ rjmp 6b
+
+fixup_st_dst:
+ mov r9, -EFAULT
+ lddsp r8, sp[20]
+ cp.w r8, 0
+ breq 1f
+ st.w r8[0], r9
+1: mov r9, 0
+ rjmp 6b
+
+ .previous
--- /dev/null
+/*
+ * Precise Delay Loops for avr32
+ *
+ * Copyright (C) 1993 Linus Torvalds
+ * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/delay.h>
+#include <asm/processor.h>
+#include <asm/sysreg.h>
+
+int read_current_timer(unsigned long *timer_value)
+{
+ *timer_value = sysreg_read(COUNT);
+ return 0;
+}
+
+void __delay(unsigned long loops)
+{
+ unsigned bclock, now;
+
+ bclock = sysreg_read(COUNT);
+ do {
+ now = sysreg_read(COUNT);
+ } while ((now - bclock) < loops);
+}
+
+inline void __const_udelay(unsigned long xloops)
+{
+ unsigned long long loops;
+
+ asm("mulu.d %0, %1, %2"
+ : "=r"(loops)
+ : "r"(current_cpu_data.loops_per_jiffy * HZ), "r"(xloops));
+ __delay(loops >> 32);
+}
+
+void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
+}
+
+void __ndelay(unsigned long nsecs)
+{
+ __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+
+ .text
+ /*
+ * unsigned long find_first_zero_bit(const unsigned long *addr,
+ * unsigned long size)
+ */
+ENTRY(find_first_zero_bit)
+ cp.w r11, 0
+ reteq r11
+ mov r9, r11
+1: ld.w r8, r12[0]
+ com r8
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
+
+ /*
+ * unsigned long find_next_zero_bit(const unsigned long *addr,
+ * unsigned long size,
+ * unsigned long offset)
+ */
+ENTRY(find_next_zero_bit)
+ lsr r8, r10, 5
+ sub r9, r11, r10
+ retle r11
+
+ lsl r8, 2
+ add r12, r8
+ andl r10, 31, COH
+ breq 1f
+
+ /* offset is not word-aligned. Handle the first (32 - r10) bits */
+ ld.w r8, r12[0]
+ com r8
+ sub r12, -4
+ lsr r8, r8, r10
+ brne .L_found
+
+ /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
+ add r9, r10
+ sub r9, 32
+ retle r11
+
+ /* Main loop. offset must be word-aligned */
+1: ld.w r8, r12[0]
+ com r8
+ brne .L_found
+ sub r12, -4
+ sub r9, 32
+ brgt 1b
+ retal r11
+
+ /* Common return path for when a bit is actually found. */
+.L_found:
+ brev r8
+ clz r10, r8
+ rsub r9, r11
+ add r10, r9
+
+ /* XXX: If we don't have to return exactly "size" when the bit
+ is not found, we may drop this "min" thing */
+ min r12, r11, r10
+ retal r12
+
+ /*
+ * unsigned long find_first_bit(const unsigned long *addr,
+ * unsigned long size)
+ */
+ENTRY(find_first_bit)
+ cp.w r11, 0
+ reteq r11
+ mov r9, r11
+1: ld.w r8, r12[0]
+ cp.w r8, 0
+ brne .L_found
+ &n