armv8 AArch64 debug notes

1. Summary

The following contents are got from  http://www.linaro.org/projects/armv8/

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.

2. Downloads and more information

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)

3. dma and memory related

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 

documentation for arm64
Yancy@pc:kernel$ vim Documentation/arm64/
booting.txt          memory.txt           tagged-pointers.txt  

3.1 arm64 doesn't allow ioremap RAM
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 

In arm64/mm/ioremap.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);


4. flush cache

In  arch/arm64/include/asm/cacheflush.h
/*
 *	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);

5. arm64 tree

.
├── 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


6. DS5 for armV8 compilation

set PATH="..."
make p=xxx_test m=module i=64
make p=xxx_test m=module i=64 clean
 
Eclipse which is integrated into DS5 can be used for editing source code.
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值