ARM announced its 64-bit ARMv8 architecture and associated ARM compiler and Fast Models in October 2011. As licensees have developed their ARMv8 solutions, Linaro has expanded its focus to include servers and networking and ARMv8 development work has become a major priority at Linaro, enabled by the ARM Fast Models and availability of silicon. During this time, ARM has announced a number of ARMv8 licensees and a majority of these are members of Linaro.
Linaro is making toolchains and software images for AArch64 (the 64-bit execution state of ARMv8) available to interested developers. As there is currently limited availability of ARMv8 hardware, software development for AArch64/A64 has been done using software models also called virtual platforms. This approach has been used in many open source projects. The Linaro provided downloads and ARM’s Fast Models virtual platform enables you to boot a virtual ARMv8 system, run 64-bit binaries and start developing code for ARMv8.
The OpenEmbedded Engineering Builds for ARM’s Virtual Platforms contain Boot Firmware and Linux Kernel images and a selection of Root filesystems. The most recent releases can be found here: http://releases.linaro.org/latest/openembedded/aarch64/
We provide pre-built versions of Linaro GCC and Linaro GDB that target either a Linaro Engineering Build or a bare-metal target. The most recent releases can be found here: http://releases.linaro.org/latest/components/toolchain/binaries/
For more information about ARMv8, ARM provides an overview of the architecture, the AArch64 execution state and the A64 instruction set: http://www.arm.com/products/processors/instruction-set-architectures/armv8-architecture.php For a deep dive into ARMv8, the ARMv8-A Architecture Reference Manual is now publicly available from ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.a_errata1/index.html (Please note that free registration is required to be able to download)
Yancy@pc:kernel$ vim drivers/base/dma- dma-buf.c dma-coherent.c dma-contiguous.c dma-mapping.c
#include "arch/arm64/include/asm/dma-mapping.h"
/** * dmam_alloc_coherent - Managed dma_alloc_coherent() * @dev: Device to allocate coherent memory for * @size: Size of allocation * @dma_handle: Out argument for allocated DMA handle * @gfp: Allocation flags * * Managed dma_alloc_coherent(). Memory allocated using this function * will be automatically released on driver detach. * * RETURNS: * Pointer to allocated memory on success, NULL on failure. */ void * dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) { struct dma_devres *dr; void *vaddr; dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp); if (!dr) return NULL; vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp); if (!vaddr) { devres_free(dr); return NULL; } dr->vaddr = vaddr; dr->dma_handle = *dma_handle; dr->size = size; devres_add(dev, dr); return vaddr; } EXPORT_SYMBOL(dmam_alloc_coherent);
/** * dmam_free_coherent - Managed dma_free_coherent() * @dev: Device to free coherent memory for * @size: Size of allocation * @vaddr: Virtual address of the memory to free * @dma_handle: DMA handle of the memory to free * * Managed dma_free_coherent(). */ void dmam_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { struct dma_devres match_data = { size, vaddr, dma_handle }; dma_free_coherent(dev, size, vaddr, dma_handle); WARN_ON(devres_destroy(dev, dmam_coherent_release, dmam_match, &match_data)); } EXPORT_SYMBOL(dmam_free_coherent);In arch/arm64/include/asm/memory.h
#include <linux/compiler.h> #include <linux/const.h> #include <linux/types.h> #include <asm/sizes.h> /* * Allow for constants defined here to be used from assembly code * by prepending the UL suffix only with actual C code compilation. */ #define UL(x) _AC(x, UL) /* * PAGE_OFFSET - the virtual address of the start of the kernel image. * VA_BITS - the maximum number of bits for virtual addresses. * TASK_SIZE - the maximum size of a user space task. * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. * The module space lives between the addresses given by TASK_SIZE * and PAGE_OFFSET - it must be within 128MB of the kernel text. */ #define PAGE_OFFSET UL(0xffffffc000000000) // This is kernel logical memory map #define MODULES_END (PAGE_OFFSET) #define MODULES_VADDR (MODULES_END - SZ_64M) #define EARLYCON_IOBASE (MODULES_VADDR - SZ_4M) #define VA_BITS (39) #define TASK_SIZE_64 (UL(1) << VA_BITS) #ifdef CONFIG_COMPAT #define TASK_SIZE_32 UL(0x100000000) #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ TASK_SIZE_32 : TASK_SIZE_64) #else #define TASK_SIZE TASK_SIZE_64 #endif /* CONFIG_COMPAT */ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4)) #if TASK_SIZE_64 > MODULES_VADDR #error Top of 64-bit user space clashes with start of module space #endif /* * Physical vs virtual RAM address space conversion. These are * private definitions which should NOT be used outside memory.h * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. */ #define __virt_to_phys(x) (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET)) // virtual_addr - 0x80000000 + 0xffffffc000000000 #define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET)) // physical_addr - 0xffffffc000000000 + 0x80000000 /* * Convert a physical address to a Page Frame Number and back */ #define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) #define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) /* * Convert a page to/from a physical address */ #define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) #define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) /* * Memory types available. */ #define MT_DEVICE_nGnRnE 0 #define MT_DEVICE_nGnRE 1 #define MT_DEVICE_GRE 2 #define MT_NORMAL_NC 3 #define MT_NORMAL 4 #ifndef __ASSEMBLY__ extern phys_addr_t memstart_addr; // 0x80000000 /* PHYS_OFFSET - the physical address of the start of memory. */ #define PHYS_OFFSET ({ memstart_addr; }) /* * PFNs are used to describe any physical page; this means * PFN 0 == physical address 0. * * This is the PFN of the first RAM page in the kernel * direct-mapped view. We assume this is the first page * of RAM in the mem_map as well. */ #define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) /* * Note: Drivers should NOT use these. They are the wrong * translation for translating DMA addresses. Use the driver * DMA support - see dma-mapping.h. */ static inline phys_addr_t virt_to_phys(const volatile void *x) { return __virt_to_phys((unsigned long)(x)); } static inline void *phys_to_virt(phys_addr_t x) { return (void *)(__phys_to_virt(x)); } /* * Drivers should NOT use these either. */ #define __pa(x) __virt_to_phys((unsigned long)(x)) // __pa == virt_to_phys #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) // __va == phys_to_virt #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) /* * virt_to_page(k) convert a _valid_ virtual address to struct page * * virt_addr_valid(k) indicates whether a virtual address is valid */ #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ ((void *)(kaddr) < (void *)high_memory)) #endif #include <asm-generic/memory_model.h>
AArch64 Linux memory layout: Start End Size Use ----------------------------------------------------------------------- 0000000000000000 0000007fffffffff 512GB user ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc ffffffbbffff0000 ffffffbbffffffff 64KB [guard page] ffffffbc00000000 ffffffbdffffffff 8GB vmemmap ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] ffffffbffbc00000 ffffffbffbdfffff 2MB earlyprintk device ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space ffffffbbffff0000 ffffffbcffffffff ~2MB [guard] ffffffbffc000000 ffffffbfffffffff 64MB modules ffffffc000000000 ffffffffffffffff 256GB kernel logical memory map
Yancy@pc:kernel$ vim Documentation/arm64/ booting.txt memory.txt tagged-pointers.txt
Yancy@pc:kernel$ git grep memblock_is_memory arch/arm64/mm/init.c: return memblock_is_memory(pfn << PAGE_SHIFT); drivers/iommu/exynos-iommu.c: BUG_ON(!memblock_is_memory(pgtable)); include/linux/memblock.h:int memblock_is_memory(phys_addr_t addr); mm/memblock.c:int __init_memblock memblock_is_memory(phys_addr_t addr) Yancy@pc:kernel$ vim mm/memblock.c
static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, pgprot_t prot, void *caller) { unsigned long last_addr; unsigned long offset = phys_addr & ~PAGE_MASK; int err; unsigned long addr; struct vm_struct *area; /* * Page align the mapping address and size, taking account of any * offset. */ phys_addr &= PAGE_MASK; size = PAGE_ALIGN(size + offset); /* * Don't allow wraparound, zero size or outside PHYS_MASK. */ last_addr = phys_addr + size - 1; if (!size || last_addr < phys_addr || (last_addr & ~PHYS_MASK)) return NULL; /* * Don't allow RAM to be mapped. */ if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr)))) // Here ram ioremap is disabled. return NULL; area = get_vm_area_caller(size, VM_IOREMAP, caller); if (!area) return NULL; addr = (unsigned long)area->addr; err = ioremap_page_range(addr, addr + size, phys_addr, prot); if (err) { vunmap((void *)addr); return NULL; } return (void __iomem *)(offset + addr); } void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot) { return __ioremap_caller(phys_addr, size, prot, __builtin_return_address(0)); } EXPORT_SYMBOL(__ioremap); void __iounmap(volatile void __iomem *io_addr) { void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); vunmap(addr); } EXPORT_SYMBOL(__iounmap);
/* * MM Cache Management * =================== * * The arch/arm64/mm/cache.S implements these methods. * * Start addresses are inclusive and end addresses are exclusive; start * addresses should be rounded down, end addresses up. * * See Documentation/cachetlb.txt for more information. Please note that * the implementation assumes non-aliasing VIPT D-cache and (aliasing) * VIPT or ASID-tagged VIVT I-cache. * * flush_cache_all() * * Unconditionally clean and invalidate the entire cache. * * flush_cache_mm(mm) * * Clean and invalidate all user space cache entries * before a change of page tables. * * flush_icache_range(start, end) * * Ensure coherency between the I-cache and the D-cache in the * region described by start, end. * - start - virtual start address * - end - virtual end address * * __flush_cache_user_range(start, end) * * Ensure coherency between the I-cache and the D-cache in the * region described by start, end. * - start - virtual start address * - end - virtual end address * * __flush_dcache_area(kaddr, size) * * Ensure that the data held in page is written back. * - kaddr - page address * - size - region size */ extern void flush_cache_all(void); extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_icache_range(unsigned long start, unsigned long end); extern void __flush_dcache_area(void *addr, size_t len); extern void __flush_cache_user_range(unsigned long start, unsigned long end);
. ├── arm64_tree.txt ├── boot │ ├── dts │ │ ├── foundation-v8.dts │ │ ├── Makefile │ │ ├── rtsm_ve-aemv8a.dts │ │ ├── rtsm_ve-motherboard.dtsi │ │ ├── skeleton.dtsi │ │ ├── sprd_tsharkl.dtb │ │ └── sprd_tsharkl.dts │ ├── Image │ ├── Image.gz │ ├── install.sh │ └── Makefile ├── configs │ ├── defconfig │ └── tsharkl_defconfig ├── include │ ├── asm │ │ ├── arch_timer.h │ │ ├── asm-offsets.h │ │ ├── assembler.h │ │ ├── atomic.h │ │ ├── barrier.h │ │ ├── bitops.h │ │ ├── cacheflush.h │ │ ├── cache.h │ │ ├── cachetype.h │ │ ├── cmpxchg.h │ │ ├── compat.h │ │ ├── compiler.h │ │ ├── cpu_ops.h │ │ ├── cputable.h │ │ ├── cputype.h │ │ ├── debug-monitors.h │ │ ├── device.h │ │ ├── dma-mapping.h │ │ ├── elf.h │ │ ├── esr.h │ │ ├── exception.h │ │ ├── exec.h │ │ ├── fb.h │ │ ├── fpsimd.h │ │ ├── fpsimdmacros.h │ │ ├── futex.h │ │ ├── gpio.h │ │ ├── hardirq.h │ │ ├── hw_breakpoint.h │ │ ├── hwcap.h │ │ ├── io.h │ │ ├── irqflags.h │ │ ├── irq.h │ │ ├── Kbuild │ │ ├── linkage.h │ │ ├── memblock.h │ │ ├── memory.h │ │ ├── mmu_context.h │ │ ├── mmu.h │ │ ├── module.h │ │ ├── page.h │ │ ├── percpu.h │ │ ├── perf_event.h │ │ ├── pgalloc.h │ │ ├── pgtable-2level-hwdef.h │ │ ├── pgtable-2level-types.h │ │ ├── pgtable-3level-hwdef.h │ │ ├── pgtable-3level-types.h │ │ ├── pgtable.h │ │ ├── pgtable-hwdef.h │ │ ├── pmu.h │ │ ├── processor.h │ │ ├── proc-fns.h │ │ ├── prom.h │ │ ├── psci.h │ │ ├── ptrace.h │ │ ├── shmparam.h │ │ ├── sigcontext.h │ │ ├── signal32.h │ │ ├── smp.h │ │ ├── smp_plat.h │ │ ├── sparsemem.h │ │ ├── spinlock.h │ │ ├── spinlock_types.h │ │ ├── stacktrace.h │ │ ├── stat.h │ │ ├── string.h │ │ ├── suspend.h │ │ ├── syscall.h │ │ ├── syscalls.h │ │ ├── system_misc.h │ │ ├── thread_info.h │ │ ├── timex.h │ │ ├── tlbflush.h │ │ ├── tlb.h │ │ ├── topology.h │ │ ├── traps.h │ │ ├── uaccess.h │ │ ├── ucontext.h │ │ ├── unistd32.h │ │ ├── unistd.h │ │ ├── vdso_datapage.h │ │ ├── vdso.h │ │ └── virt.h │ ├── generated │ │ ├── asm │ │ │ ├── bug.h │ │ │ ├── bugs.h │ │ │ ├── checksum.h │ │ │ ├── clkdev.h │ │ │ ├── cputime.h │ │ │ ├── current.h │ │ │ ├── delay.h │ │ │ ├── div64.h │ │ │ ├── dma.h │ │ │ ├── emergency-restart.h │ │ │ ├── errno.h │ │ │ ├── ftrace.h │ │ │ ├── hw_irq.h │ │ │ ├── ioctl.h │ │ │ ├── ioctls.h │ │ │ ├── ipcbuf.h │ │ │ ├── irq_regs.h │ │ │ ├── kdebug.h │ │ │ ├── kmap_types.h │ │ │ ├── kvm_para.h │ │ │ ├── local64.h │ │ │ ├── local.h │ │ │ ├── mman.h │ │ │ ├── msgbuf.h │ │ │ ├── mutex.h │ │ │ ├── pci.h │ │ │ ├── poll.h │ │ │ ├── posix_types.h │ │ │ ├── resource.h │ │ │ ├── scatterlist.h │ │ │ ├── sections.h │ │ │ ├── segment.h │ │ │ ├── sembuf.h │ │ │ ├── serial.h │ │ │ ├── shmbuf.h │ │ │ ├── sizes.h │ │ │ ├── socket.h │ │ │ ├── sockios.h │ │ │ ├── swab.h │ │ │ ├── switch_to.h │ │ │ ├── termbits.h │ │ │ ├── termios.h │ │ │ ├── topology.h │ │ │ ├── trace_clock.h │ │ │ ├── types.h │ │ │ ├── unaligned.h │ │ │ ├── user.h │ │ │ ├── vga.h │ │ │ └── xor.h │ │ └── uapi │ │ └── asm │ │ └── kvm_para.h │ └── uapi │ └── asm │ ├── auxvec.h │ ├── bitsperlong.h │ ├── byteorder.h │ ├── fcntl.h │ ├── hwcap.h │ ├── Kbuild │ ├── param.h │ ├── ptrace.h │ ├── setup.h │ ├── sigcontext.h │ ├── siginfo.h │ ├── signal.h │ ├── statfs.h │ ├── stat.h │ └── unistd.h ├── Kconfig ├── Kconfig.debug ├── kernel │ ├── arm64ksyms.c │ ├── asm-offsets.c │ ├── asm-offsets.s │ ├── built-in.o │ ├── cpu_ops.c │ ├── cputable.c │ ├── debug-monitors.c │ ├── early_printk.c │ ├── entry-fpsimd.S │ ├── entry.S │ ├── fpsimd.c │ ├── head.S │ ├── hw_breakpoint.c │ ├── hw_breakpoint.o │ ├── hyp-stub.S │ ├── io.c │ ├── irq.c │ ├── kuser32.S │ ├── Makefile │ ├── module.c │ ├── modules.builtin │ ├── modules.order │ ├── perf_event.c │ ├── process.c │ ├── psci.c │ ├── ptrace.c │ ├── setup.c │ ├── signal32.c │ ├── signal.c │ ├── sleep.S │ ├── smp.c │ ├── smp_spin_table.c │ ├── stacktrace.c │ ├── suspend.c │ ├── sys32.S │ ├── sys.c │ ├── sys_compat.c │ ├── time.c │ ├── topology.c │ ├── traps.c │ ├── vdso │ │ ├── built-in.o │ │ ├── gen_vdso_offsets.sh │ │ ├── gettimeofday.S │ │ ├── Makefile │ │ ├── modules.builtin │ │ ├── modules.order │ │ ├── note.S │ │ ├── sigreturn.S │ │ ├── vdso.lds │ │ ├── vdso.lds.S │ │ ├── vdso-offsets.h │ │ ├── vdso.S │ │ ├── vdso.so │ │ └── vdso.so.dbg │ ├── vdso.c │ ├── vmlinux.lds │ └── vmlinux.lds.S ├── lib │ ├── bitops.S │ ├── built-in.o │ ├── clear_page.S │ ├── clear_user.S │ ├── copy_from_user.S │ ├── copy_in_user.S │ ├── copy_page.S ││ ├── copy_to_user.S │ ├── delay.c │ ├── lib.a │ ├── Makefile │ ├── memchr.S │ ├── memcpy.S │ ├── memmove.S │ ├── memset.S │ ├── modules.builtin │ ├── modules.order │ ├── strchr.S │ ├── strncpy_from_user.S │ ├── strnlen_user.S │ └── strrchr.S ├── Makefile └── mm ├── built-in.o ├── cache.o ├── cache.S ├── context.c ├── context.o ├── copypage.c ├── dma-mapping.c ├── extable.c ├── fault.c ├── flush.c ├── init.c ├── ioremap.c ├── Makefile ├── mmap.c ├── mm.h ├── mmu.c ├── modules.builtin ├── modules.order ├── pgd.c ├── proc-macros.S ├── proc.S └── tlb.S 15 directories, 328 files