Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

unicore32 core architecture: processor and system headers

This patch includes processor and system headers. System call interface is here.
We used the syscall interface the same as asm-generic version.

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>

+810
+24
arch/unicore32/include/asm/byteorder.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/byteorder.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * UniCore ONLY support Little Endian mode, the data bus is connected such 13 + * that byte accesses appear as: 14 + * 0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31 15 + * and word accesses (data or instruction) appear as: 16 + * d0...d31 17 + */ 18 + #ifndef __UNICORE_BYTEORDER_H__ 19 + #define __UNICORE_BYTEORDER_H__ 20 + 21 + #include <linux/byteorder/little_endian.h> 22 + 23 + #endif 24 +
+45
arch/unicore32/include/asm/cpu-single.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/cpu-single.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #ifndef __UNICORE_CPU_SINGLE_H__ 13 + #define __UNICORE_CPU_SINGLE_H__ 14 + 15 + #include <asm/page.h> 16 + #include <asm/memory.h> 17 + 18 + #ifdef __KERNEL__ 19 + #ifndef __ASSEMBLY__ 20 + 21 + #define cpu_switch_mm(pgd, mm) cpu_do_switch_mm(virt_to_phys(pgd), mm) 22 + 23 + #define cpu_get_pgd() \ 24 + ({ \ 25 + unsigned long pg; \ 26 + __asm__("movc %0, p0.c2, #0" \ 27 + : "=r" (pg) : : "cc"); \ 28 + pg &= ~0x0fff; \ 29 + (pgd_t *)phys_to_virt(pg); \ 30 + }) 31 + 32 + struct mm_struct; 33 + 34 + /* declare all the functions as extern */ 35 + extern void cpu_proc_fin(void); 36 + extern int cpu_do_idle(void); 37 + extern void cpu_dcache_clean_area(void *, int); 38 + extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); 39 + extern void cpu_set_pte(pte_t *ptep, pte_t pte); 40 + extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); 41 + 42 + #endif /* __ASSEMBLY__ */ 43 + #endif /* __KERNEL__ */ 44 + 45 + #endif /* __UNICORE_CPU_SINGLE_H__ */
+33
arch/unicore32/include/asm/cputype.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/cputype.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #ifndef __UNICORE_CPUTYPE_H__ 13 + #define __UNICORE_CPUTYPE_H__ 14 + 15 + #include <linux/stringify.h> 16 + 17 + #define CPUID_CPUID 0 18 + #define CPUID_CACHETYPE 1 19 + 20 + #define read_cpuid(reg) \ 21 + ({ \ 22 + unsigned int __val; \ 23 + asm("movc %0, p0.c0, #" __stringify(reg) \ 24 + : "=r" (__val) \ 25 + : \ 26 + : "cc"); \ 27 + __val; \ 28 + }) 29 + 30 + #define uc32_cpuid read_cpuid(CPUID_CPUID) 31 + #define uc32_cachetype read_cpuid(CPUID_CACHETYPE) 32 + 33 + #endif
+32
arch/unicore32/include/asm/hwcap.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/hwcap.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #ifndef __UNICORE_HWCAP_H__ 13 + #define __UNICORE_HWCAP_H__ 14 + 15 + /* 16 + * HWCAP flags 17 + */ 18 + #define HWCAP_MSP 1 19 + #define HWCAP_UNICORE16 2 20 + #define HWCAP_CMOV 4 21 + #define HWCAP_UNICORE_F64 8 22 + #define HWCAP_TLS 0x80 23 + 24 + #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 25 + /* 26 + * This yields a mask that user programs can use to figure out what 27 + * instruction set this cpu supports. 28 + */ 29 + #define ELF_HWCAP (HWCAP_CMOV | HWCAP_UNICORE_F64) 30 + #endif 31 + 32 + #endif
+92
arch/unicore32/include/asm/processor.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/processor.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #ifndef __UNICORE_PROCESSOR_H__ 14 + #define __UNICORE_PROCESSOR_H__ 15 + 16 + /* 17 + * Default implementation of macro that returns current 18 + * instruction pointer ("program counter"). 19 + */ 20 + #define current_text_addr() ({ __label__ _l; _l: &&_l; }) 21 + 22 + #ifdef __KERNEL__ 23 + 24 + #include <asm/ptrace.h> 25 + #include <asm/types.h> 26 + 27 + #ifdef __KERNEL__ 28 + #define STACK_TOP TASK_SIZE 29 + #define STACK_TOP_MAX TASK_SIZE 30 + #endif 31 + 32 + struct debug_entry { 33 + u32 address; 34 + u32 insn; 35 + }; 36 + 37 + struct debug_info { 38 + int nsaved; 39 + struct debug_entry bp[2]; 40 + }; 41 + 42 + struct thread_struct { 43 + /* fault info */ 44 + unsigned long address; 45 + unsigned long trap_no; 46 + unsigned long error_code; 47 + /* debugging */ 48 + struct debug_info debug; 49 + }; 50 + 51 + #define INIT_THREAD { } 52 + 53 + #define start_thread(regs, pc, sp) \ 54 + ({ \ 55 + unsigned long *stack = (unsigned long *)sp; \ 56 + set_fs(USER_DS); \ 57 + memset(regs->uregs, 0, sizeof(regs->uregs)); \ 58 + regs->UCreg_asr = USER_MODE; \ 59 + regs->UCreg_pc = pc & ~1; /* pc */ \ 60 + regs->UCreg_sp = sp; /* sp */ \ 61 + regs->UCreg_02 = stack[2]; /* r2 (envp) */ \ 62 + regs->UCreg_01 = stack[1]; /* r1 (argv) */ \ 63 + regs->UCreg_00 = stack[0]; /* r0 (argc) */ \ 64 + }) 65 + 66 + /* Forward declaration, a strange C thing */ 67 + struct task_struct; 68 + 69 + /* Free all resources held by a thread. */ 70 + extern void release_thread(struct task_struct *); 71 + 72 + /* Prepare to copy thread state - unlazy all lazy status */ 73 + #define prepare_to_copy(tsk) do { } while (0) 74 + 75 + unsigned long get_wchan(struct task_struct *p); 76 + 77 + #define cpu_relax() barrier() 78 + 79 + /* 80 + * Create a new kernel thread 81 + */ 82 + extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 83 + 84 + #define task_pt_regs(p) \ 85 + ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) 86 + 87 + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->UCreg_pc) 88 + #define KSTK_ESP(tsk) (task_pt_regs(tsk)->UCreg_sp) 89 + 90 + #endif 91 + 92 + #endif /* __UNICORE_PROCESSOR_H__ */
+161
arch/unicore32/include/asm/system.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/system.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #ifndef __UNICORE_SYSTEM_H__ 13 + #define __UNICORE_SYSTEM_H__ 14 + 15 + #ifdef __KERNEL__ 16 + 17 + /* 18 + * CR1 bits (CP#0 CR1) 19 + */ 20 + #define CR_M (1 << 0) /* MMU enable */ 21 + #define CR_A (1 << 1) /* Alignment abort enable */ 22 + #define CR_D (1 << 2) /* Dcache enable */ 23 + #define CR_I (1 << 3) /* Icache enable */ 24 + #define CR_B (1 << 4) /* Dcache write mechanism: write back */ 25 + #define CR_T (1 << 5) /* Burst enable */ 26 + #define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ 27 + 28 + #ifndef __ASSEMBLY__ 29 + 30 + #include <linux/linkage.h> 31 + #include <linux/irqflags.h> 32 + 33 + struct thread_info; 34 + struct task_struct; 35 + 36 + struct pt_regs; 37 + 38 + void die(const char *msg, struct pt_regs *regs, int err); 39 + 40 + struct siginfo; 41 + void uc32_notify_die(const char *str, struct pt_regs *regs, 42 + struct siginfo *info, unsigned long err, unsigned long trap); 43 + 44 + void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, 45 + struct pt_regs *), 46 + int sig, int code, const char *name); 47 + 48 + #define xchg(ptr, x) \ 49 + ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) 50 + 51 + extern asmlinkage void __backtrace(void); 52 + extern asmlinkage void c_backtrace(unsigned long fp, int pmode); 53 + 54 + struct mm_struct; 55 + extern void show_pte(struct mm_struct *mm, unsigned long addr); 56 + extern void __show_regs(struct pt_regs *); 57 + 58 + extern int cpu_architecture(void); 59 + extern void cpu_init(void); 60 + 61 + #define vectors_high() (cr_alignment & CR_V) 62 + 63 + #define isb() __asm__ __volatile__ ("" : : : "memory") 64 + #define dsb() __asm__ __volatile__ ("" : : : "memory") 65 + #define dmb() __asm__ __volatile__ ("" : : : "memory") 66 + 67 + #define mb() barrier() 68 + #define rmb() barrier() 69 + #define wmb() barrier() 70 + #define smp_mb() barrier() 71 + #define smp_rmb() barrier() 72 + #define smp_wmb() barrier() 73 + #define read_barrier_depends() do { } while (0) 74 + #define smp_read_barrier_depends() do { } while (0) 75 + 76 + #define set_mb(var, value) do { var = value; smp_mb(); } while (0) 77 + #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t"); 78 + 79 + extern unsigned long cr_no_alignment; /* defined in entry-unicore.S */ 80 + extern unsigned long cr_alignment; /* defined in entry-unicore.S */ 81 + 82 + static inline unsigned int get_cr(void) 83 + { 84 + unsigned int val; 85 + asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc"); 86 + return val; 87 + } 88 + 89 + static inline void set_cr(unsigned int val) 90 + { 91 + asm volatile("movc p0.c1, %0, #0 @set CR" 92 + : : "r" (val) : "cc"); 93 + isb(); 94 + } 95 + 96 + extern void adjust_cr(unsigned long mask, unsigned long set); 97 + 98 + /* 99 + * switch_to(prev, next) should switch from task `prev' to `next' 100 + * `prev' will never be the same as `next'. schedule() itself 101 + * contains the memory barrier to tell GCC not to cache `current'. 102 + */ 103 + extern struct task_struct *__switch_to(struct task_struct *, 104 + struct thread_info *, struct thread_info *); 105 + extern void panic(const char *fmt, ...); 106 + 107 + #define switch_to(prev, next, last) \ 108 + do { \ 109 + last = __switch_to(prev, \ 110 + task_thread_info(prev), task_thread_info(next)); \ 111 + } while (0) 112 + 113 + static inline unsigned long 114 + __xchg(unsigned long x, volatile void *ptr, int size) 115 + { 116 + unsigned long ret; 117 + 118 + switch (size) { 119 + case 1: 120 + asm volatile("@ __xchg1\n" 121 + " swapb %0, %1, [%2]" 122 + : "=&r" (ret) 123 + : "r" (x), "r" (ptr) 124 + : "memory", "cc"); 125 + break; 126 + case 4: 127 + asm volatile("@ __xchg4\n" 128 + " swapw %0, %1, [%2]" 129 + : "=&r" (ret) 130 + : "r" (x), "r" (ptr) 131 + : "memory", "cc"); 132 + break; 133 + default: 134 + panic("xchg: bad data size: ptr 0x%p, size %d\n", 135 + ptr, size); 136 + } 137 + 138 + return ret; 139 + } 140 + 141 + #include <asm-generic/cmpxchg-local.h> 142 + 143 + /* 144 + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make 145 + * them available. 146 + */ 147 + #define cmpxchg_local(ptr, o, n) \ 148 + ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), \ 149 + (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr)))) 150 + #define cmpxchg64_local(ptr, o, n) \ 151 + __cmpxchg64_local_generic((ptr), (o), (n)) 152 + 153 + #include <asm-generic/cmpxchg.h> 154 + 155 + #endif /* __ASSEMBLY__ */ 156 + 157 + #define arch_align_stack(x) (x) 158 + 159 + #endif /* __KERNEL__ */ 160 + 161 + #endif
+18
arch/unicore32/include/asm/unistd.h
··· 1 + /* 2 + * linux/arch/unicore32/include/asm/unistd.h 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #if !defined(__UNICORE_UNISTD_H__) || defined(__SYSCALL) 13 + #define __UNICORE_UNISTD_H__ 14 + 15 + /* Use the standard ABI for syscalls. */ 16 + #include <asm-generic/unistd.h> 17 + 18 + #endif /* __UNICORE_UNISTD_H__ */
+126
arch/unicore32/kernel/sys.c
··· 1 + /* 2 + * linux/arch/unicore32/kernel/sys.c 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #include <linux/module.h> 13 + #include <linux/errno.h> 14 + #include <linux/sched.h> 15 + #include <linux/slab.h> 16 + #include <linux/mm.h> 17 + #include <linux/sem.h> 18 + #include <linux/msg.h> 19 + #include <linux/shm.h> 20 + #include <linux/stat.h> 21 + #include <linux/syscalls.h> 22 + #include <linux/mman.h> 23 + #include <linux/fs.h> 24 + #include <linux/file.h> 25 + #include <linux/ipc.h> 26 + #include <linux/uaccess.h> 27 + 28 + #include <asm/syscalls.h> 29 + #include <asm/cacheflush.h> 30 + 31 + /* Clone a task - this clones the calling program thread. 32 + * This is called indirectly via a small wrapper 33 + */ 34 + asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp, 35 + void __user *parent_tid, void __user *child_tid, 36 + struct pt_regs *regs) 37 + { 38 + if (!newsp) 39 + newsp = regs->UCreg_sp; 40 + 41 + return do_fork(clone_flags, newsp, regs, 0, 42 + parent_tid, child_tid); 43 + } 44 + 45 + /* sys_execve() executes a new program. 46 + * This is called indirectly via a small wrapper 47 + */ 48 + asmlinkage long __sys_execve(const char __user *filename, 49 + const char __user *const __user *argv, 50 + const char __user *const __user *envp, 51 + struct pt_regs *regs) 52 + { 53 + int error; 54 + char *fn; 55 + 56 + fn = getname(filename); 57 + error = PTR_ERR(fn); 58 + if (IS_ERR(fn)) 59 + goto out; 60 + error = do_execve(fn, argv, envp, regs); 61 + putname(fn); 62 + out: 63 + return error; 64 + } 65 + 66 + int kernel_execve(const char *filename, 67 + const char *const argv[], 68 + const char *const envp[]) 69 + { 70 + struct pt_regs regs; 71 + int ret; 72 + 73 + memset(&regs, 0, sizeof(struct pt_regs)); 74 + ret = do_execve(filename, 75 + (const char __user *const __user *)argv, 76 + (const char __user *const __user *)envp, &regs); 77 + if (ret < 0) 78 + goto out; 79 + 80 + /* 81 + * Save argc to the register structure for userspace. 82 + */ 83 + regs.UCreg_00 = ret; 84 + 85 + /* 86 + * We were successful. We won't be returning to our caller, but 87 + * instead to user space by manipulating the kernel stack. 88 + */ 89 + asm("add r0, %0, %1\n\t" 90 + "mov r1, %2\n\t" 91 + "mov r2, %3\n\t" 92 + "mov r22, #0\n\t" /* not a syscall */ 93 + "mov r23, %0\n\t" /* thread structure */ 94 + "b.l memmove\n\t" /* copy regs to top of stack */ 95 + "mov sp, r0\n\t" /* reposition stack pointer */ 96 + "b ret_to_user" 97 + : 98 + : "r" (current_thread_info()), 99 + "Ir" (THREAD_START_SP - sizeof(regs)), 100 + "r" (&regs), 101 + "Ir" (sizeof(regs)) 102 + : "r0", "r1", "r2", "r3", "ip", "lr", "memory"); 103 + 104 + out: 105 + return ret; 106 + } 107 + EXPORT_SYMBOL(kernel_execve); 108 + 109 + /* Note: used by the compat code even in 64-bit Linux. */ 110 + SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, 111 + unsigned long, prot, unsigned long, flags, 112 + unsigned long, fd, unsigned long, off_4k) 113 + { 114 + return sys_mmap_pgoff(addr, len, prot, flags, fd, 115 + off_4k); 116 + } 117 + 118 + /* Provide the actual syscall number to call mapping. */ 119 + #undef __SYSCALL 120 + #define __SYSCALL(nr, call) [nr] = (call), 121 + 122 + /* Note that we don't include <linux/unistd.h> but <asm/unistd.h> */ 123 + void *sys_call_table[__NR_syscalls] = { 124 + [0 ... __NR_syscalls-1] = sys_ni_syscall, 125 + #include <asm/unistd.h> 126 + };
+145
arch/unicore32/mm/proc-macros.S
··· 1 + /* 2 + * linux/arch/unicore32/mm/proc-macros.S 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + * 12 + * We need constants.h for: 13 + * VMA_VM_MM 14 + * VMA_VM_FLAGS 15 + * VM_EXEC 16 + */ 17 + #include <generated/asm-offsets.h> 18 + #include <asm/thread_info.h> 19 + #include <asm/memory.h> 20 + 21 + /* 22 + * the cache line sizes of the I and D cache are the same 23 + */ 24 + #define CACHE_LINESIZE 32 25 + 26 + /* 27 + * This is the maximum size of an area which will be invalidated 28 + * using the single invalidate entry instructions. Anything larger 29 + * than this, and we go for the whole cache. 30 + * 31 + * This value should be chosen such that we choose the cheapest 32 + * alternative. 33 + */ 34 + #ifdef CONFIG_CPU_UCV2 35 + #define MAX_AREA_SIZE 0x800 /* 64 cache line */ 36 + #endif 37 + 38 + /* 39 + * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm) 40 + */ 41 + .macro vma_vm_mm, rd, rn 42 + ldw \rd, [\rn+], #VMA_VM_MM 43 + .endm 44 + 45 + /* 46 + * vma_vm_flags - get vma->vm_flags 47 + */ 48 + .macro vma_vm_flags, rd, rn 49 + ldw \rd, [\rn+], #VMA_VM_FLAGS 50 + .endm 51 + 52 + .macro tsk_mm, rd, rn 53 + ldw \rd, [\rn+], #TI_TASK 54 + ldw \rd, [\rd+], #TSK_ACTIVE_MM 55 + .endm 56 + 57 + /* 58 + * act_mm - get current->active_mm 59 + */ 60 + .macro act_mm, rd 61 + andn \rd, sp, #8128 62 + andn \rd, \rd, #63 63 + ldw \rd, [\rd+], #TI_TASK 64 + ldw \rd, [\rd+], #TSK_ACTIVE_MM 65 + .endm 66 + 67 + /* 68 + * mmid - get context id from mm pointer (mm->context.id) 69 + */ 70 + .macro mmid, rd, rn 71 + ldw \rd, [\rn+], #MM_CONTEXT_ID 72 + .endm 73 + 74 + /* 75 + * mask_asid - mask the ASID from the context ID 76 + */ 77 + .macro asid, rd, rn 78 + and \rd, \rn, #255 79 + .endm 80 + 81 + .macro crval, clear, mmuset, ucset 82 + .word \clear 83 + .word \mmuset 84 + .endm 85 + 86 + #ifndef CONFIG_CPU_DCACHE_LINE_DISABLE 87 + /* 88 + * va2pa va, pa, tbl, msk, off, err 89 + * This macro is used to translate virtual address to its physical address. 90 + * 91 + * va: virtual address 92 + * pa: physical address, result is stored in this register 93 + * tbl, msk, off: temp registers, will be destroyed 94 + * err: jump to error label if the physical address not exist 95 + * NOTE: all regs must be different 96 + */ 97 + .macro va2pa, va, pa, tbl, msk, off, err=990f 98 + movc \pa, p0.c2, #0 99 + mov \off, \va >> #22 @ off <- index of 1st page table 100 + adr \tbl, 910f @ tbl <- table of 1st page table 101 + 900: @ ---- handle 1, 2 page table 102 + add \pa, \pa, #PAGE_OFFSET @ pa <- virt addr of page table 103 + ldw \pa, [\pa+], \off << #2 @ pa <- the content of pt 104 + cand.a \pa, #4 @ test exist bit 105 + beq \err @ if not exist 106 + and \off, \pa, #3 @ off <- the last 2 bits 107 + add \tbl, \tbl, \off << #3 @ cmove table pointer 108 + ldw \msk, [\tbl+], #0 @ get the mask 109 + ldw pc, [\tbl+], #4 110 + 930: @ ---- handle 2nd page table 111 + and \pa, \pa, \msk @ pa <- phys addr of 2nd pt 112 + mov \off, \va << #10 113 + cntlo \tbl, \msk @ use tbl as temp reg 114 + mov \off, \off >> \tbl 115 + mov \off, \off >> #2 @ off <- index of 2nd pt 116 + adr \tbl, 920f @ tbl <- table of 2nd pt 117 + b 900b 118 + 910: @ 1st level page table 119 + .word 0xfffff000, 930b @ second level page table 120 + .word 0xfffffc00, 930b @ second level large page table 121 + .word 0x00000000, \err @ invalid 122 + .word 0xffc00000, 980f @ super page 123 + 124 + 920: @ 2nd level page table 125 + .word 0xfffff000, 980f @ page 126 + .word 0xffffc000, 980f @ middle page 127 + .word 0xffff0000, 980f @ large page 128 + .word 0x00000000, \err @ invalid 129 + 980: 130 + andn \tbl, \va, \msk 131 + and \pa, \pa, \msk 132 + or \pa, \pa, \tbl 133 + 990: 134 + .endm 135 + #endif 136 + 137 + .macro dcacheline_flush, addr, t1, t2 138 + mov \t1, \addr << #20 139 + ldw \t2, =_stext @ _stext must ALIGN(4096) 140 + add \t2, \t2, \t1 >> #20 141 + ldw \t1, [\t2+], #0x0000 142 + ldw \t1, [\t2+], #0x1000 143 + ldw \t1, [\t2+], #0x2000 144 + ldw \t1, [\t2+], #0x3000 145 + .endm
+134
arch/unicore32/mm/proc-ucv2.S
··· 1 + /* 2 + * linux/arch/unicore32/mm/proc-ucv2.S 3 + * 4 + * Code specific to PKUnity SoC and UniCore ISA 5 + * 6 + * Copyright (C) 2001-2010 GUAN Xue-tao 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + #include <linux/init.h> 13 + #include <linux/linkage.h> 14 + #include <asm/assembler.h> 15 + #include <asm/hwcap.h> 16 + #include <asm/pgtable-hwdef.h> 17 + #include <asm/pgtable.h> 18 + 19 + #include "proc-macros.S" 20 + 21 + ENTRY(cpu_proc_fin) 22 + stm.w (lr), [sp-] 23 + mov ip, #PSR_R_BIT | PSR_I_BIT | PRIV_MODE 24 + mov.a asr, ip 25 + b.l __cpuc_flush_kern_all 26 + ldm.w (pc), [sp]+ 27 + 28 + /* 29 + * cpu_reset(loc) 30 + * 31 + * Perform a soft reset of the system. Put the CPU into the 32 + * same state as it would be if it had been reset, and branch 33 + * to what would be the reset vector. 34 + * 35 + * - loc - location to jump to for soft reset 36 + */ 37 + .align 5 38 + ENTRY(cpu_reset) 39 + mov ip, #0 40 + movc p0.c5, ip, #28 @ Cache invalidate all 41 + nop8 42 + 43 + movc p0.c6, ip, #6 @ TLB invalidate all 44 + nop8 45 + 46 + movc ip, p0.c1, #0 @ ctrl register 47 + or ip, ip, #0x2000 @ vector base address 48 + andn ip, ip, #0x000f @ ............idam 49 + movc p0.c1, ip, #0 @ disable caches and mmu 50 + nop 51 + mov pc, r0 @ jump to loc 52 + nop8 53 + 54 + /* 55 + * cpu_do_idle() 56 + * 57 + * Idle the processor (eg, wait for interrupt). 58 + * 59 + * IRQs are already disabled. 60 + */ 61 + ENTRY(cpu_do_idle) 62 + mov r0, #0 @ PCI address 63 + .rept 8 64 + ldw r1, [r0] 65 + .endr 66 + mov pc, lr 67 + 68 + ENTRY(cpu_dcache_clean_area) 69 + #ifndef CONFIG_CPU_DCACHE_LINE_DISABLE 70 + csub.a r1, #MAX_AREA_SIZE 71 + bsg 101f 72 + mov r9, #PAGE_SZ 73 + sub r9, r9, #1 @ PAGE_MASK 74 + 1: va2pa r0, r10, r11, r12, r13 @ r10 is PA 75 + b 3f 76 + 2: cand.a r0, r9 77 + beq 1b 78 + 3: movc p0.c5, r10, #11 @ clean D entry 79 + nop8 80 + add r0, r0, #CACHE_LINESIZE 81 + add r10, r10, #CACHE_LINESIZE 82 + sub.a r1, r1, #CACHE_LINESIZE 83 + bua 2b 84 + mov pc, lr 85 + #endif 86 + 101: mov ip, #0 87 + movc p0.c5, ip, #10 @ Dcache clean all 88 + nop8 89 + 90 + mov pc, lr 91 + 92 + /* 93 + * cpu_do_switch_mm(pgd_phys) 94 + * 95 + * Set the translation table base pointer to be pgd_phys 96 + * 97 + * - pgd_phys - physical address of new pgd 98 + * 99 + * It is assumed that: 100 + * - we are not using split page tables 101 + */ 102 + .align 5 103 + ENTRY(cpu_do_switch_mm) 104 + movc p0.c2, r0, #0 @ update page table ptr 105 + nop8 106 + 107 + movc p0.c6, ip, #6 @ TLB invalidate all 108 + nop8 109 + 110 + mov pc, lr 111 + 112 + /* 113 + * cpu_set_pte(ptep, pte) 114 + * 115 + * Set a level 2 translation table entry. 116 + * 117 + * - ptep - pointer to level 2 translation table entry 118 + * - pte - PTE value to store 119 + */ 120 + .align 5 121 + ENTRY(cpu_set_pte) 122 + stw r1, [r0] 123 + #ifndef CONFIG_CPU_DCACHE_LINE_DISABLE 124 + sub r2, r0, #PAGE_OFFSET 125 + movc p0.c5, r2, #11 @ Dcache clean line 126 + nop8 127 + #else 128 + mov ip, #0 129 + movc p0.c5, ip, #10 @ Dcache clean all 130 + nop8 131 + @dcacheline_flush r0, r2, ip 132 + #endif 133 + mov pc, lr 134 +