@@ -0,0 +1,207 @@+/*+*Copyright (C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include <linux/linkage.h>+#include <asm/unistd.h>+#include <asm/assembler.h>+#include <asm/nds32.h>+#include <asm/asm-offsets.h>+#include <asm/thread_info.h>+#include <asm/current.h>++#define why $r8+++.macropop_zol+#ifdef CONFIG_HWZOL+mtusr$r14,$LB+mtusr$r15,$LE+mtusr$r16,$LC+#endif+.endm++.macrorestore_user_regs_first+setgie.d+isb++addi$sp,$sp,FUCOP_CTL_OFFSET++lmw.adm$r12,[$sp],$r24,#0x0+mtsr$r12,$SP_USR+mtsr$r13,$IPC+#ifdef CONFIG_HWZOL+pop_zol+#endif+mtsr$r19,$PSW+mtsr$r20,$IPSW+mtsr$r21,$P_IPSW+mtsr$r22,$P_IPC+mtsr$r23,$P_P0+mtsr$r24,$P_P1+lmw.adm$sp,[$sp],$sp,#0xe+.endm++.macrorestore_user_regs_last+pop$p0+cmovn$sp,$p0,$p0++iret+nop++.endm++.macrorestore_user_regs+restore_user_regs_first+lmw.adm$r0,[$sp],$r25,#0x0+addi$sp,$sp,OSP_OFFSET+restore_user_regs_last+.endm++.macrofast_restore_user_regs+restore_user_regs_first+lmw.adm$r1,[$sp],$r25,#0x0+addi$sp,$sp,OSP_OFFSET-4+restore_user_regs_last+.endm++#ifdef CONFIG_PREEMPT+.macropreempt_stop+.endm+#else+.macropreempt_stop+setgie.d+isb+.endm+#define resume_kernel no_work_pending+#endif++ENTRY(ret_from_exception)+preempt_stop+ENTRY(ret_from_intr)+movewhy,#0 ! not system call++/*+*judgeKernelorusermode+*+*/+lwi$p0,[$sp+(#IPSW_OFFSET)] ! Check if in nested interrupt+andi$p0,$p0,#PSW_mskINTL+bnez$p0,resume_kernel!donewithiret+jresume_userspace+++/*+*Thisisthefastsyscallreturnpath.Wedoaslittleas+*possiblehere,andthisincludessaving$r0backintotheSVC+*stack.+*fixed:tsk-$r25,why-$r8,$r7-syscall#, $r8 - syscall table pointer+*/+ENTRY(ret_fast_syscall)+gie_disable+lwi$r1,[tsk+#TSK_TI_FLAGS]+andi$p1,$r1,#_TIF_WORK_MASK+bnez$p1,fast_work_pending+fast_restore_user_regs!iret++/*+*Ok,weneedtodoextraprocessing,+*entertheslowpathreturningfromsyscall,whilependingwork.+*/+fast_work_pending:+swi$r0,[$sp+(#R0_OFFSET)] ! what is different from ret_from_exception+movewhy,#1 ! come from a syscall+work_pending:+andi$p1,$r1,#_TIF_NEED_RESCHED+bnez$p1,work_resched++andi$p1,$r1,#_TIF_SIGPENDING|#_TIF_NOTIFY_RESUME+beqz$p1,no_work_pending++move$r0,$sp!'regs'+move$r2,why+gie_enable+baldo_notify_resume+beqz$r0,ret_slow_syscall+bgtz$r0,1f+movi$r7,#__NR_restart_syscall+1:+beh_syscall_phase_2+work_resched:+balschedule!path,returntousermode++/*+*"slow"syscallreturnpath.+*"why"tellsusifthiswasarealsyscall.+*/+ENTRY(resume_userspace)+ENTRY(ret_slow_syscall)+gie_disable+lwi$p0,[$sp+(#IPSW_OFFSET)] ! Check if in nested interrupt+andi$p0,$p0,#PSW_mskINTL+bnez$p0,no_work_pending!donewithiret+lwi$r1,[tsk+#TSK_TI_FLAGS]+andi$p1,$r1,#_TIF_WORK_MASK+bnez$p1,work_pending!handlework_resched,sig_pend++no_work_pending:+#ifdef CONFIG_TRACE_IRQFLAGS+lwi$p0,[$sp+(#IPSW_OFFSET)]+andi$p0,$p0,#0x1+la$r10,arch_trace_hardirqs_off+la$r9,arch_trace_hardirqs_on+cmovz$r9,$p0,$r10+jral$r9+#endif+restore_user_regs!returnfromiret+++/*+*preemptivekernel+*/+#ifdef CONFIG_PREEMPT+resume_kernel:+gie_disable+lwi$t0,[tsk+#TSK_TI_PREEMPT]+bnez$t0,no_work_pending+need_resched:+lwi$t0,[tsk+#TSK_TI_FLAGS]+andi$p1,$t0,#_TIF_NEED_RESCHED+beqz$p1,no_work_pending++lwi$t0,[$sp+(#IPSW_OFFSET)] ! Interrupts off?+andi$t0,$t0,#1+beqz$t0,no_work_pending++jalpreempt_schedule_irq+bneed_resched+#endif++/*+*Thisishowwereturnfromafork.+*/+ENTRY(ret_from_fork)+balschedule_tail+beqz$r6,1f!r6storesfnforkernelthread+move$r0,$r7!preparekernelthreadarg+jral$r6+1:+lwi$r1,[tsk+#TSK_TI_FLAGS] ! check for syscall tracing+movewhy,#1+andi$p1,$r1,#_TIF_WORK_SYSCALL_LEAVE ! are we tracing syscalls?+beqz$p1,ret_slow_syscall+move$r0,$sp+balsyscall_trace_leave+bret_slow_syscall
@@ -0,0 +1,608 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/module.h>+#include<linux/sched.h>+#include<linux/mm.h>+#include<asm/nds32.h>+#include<asm/pgtable.h>+#include<asm/tlbflush.h>+#include<asm/cacheflush.h>+#ifdef CONFIG_CACHE_L2+#include<asm/l2_cache.h>+#endif+#include<nds32_intrinsic.h>++#include<asm/cache_info.h>+externstructcache_infoL1_cache_info[2];++intva_kernel_present(unsignedlongaddr)+{+pmd_t*pmd;+pte_t*ptep,pte;++pmd=pmd_offset(pgd_offset_k(addr),addr);+if(!pmd_none(*pmd)){+ptep=pte_offset_map(pmd,addr);+pte=*ptep;+if(pte_present(pte))+returnpte;+}+return0;+}++pte_tva_present(structmm_struct*mm,unsignedlongaddr)+{+pgd_t*pgd;+pud_t*pud;+pmd_t*pmd;+pte_t*ptep,pte;++pgd=pgd_offset(mm,addr);+if(!pgd_none(*pgd)){+pud=pud_offset(pgd,addr);+if(!pud_none(*pud)){+pmd=pmd_offset(pud,addr);+if(!pmd_none(*pmd)){+ptep=pte_offset_map(pmd,addr);+pte=*ptep;+if(pte_present(pte))+returnpte;+}+}+}+return0;++}++intva_readable(structpt_regs*regs,unsignedlongaddr)+{+structmm_struct*mm=current->mm;+pte_tpte;+intret=0;++if(user_mode(regs)){+/* user mode */+pte=va_present(mm,addr);+if(!pte&&pte_read(pte))+ret=1;+}else{+/* superuser mode is always readable, so we can only+*checkitispresentornot*/+return(!!va_kernel_present(addr));+}+returnret;+}++intva_writable(structpt_regs*regs,unsignedlongaddr)+{+structmm_struct*mm=current->mm;+pte_tpte;+intret=0;++if(user_mode(regs)){+/* user mode */+pte=va_present(mm,addr);+if(!pte&&pte_write(pte))+ret=1;+}else{+/* superuser mode */+pte=va_kernel_present(addr);+if(!pte&&pte_kernel_write(pte))+ret=1;+}+returnret;+}++/*+*All+*/+voidn13_icache_inval_all(void)+{+unsignedlongend,line_size;++line_size=L1_cache_info[ICACHE].line_size;+end=+line_size*L1_cache_info[ICACHE].ways*L1_cache_info[ICACHE].sets;++do{+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_IX_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_IX_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_IX_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_IX_INVAL"::"r"(end));+}while(end>0);+}++voidn13_dcache_inval_all(void)+{+__nds32__cctl_l1d_invalall();+}++voidn13_dcache_wb_all(void)+{+#ifdef CONFIG_CACHE_L2+if(atl2c_base)+__nds32__cctl_l1d_wball_alvl();+else+__nds32__cctl_l1d_wball_one_lvl();+#else+__nds32__cctl_l1d_wball_one_lvl();+#endif+}++voidn13_dcache_wbinval_all(void)+{+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+unsignedlongflags;+#endif++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+local_irq_save(flags);+#endif+#ifdef CONFIG_CACHE_L2+if(atl2c_base)+__nds32__cctl_l1d_wball_alvl();+else+__nds32__cctl_l1d_wball_one_lvl();+#else+__nds32__cctl_l1d_wball_one_lvl();+#endif+__nds32__cctl_l1d_invalall();+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+local_irq_restore(flags);+#endif+}++/*+*Page+*/+voidn13_icache_inval_page(unsignedlongstart)+{+unsignedlongline_size,end;++line_size=L1_cache_info[ICACHE].line_size;+end=start+PAGE_SIZE;++do{+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_VA_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_VA_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_VA_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1I_VA_INVAL"::"r"(end));+}while(end!=start);+}++voidn13_dcache_inval_page(unsignedlongstart)+{+unsignedlongline_size,end;++line_size=L1_cache_info[DCACHE].line_size;+end=start+PAGE_SIZE;++do{+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+}while(end!=start);+}++voidn13_dcache_wb_page(unsignedlongstart)+{+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+unsignedlongline_size,end;++line_size=L1_cache_info[DCACHE].line_size;+end=start+PAGE_SIZE;++do{+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+end-=line_size;+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+}while(end!=start);+#endif+}++voidn13_dcache_wbinval_page(unsignedlongstart)+{+unsignedlongline_size,end;++line_size=L1_cache_info[DCACHE].line_size;+end=start+PAGE_SIZE;++do{+end-=line_size;+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+#endif+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+end-=line_size;+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+#endif+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+end-=line_size;+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+#endif+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+end-=line_size;+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(end));+#endif+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(end));+}while(end!=start);+}++voidn13_cache_wbinval_page(unsignedlongpage,intflushi)+{+n13_dcache_wbinval_page(page);+if(flushi)+n13_icache_inval_page(page);+}++/*+*Range+*/+voidn13_icache_inval_range(unsignedlongstart,unsignedlongend)+{+unsignedlongline_size;++line_size=L1_cache_info[ICACHE].line_size;++while(end>start){+__asm__volatile("\n\tcctl %0, L1I_VA_INVAL"::"r"(start));+start+=line_size;+}+}++voidn13_dcache_inval_range(unsignedlongstart,unsignedlongend)+{+unsignedlongline_size;++line_size=L1_cache_info[DCACHE].line_size;++while(end>start){+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(start));+start+=line_size;+}+}++voidn13_dcache_wb_range(unsignedlongstart,unsignedlongend)+{+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+unsignedlongline_size;++line_size=L1_cache_info[DCACHE].line_size;++while(end>start){+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(start));+start+=line_size;+}+#endif+}++voidn13_dcache_wbinval_range(unsignedlongstart,unsignedlongend)+{+unsignedlongline_size;++line_size=L1_cache_info[DCACHE].line_size;++while(end>start){+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH+__asm__volatile("\n\tcctl %0, L1D_VA_WB"::"r"(start));+#endif+__asm__volatile("\n\tcctl %0, L1D_VA_INVAL"::"r"(start));+start+=line_size;+}+}++voidn13_cache_wbinval_range(unsignedlongstart,unsignedlongend,intflushi)+{+unsignedlongline_size,align_start,align_end;++line_size=L1_cache_info[DCACHE].line_size;+align_start=start&~(line_size-1);+align_end=(end+line_size-1)&~(line_size-1);+n13_dcache_wbinval_range(align_start,align_end);++if(flushi){+line_size=L1_cache_info[ICACHE].line_size;+align_start=start&~(line_size-1);+align_end=(end+line_size-1)&~(line_size-1);+n13_icache_inval_range(align_start,align_end);+}+}++voidn13_cache_wbinval_range_check(structvm_area_struct*vma,+unsignedlongstart,unsignedlongend,+boolflushi,boolwbd)+{+unsignedlongline_size,t_start,t_end;++if(!flushi&&!wbd)+return;+line_size=L1_cache_info[DCACHE].line_size;+start=start&~(line_size-1);+end=(end+line_size-1)&~(line_size-1);++if((end-start)>(8*PAGE_SIZE)){+if(wbd)+n13_dcache_wbinval_all();+if(flushi)+n13_icache_inval_all();+return;+}++t_start=(start+PAGE_SIZE)&PAGE_MASK;+t_end=((end-1)&PAGE_MASK);++if((start&PAGE_MASK)==t_end){+if(va_present(vma->vm_mm,start)){+if(wbd)+n13_dcache_wbinval_range(start,end);+if(flushi)+n13_icache_inval_range(start,end);+}+return;+}++if(va_present(vma->vm_mm,start)){+if(wbd)+n13_dcache_wbinval_range(start,end);+if(flushi)+n13_icache_inval_range(start,end);+}++if(va_present(vma->vm_mm,end-1)){+if(wbd)+n13_dcache_wbinval_range(start,end);+if(flushi)+n13_icache_inval_range(start,end);+}++while(t_start<t_end){+if(va_present(vma->vm_mm,t_start)){+if(wbd)+n13_dcache_wbinval_page(t_start);+if(flushi)+n13_icache_inval_page(t_start);+}+t_start+=PAGE_SIZE;+}+}++/*+*DMA+*/+voidn13_dma_wb_range(unsignedlongstart,unsignedlongend)+{+unsignedlongline_size;+unsignedlongflags;+line_size=L1_cache_info[DCACHE].line_size;+start=start&(~(line_size-1));+end=(end+line_size-1)&(~(line_size-1));+if(unlikely(start==end))+return;++local_irq_save(flags);+n13_dcache_wb_range(start,end);++#ifdef CONFIG_CACHE_L2+if(atl2c_base){+unsignedlongp_start=__pa(start);+unsignedlongp_end=__pa(end);+unsignedlongcmd;+/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */+line_size=L2_CACHE_LINE_SIZE();+p_start=p_start&(~(line_size-1));+p_end=(p_end+line_size-1)&(~(line_size-1));+cmd=+(p_start&~(line_size-1))|CCTL_CMD_L2_PA_WB|+CCTL_SINGLE_CMD;+do{+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+cmd+=line_size;+p_start+=line_size;+}while(p_end>p_start);+cmd=CCTL_CMD_L2_SYNC;+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+L2_CMD_RDY();++}+#endif+local_irq_restore(flags);+}++#ifdef CONFIG_CACHE_L2+voidn13_l2dcache_wbinval_range(unsignedlongstart,unsignedlongend)+{+unsignedlongp_start;+unsignedlongp_end;+unsignedlongcmd;+unsignedlongline_size;++p_start=__pa(start);+p_end=__pa(end);+/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */+line_size=L2_CACHE_LINE_SIZE();+p_start=p_start&(~(line_size-1));+p_end=(p_end+line_size-1)&(~(line_size-1));+cmd=+(p_start&~(line_size-1))|CCTL_CMD_L2_PA_WBINVAL|+CCTL_SINGLE_CMD;+do{+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+cmd+=line_size;+p_start+=line_size;+}while(p_end>p_start);+cmd=CCTL_CMD_L2_SYNC;+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+L2_CMD_RDY();++}+#endif++voidn13_dma_inval_range(unsignedlongstart,unsignedlongend)+{+unsignedlongline_size;+unsignedlongold_start=start;+unsignedlongold_end=end;+unsignedlongflags;+line_size=L1_cache_info[DCACHE].line_size;+start=start&(~(line_size-1));+end=(end+line_size-1)&(~(line_size-1));+if(unlikely(start==end))+return;+local_irq_save(flags);+if(start!=old_start){+n13_dcache_wbinval_range(start,start+line_size);+#ifdef CONFIG_CACHE_L2+if(atl2c_base)+n13_l2dcache_wbinval_range(start,start+line_size);+#endif+}+if(end!=old_end){+n13_dcache_wbinval_range(end-line_size,end);+#ifdef CONFIG_CACHE_L2+if(atl2c_base)+n13_l2dcache_wbinval_range(end-line_size,end);+#endif+}+n13_dcache_inval_range(start,end);+#ifdef CONFIG_CACHE_L2+if(atl2c_base){+unsignedlongp_start=__pa(start);+unsignedlongp_end=__pa(end);+unsignedlongcmd;+/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */+line_size=L2_CACHE_LINE_SIZE();+p_start=p_start&(~(line_size-1));+p_end=(p_end+line_size-1)&(~(line_size-1));+cmd=+(p_start&~(line_size-1))|CCTL_CMD_L2_PA_INVAL|+CCTL_SINGLE_CMD;+do{+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+cmd+=line_size;+p_start+=line_size;+}while(p_end>p_start);+cmd=CCTL_CMD_L2_SYNC;+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+L2_CMD_RDY();+}+#endif+local_irq_restore(flags);++}++voidn13_dma_wbinval_range(unsignedlongstart,unsignedlongend)+{+unsignedlongline_size;+unsignedlongflags;+line_size=L1_cache_info[DCACHE].line_size;+start=start&(~(line_size-1));+end=(end+line_size-1)&(~(line_size-1));+if(unlikely(start==end))+return;++local_irq_save(flags);+n13_dcache_wbinval_range(start,end);+#ifdef CONFIG_CACHE_L2+if(atl2c_base){+unsignedlongp_start=__pa(start);+unsignedlongp_end=__pa(end);+unsignedlongcmd;++/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */+line_size=L2_CACHE_LINE_SIZE();+p_start=p_start&(~(line_size-1));+p_end=(p_end+line_size-1)&(~(line_size-1));+cmd=+(p_start&~(line_size-1))|CCTL_CMD_L2_PA_WBINVAL|+CCTL_SINGLE_CMD;+do{+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+cmd+=line_size;+p_start+=line_size;+}while(p_end>p_start);+cmd=CCTL_CMD_L2_SYNC;+L2_CMD_RDY();+L2C_W_REG(L2_CCTL_CMD_OFF,cmd);+L2_CMD_RDY();++}+#endif+local_irq_restore(flags);+}++voidn13_proc_init(void)+{+}++voidn13_proc_fin(void)+{+}++voidn13_do_idle(void)+{+__nds32__standby_no_wake_grant();+}++voidn13_reset(unsignedlongreset)+{+u32tmp;+GIE_DISABLE();+tmp=__nds32__mfsr(NDS32_SR_CACHE_CTL);+tmp&=~(CACHE_CTL_mskIC_EN|CACHE_CTL_mskDC_EN);+__nds32__mtsr_isb(tmp,NDS32_SR_CACHE_CTL);+n13_dcache_wbinval_all();+n13_icache_inval_all();++__asm____volatile__("jr.toff %0\n\t"::"r"(reset));+}++voidn13_switch_mm(structmm_struct*mm)+{+unsignedlongcid;+cid=__nds32__mfsr(NDS32_SR_TLB_MISC);+cid=(cid&~TLB_MISC_mskCID)|mm->context.id;+__nds32__mtsr_dsb(cid,NDS32_SR_TLB_MISC);+__nds32__mtsr_isb(__pa(mm->pgd),NDS32_SR_L1_PPTB);+}
@@ -0,0 +1,203 @@+/*+*Accesstousersystemcallparametersandresults+*+*Copyright(C)2008-2009RedHat,Inc.Allrightsreserved.+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thiscopyrightedmaterialismadeavailabletoanyonewishingtouse,+*modify,copy,orredistributeitsubjecttothetermsandconditions+*oftheGNUGeneralPublicLicensev.2.+*+*Thisfileisastubprovidingdocumentationforwhatfunctions+*asm-ARCH/syscall.hfilesneedtodefine.Mostarchdefinitions+*willbesimpleinlines.+*+*Allofthesefunctionsexpecttobecalledwithnolocks,+*andonlywhenthecallerissurethatthetaskofinterest+*cannotreturntousermodewhilewearelookingatit.+*/++#ifndef _ASM_NDS32_SYSCALL_H+#define _ASM_NDS32_SYSCALL_H 1++#include<linux/err.h>+structtask_struct;+structpt_regs;++/**+*syscall_get_nr-findwhatsystemcallataskisexecuting+*@task:taskofinterest,mustbeblocked+*@regs:task_pt_regs()of@task+*+*If@taskisexecutingasystemcallorisatsystemcall+*tracingabouttoattemptone,returnsthesystemcallnumber.+*If@taskisnotexecutingasystemcall,i.e.it'sblocked+*insidethekernelforafaultorsignal,returns-1.+*+*Notethisreturnsintevenon64-bitmachines.Only32bitsof+*systemcallnumbercanbemeaningful.Iftheactualarchvalue+*is64bits,thistruncatesto32bitsso0xffffffffmeans-1.+*+*It'sonlyvalidtocallthiswhen@taskisknowntobeblocked.+*/+intsyscall_get_nr(structtask_struct*task,structpt_regs*regs)+{+returnregs->syscallno;+}++/**+*syscall_rollback-rollbackregistersafteranabortedsystemcall+*@task:taskofinterest,mustbeinsystemcallexittracing+*@regs:task_pt_regs()of@task+*+*It'sonlyvalidtocallthiswhen@taskisstoppedforsystem+*callexittracing(duetoTIF_SYSCALL_TRACEorTIF_SYSCALL_AUDIT),+*aftertracehook_report_syscall_entry()returnednonzerotoprevent+*thesystemcallfromtakingplace.+*+*Thisrollsbacktheregisterstatein@regssoit'sasifthe+*systemcallinstructionwasano-op.Theregisterscontaining+*thesystemcallnumberandargumentsareastheywerebeforethe+*systemcallinstruction.Thismaynotbethesameaswhatthe+*registerstatelookedlikeatsystemcallentrytracing.+*/+voidsyscall_rollback(structtask_struct*task,structpt_regs*regs)+{+regs->uregs[0]=regs->orig_r0;+}++/**+*syscall_get_error-checkresultoftracedsystemcall+*@task:taskofinterest,mustbeblocked+*@regs:task_pt_regs()of@task+*+*Returns0ifthesystemcallsucceeded,or-ERRORCODEifitfailed.+*+*It'sonlyvalidtocallthiswhen@taskisstoppedfortracingonexit+*fromasystemcall,dueto%TIF_SYSCALL_TRACEor%TIF_SYSCALL_AUDIT.+*/+longsyscall_get_error(structtask_struct*task,structpt_regs*regs)+{+unsignedlongerror=regs->uregs[0];+returnIS_ERR_VALUE(error)?error:0;+}++/**+*syscall_get_return_value-getthereturnvalueofatracedsystemcall+*@task:taskofinterest,mustbeblocked+*@regs:task_pt_regs()of@task+*+*Returnsthereturnvalueofthesuccessfulsystemcall.+*Thisvalueismeaninglessifsyscall_get_error()returnednonzero.+*+*It'sonlyvalidtocallthiswhen@taskisstoppedfortracingonexit+*fromasystemcall,dueto%TIF_SYSCALL_TRACEor%TIF_SYSCALL_AUDIT.+*/+longsyscall_get_return_value(structtask_struct*task,structpt_regs*regs)+{+returnregs->uregs[0];+}++/**+*syscall_set_return_value-changethereturnvalueofatracedsystemcall+*@task:taskofinterest,mustbeblocked+*@regs:task_pt_regs()of@task+*@error:negativeerrorcode,orzerotoindicatesuccess+*@val:userreturnvalueif@erroriszero+*+*Thischangestheresultsofthesystemcallthatusermodewillsee.+*If@erroriszero,theuserseesasuccessfulsystemcallwitha+*returnvalueof@val.If@errorisnonzero,it'sanegatederrno+*code;theuserseesafailedsystemcallwiththiserrnocode.+*+*It'sonlyvalidtocallthiswhen@taskisstoppedfortracingonexit+*fromasystemcall,dueto%TIF_SYSCALL_TRACEor%TIF_SYSCALL_AUDIT.+*/+voidsyscall_set_return_value(structtask_struct*task,structpt_regs*regs,+interror,longval)+{+regs->uregs[0]=(long)error?error:val;+}++/**+*syscall_get_arguments-extractsystemcallparametervalues+*@task:taskofinterest,mustbeblocked+*@regs:task_pt_regs()of@task+*@i:argumentindex[0,5]+*@n:numberofarguments;n+imustbe[1,6].+*@args:arrayfilledwithargumentvalues+*+*Fetches@nargumentstothesystemcallstartingwiththe@i'thargument+*(from0through5).Argument@iisstoredin@args[0],andsoon.+*Anarchinlineversionisprobablyoptimalwhen@iand@nareconstants.+*+*It'sonlyvalidtocallthiswhen@taskisstoppedfortracingon+*entrytoasystemcall,dueto%TIF_SYSCALL_TRACEor%TIF_SYSCALL_AUDIT.+*It'sinvalidtocallthiswith@i+@n>6;weonlysupportsystemcalls+*takingupto6arguments.+*/+#define SYSCALL_MAX_ARGS 6+voidsyscall_get_arguments(structtask_struct*task,structpt_regs*regs,+unsignedinti,unsignedintn,unsignedlong*args)+{+if(n==0)+return;+if(i+n>SYSCALL_MAX_ARGS){+unsignedlong*args_bad=args+SYSCALL_MAX_ARGS-i;+unsignedintn_bad=n+i-SYSCALL_MAX_ARGS;+pr_warning("%s called with max args %d, handling only %d\n",+__func__,i+n,SYSCALL_MAX_ARGS);+memset(args_bad,0,n_bad*sizeof(args[0]));+memset(args_bad,0,n_bad*sizeof(args[0]));+}++if(i==0){+args[0]=regs->orig_r0;+args++;+i++;+n--;+}++memcpy(args,®s->uregs[0]+i,n*sizeof(args[0]));+}++/**+*syscall_set_arguments-changesystemcallparametervalue+*@task:taskofinterest,mustbeinsystemcallentrytracing+*@regs:task_pt_regs()of@task+*@i:argumentindex[0,5]+*@n:numberofarguments;n+imustbe[1,6].+*@args:arrayofargumentvaluestostore+*+*Changes@nargumentstothesystemcallstartingwiththe@i'thargument.+*Argument@igetsvalue@args[0],andsoon.+*Anarchinlineversionisprobablyoptimalwhen@iand@nareconstants.+*+*It'sonlyvalidtocallthiswhen@taskisstoppedfortracingon+*entrytoasystemcall,dueto%TIF_SYSCALL_TRACEor%TIF_SYSCALL_AUDIT.+*It'sinvalidtocallthiswith@i+@n>6;weonlysupportsystemcalls+*takingupto6arguments.+*/+voidsyscall_set_arguments(structtask_struct*task,structpt_regs*regs,+unsignedinti,unsignedintn,+constunsignedlong*args)+{+if(n==0)+return;++if(i+n>SYSCALL_MAX_ARGS){+pr_warn("%s called with max args %d, handling only %d\n",+__func__,i+n,SYSCALL_MAX_ARGS);+n=SYSCALL_MAX_ARGS-i;+}++if(i==0){+regs->orig_r0=args[0];+args++;+i++;+n--;+}++memcpy(®s->uregs[0]+i,args,n*sizeof(args[0]));+}+#endif /* _ASM_NDS32_SYSCALL_H */
@@ -0,0 +1,146 @@+/*+*Copyright (C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include <linux/linkage.h>+#include <asm/unistd.h>+#include <asm/assembler.h>+#include <asm/nds32.h>+#include <asm/asm-offsets.h>+#include <asm/thread_info.h>+#include <asm/current.h>++/*+*$r0=previoustask_struct,+*$r1=nexttask_struct,+*previousandnextareguaranteednottobethesame.+*/++ENTRY(__switch_to)++la$p0,__entry_task+sw$r1,[$p0]+move$p1,$r0+addi$p1,$p1,#THREAD_CPU_CONTEXT+smw.bi$r6,[$p1],$r14,#0xb ! push r6~r14, fp, lp, sp+move$r25,$r1+addi$r1,$r1,#THREAD_CPU_CONTEXT+lmw.bi$r6,[$r1],$r14,#0xb ! pop r6~r14, fp, lp, sp+ret++/*+*Thesearetheregistersusedinthesyscallhandler,andallowus+*tohaveintheoryupto6argumentstoafunction-$r0to$r5.+*+*Wemustsetatleast"tsk"and"tbl"whencallingret_with_reschedule.+*/+#define tbl $r8 // syscall table pointer++/*+*$r7willbewritenassyscallnr+*byretrievingfrom$ITYPE'SWID'bitfiled+*/+.macroget_scno+mfsr$r7,$ITYPE+srli$r7,$r7,#ITYPE_offSWID+swi$r7,[$sp+SYSCALLNO_OFFSET]+.endm++.macroupdateipc+addi$r17,$r13,#4 ! $r13 is $IPC+swi$r17,[$sp+IPC_OFFSET]+.endm++ENTRY(eh_syscall)+updateipc++get_scno+gie_enable++ENTRY(eh_syscall_phase_2)+lwi$p0,[tsk+#TSK_TI_FLAGS] ! check for syscall tracing++andi$p1,$p0,#_TIF_WORK_SYSCALL_ENTRY ! are we tracing syscalls?+bnez$p1,__sys_trace++la$lp,ret_fast_syscall!returnaddress+jmp_systbl:+addi$p1,$r7,#-__NR_syscalls ! syscall number of syscall instruction is guarded by addembler+bgez$p1,_SCNO_EXCEED!callsys_*routine+latbl,sys_call_table!loadsyscalltablepointer+slli$p1,$r7,#2+add$p1,tbl,$p1+lwi$p1,[$p1]+jr$p1!noreturn++_SCNO_EXCEED:+ori$r0,$r7,#0+ori$r1,$sp,#0+bbad_syscall++/*+*Thisisthereallyslowpath.We're going to be doing+*contextswitches,andwaitingforourparenttorespond.+*/+__sys_trace:+move$r1,$sp+move$r0,$r7!traceentry[IP=0]+balsyscall_trace_enter+move$r7,$r0+la$lp,__sys_trace_return!returnaddress++addi$p1,$r7,#1+beqz$p1,ret_slow_syscall!fatalsignalispending++addi$p1,$sp,#R0_OFFSET ! pointer to regs+lmw.bi$r0,[$p1],$r5!havetoreload$r0-$r5+bjmp_systbl++__sys_trace_return:+swi$r0,[$sp+#R0_OFFSET] ! T: save returned $r0+move$r0,$sp!setpt_regsforsyscall_trace_leave+balsyscall_trace_leave+bret_slow_syscall++/*+*Specialsystemcallwrappers+*+*$r0=syscallnumber+*$r8=syscalltable+*/+.typesys_syscall,#function+ENTRY(sys_syscall)+addi$p1,$r0,#-__NR_syscalls+bgtz$p1,3f+move$p1,$r0+move$r0,$r1+move$r1,$r2+move$r2,$r3+move$r3,$r4+move$r4,$r5+!addforsyscall6args+lwi$r5,[$sp+#SP_OFFSET ]+lwi$r5,[$r5]+!~addforsyscall6args++lw$p1,[tbl+$p1<<2]+jr$p1+3:bsys_ni_syscall+ENDPROC(sys_syscall)++ENTRY(sys_rt_sigreturn_wrapper)+addi$r0,$sp,#0+bsys_rt_sigreturn+ENDPROC(sys_rt_sigreturn_wrapper)
@@ -0,0 +1,54 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/module.h>+#include<linux/string.h>+#include<linux/delay.h>+#include<linux/in6.h>+#include<linux/syscalls.h>++#include<asm/checksum.h>+#include<asm/io.h>+#include<asm/uaccess.h>+#include<asm/ftrace.h>+#include<asm/proc-fns.h>++/* mem functions */+EXPORT_SYMBOL(memset);+EXPORT_SYMBOL(memcpy);+EXPORT_SYMBOL(memmove);+EXPORT_SYMBOL(memzero);++/* user mem (segment) */+EXPORT_SYMBOL(__arch_copy_from_user);+EXPORT_SYMBOL(__arch_copy_to_user);+EXPORT_SYMBOL(__arch_clear_user);++EXPORT_SYMBOL(__get_user_1);+EXPORT_SYMBOL(__get_user_2);+EXPORT_SYMBOL(__get_user_4);+EXPORT_SYMBOL(__get_user_8);++EXPORT_SYMBOL(__put_user_1);+EXPORT_SYMBOL(__put_user_2);+EXPORT_SYMBOL(__put_user_4);+EXPORT_SYMBOL(__put_user_8);++/* cache handling */+EXPORT_SYMBOL(cpu_icache_inval_all);+EXPORT_SYMBOL(cpu_dcache_wbinval_all);+EXPORT_SYMBOL(cpu_dma_inval_range);+EXPORT_SYMBOL(cpu_dma_wb_range);
@@ -0,0 +1,93 @@+/*+*Copyright (C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include <linux/linkage.h>++.text++ENTRY(memcpy)+move$r5,$r0+beq$r0,$r1,quit_memcpy+beqz$r2,quit_memcpy+srli$r3,$r2,#5 ! check if len < cache-line size 32+beqz$r3,word_copy_entry+andi$r4,$r0,#0x3 ! check byte-align+beqz$r4,unalign_word_copy_entry++addi$r4,$r4,#-4+abs$r4,$r4!checkhowmanyun-alignbytetocopy+sub$r2,$r2,$r4!update$R2++unalign_byte_copy:+lbi.bi$r3,[$r1],#1+addi$r4,$r4,#-1+sbi.bi$r3,[$r0],#1+bnez$r4,unalign_byte_copy+beqz$r2,quit_memcpy++unalign_word_copy_entry:+andi$r3,$r0,0x1f!checkcache-lineunaligncount+beqz$r3,cache_copy++addi$r3,$r3,#-32+abs$r3,$r3+sub$r2,$r2,$r3!update$R2++unalign_word_copy:+lmw.bim$r4,[$r1],$r4+addi$r3,$r3,#-4+smw.bim$r4,[$r0],$r4+bnez$r3,unalign_word_copy+beqz$r2,quit_memcpy++addi$r3,$r2,#-32 ! to check $r2< cache_line , than go to word_copy+bltz$r3,word_copy_entry+cache_copy:+srli$r3,$r2,#5+beqz$r3,word_copy_entry+pushm$r6,$r13+3:+lmw.bim$r6,[$r1],$r13+addi$r3,$r3,#-1+smw.bim$r6,[$r0],$r13+bnez$r3,3b+popm$r6,$r13++word_copy_entry:+andi$r2,$r2,#31++beqz$r2,quit_memcpy+5:+srli$r3,$r2,#2+beqz$r3,byte_copy+word_copy:+lmw.bim$r4,[$r1],$r4+addi$r3,$r3,#-1+smw.bim$r4,[$r0],$r4+bnez$r3,word_copy+andi$r2,$r2,#3+beqz$r2,quit_memcpy+byte_copy:+lbi.bi$r3,[$r1],#1+addi$r2,$r2,#-1++sbi.bi$r3,[$r0],#1+bnez$r2,byte_copy+quit_memcpy:+move$r0,$r5+ret++ENDPROC(memcpy)
@@ -0,0 +1,83 @@+/*+*Copyright (C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include <linux/linkage.h>++/*+void*memmove(void*dst,constvoid*src,intn);++dst:$r0+src:$r1+n:$r2+ret:$r0-pointertothememoryareadst.+*/+.text++ENTRY(memmove)+move$r5,$r0!Setreturnvalue=det+beq$r0,$r1,exit_memcpy!Exitwhendet=src+beqz$r2,exit_memcpy!Exitwhenn=0+pushm$t0,$t1!Savereg+srli$p1,$r2,#2 ! $p1 is how many words to copy++!Avoiddatalostwhenmemoryoverlap+!Copydatareverselywhensrc<dst+slt$p0,$r0,$r1!checkif$r0<$r1+beqz$p0,do_reverse!branchifdst>src++!Noreverse,dst<src+andi$r2,$r2,#3 ! How many bytes are less than a word+li$t0,#1 ! Determining copy direction in byte_cpy+beqz$p1,byte_cpy!Whennislessthanaword++word_cpy:+lmw.bim$p0,[$r1],$p0!Readawordfromsrc+addi$p1,$p1,#-1 ! How many words left to copy+smw.bim$p0,[$r0],$p0!Copythewordtodet+bnez$p1,word_cpy!Ifremainedwords>0+beqz$r2,end_memcpy!Noleftbytestocopy+bbyte_cpy++do_reverse:+add$r0,$r0,$r2!Startwiththeendof$r0+add$r1,$r1,$r2!Startwiththeendof$r1+andi$r2,$r2,#3 ! How many bytes are less than a word+li$t0,#-1 ! Determining copy direction in byte_cpy+beqz$p1,reverse_byte_cpy!Whennislessthanaword++reverse_word_cpy:+lmw.adm$p0,[$r1],$p0!Readawordfromsrc+addi$p1,$p1,#-1 ! How many words left to copy+smw.adm$p0,[$r0],$p0!Copythewordtodet+bnez$p1,reverse_word_cpy!Ifremainedwords>0+beqz$r2,end_memcpy!Noleftbytestocopy++reverse_byte_cpy:+addi$r0,$r0,#-1+addi$r1,$r1,#-1+byte_cpy:!Lessthan4bytestocopynow+lb.bi$p0,[$r1],$t0!Readabytefromsrc+addi$r2,$r2,#-1 ! How many bytes left to copy+sb.bi$p0,[$r0],$t0!copythebytetodet+bnez$r2,byte_cpy!Ifremainedbytes>0++end_memcpy:+popm$t0,$t1+exit_memcpy:+move$r0,$r5+ret++ENDPROC(memmove)
@@ -0,0 +1,46 @@+/*+*Copyright (C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include <linux/linkage.h>++.text+ENTRY(memset)+move$r5,$r0!Returnvalue+beqz$r2,end_memset!Exitwhenlen=0+srli$p1,$r2,2!$p1ishowmanywordstocopy+andi$r2,$r2,3!Howmanybytesarelessthanaword+beqz$p1,byte_set!Whennislessthanaword++!set$r1from??????abtoabababab+andi$r1,$r1,#0x00ff ! $r1 = 000000ab+slli$p0,$r1,#8 ! $p0 = 0000ab00+or$r1,$r1,$p0!$r1=0000abab+slli$p0,$r1,#16 ! $p0 = abab0000+or$r1,$r1,$p0!$r1=abababab+word_set:+addi$p1,$p1,#-1 ! How many words left to copy+smw.bim$r1,[$r0],$r1!Copythewordtodet+bnez$p1,word_set!Stillwordstoset,continuelooping+beqz$r2,end_memset!Noleftbytetoset+byte_set:!Lessthan4byteslefttoset+addi$r2,$r2,#-1 ! Decrease len by 1+sbi.bi$r1,[$r0],#1 ! Set data of the next byte to $r1+bnez$r2,byte_set!Stillbyteslefttoset+end_memset:+move$r0,$r5+ret++ENDPROC(memset)
@@ -0,0 +1,160 @@+/*+*Copyright (C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include <linux/linkage.h>+#include <asm/assembler.h>+#include <asm/errno.h>++.text++/*Prototype:int__arch_copy_to_user(void*to,constchar*from,size_tn)+*Purpose:copyablocktousermemoryfromkernelmemory+*Params:to-usermemory+*:from-kernelmemory+*:n-numberofbytestocopy+*Returns:NumberofbytesNOTcopied.+*/++ENTRY(__arch_copy_to_user)+push$r0+push$r2+beqz$r2,ctu_exit+srli$p0,$r2,#2 ! $p0 = number of word to clear+andi$r2,$r2,#3 ! Bytes less than a word to copy+beqz$p0,byte_ctu!Onlylessthanawordtocopy+word_ctu:+lmw.bim$p1,[$r1],$p1!Loadthenextword+USER(smw.bim,$p1,[$r0],$p1)!Storethenextword+addi$p0,$p0,#-1 ! Decrease word count+bnez$p0,word_ctu!Continueloopingtocopyallwords+beqz$r2,ctu_exit!Noleftbytestocopy+byte_ctu:+lbi.bi$p1,[$r1],#1 ! Load the next byte+USER(sbi.bi,$p1,[$r0],#1) ! Store the next byte+addi$r2,$r2,#-1 ! Decrease byte count+bnez$r2,byte_ctu!Continueloopingtoclearallleftbytes+ctu_exit:+move$r0,$r2!Setreturnvalue+pop$r2+pop$r2!Popsaved$r0to$r2tonotcorruptreturnvalue+ret++.section.fixup,"ax"+.align0+9001:+pop$p1!Original$r2,n+pop$p0!Original$r0,void*to+sub$r1,$r0,$p0!Bytescopied+sub$r2,$p1,$r1!Byteslefttocopy+push$lp+move$r0,$p0+balmemzero!Cleanupthememory+pop$lp+move$r0,$r2+ret+.previous+ENDPROC(__arch_copy_to_user)++/*Prototype:unsignedlong__arch_copy_from_user(void*to,constvoid*from,unsignedlongn);+*Purpose:copyablockfromusermemorytokernelmemory+*Params:to-kernelmemory+*:from-usermemory+*:n-numberofbytestocopy+*Returns:NumberofbytesNOTcopied.+*/+++ENTRY(__arch_copy_from_user)+push$r1+push$r2+beqz$r2,cfu_exit+srli$p0,$r2,#2 ! $p0 = number of word to clear+andi$r2,$r2,#3 ! Bytes less than a word to copy+beqz$p0,byte_cfu!Onlylessthanawordtocopy+word_cfu:+USER(lmw.bim,$p1,[$r1],$p1)!Loadthenextword+smw.bim$p1,[$r0],$p1!Storethenextword+addi$p0,$p0,#-1 ! Decrease word count+bnez$p0,word_cfu!Continueloopingtocopyallwords+beqz$r2,cfu_exit!Noleftbytestocopy+byte_cfu:+USER(lbi.bi,$p1,[$r1],#1) ! Load the next byte+sbi.bi$p1,[$r0],#1 ! Store the next byte+addi$r2,$r2,#-1 ! Decrease byte count+bnez$r2,byte_cfu!Continueloopingtoclearallleftbytes+cfu_exit:+move$r0,$r2!Setreturnvalue+pop$r2+pop$r1+ret++.section.fixup,"ax"+.align0+/*+*Wetookanexception.$r0containsapointerto+*thebytenotcopied.+*/+9001:+pop$p1!Original$r2,n+pop$p0!Original$r0,void*to+sub$r1,$r1,$p0!Bytescopied+sub$r2,$p1,$r1!Byteslefttocopy+push$lp+balmemzero!Cleanupthememory+pop$lp+move$r0,$r2+ret+.previous+ENDPROC(__arch_copy_from_user)++/*Prototype:int__arch_clear_user(void*addr,size_tsz)+*Purpose:clearsomeusermemory+*Params:addr-usermemoryaddresstoclear+*:sz-numberofbytestoclear+*Returns:numberofbytesNOTcleared+*/+.align5+ENTRY(__arch_clear_user)+pushm$r0,$r1+beqz$r1,clear_exit+xor$p1,$p1,$p1!Use$p1=0toclearmem+srli$p0,$r1,#2 ! $p0 = number of word to clear+andi$r1,$r1,#3 ! Bytes less than a word to copy+beqz$p0,byte_clear!Onlylessthanawordtoclear+word_clear:+USER(smw.bim,$p1,[$r0],$p1)!Cleartheword+addi$p0,$p0,#-1 ! Decrease word count+bnez$p0,word_clear!Continueloopingtoclearallwords+beqz$r1,clear_exit!Noleftbytestocopy+byte_clear:+USER(sbi.bi,$p1,[$r0],#1) ! Clear the byte+addi$r1,$r1,#-1 ! Decrease byte count+bnez$r1,byte_clear!Continueloopingtoclearallleftbytes+clear_exit:+move$r0,$r1!Setreturnvalue+pop$r1+pop$r1!Popsaved$r0to$r1tonotcorruptreturnvalue+ret++.section.fixup,"ax"+.align0+9001:+popm$p0,$p1!$p0=original$r0,*addr,$p1=original$r1,n+sub$p0,$r0,$p0!Bytescopied+sub$r0,$p1,$p0!Byteslefttocopy+ret+.previous+ENDPROC(__arch_clear_user)
@@ -0,0 +1,107 @@+#+# For a description of the syntax of this configuration file,+# see Documentation/kbuild/kconfig-language.txt.+#++configNDS32+def_booly+selectARCH_HAS_RAW_COPY_USER+selectARCH_WANT_FRAME_POINTERSifFTRACE+selectARCH_WANT_IPC_PARSE_VERSION+selectCLKSRC_MMIO+selectCLONE_BACKWARDS+selectTIMER_OF+selectFRAME_POINTER+selectGENERIC_ATOMIC64+selectGENERIC_CPU_DEVICES+selectGENERIC_CLOCKEVENTS+selectGENERIC_IOMAP+selectGENERIC_IRQ_CHIP+selectGENERIC_IRQ_PROBE+selectGENERIC_IRQ_SHOW+selectGENERIC_STRNCPY_FROM_USER+selectGENERIC_STRNLEN_USER+selectGENERIC_TIME_VSYSCALL+selectHAVE_ARCH_TRACEHOOK+selectHAVE_GENERIC_IOMAP+selectHAVE_DEBUG_KMEMLEAK+selectHAVE_IDE+selectHAVE_MEMBLOCK+selectHAVE_MEMBLOCK_NODE_MAP+selectHAVE_UID16+selectHAVE_REGS_AND_STACK_ACCESS_API+selectIRQ_DOMAIN+selectLOCKDEP_SUPPORT+selectMODULES_USE_ELF_REL+selectMODULES_USE_ELF_RELA+selectOF+selectOF_EARLY_FLATTREE+selectOLD_SIGACTION+selectOLD_SIGSUSPEND3+selectNO_IOPORT_MAP+selectRTC_LIB+selectTHREAD_INFO_IN_TASK+selectSYS_SUPPORTS_APM_EMULATION+help+Andes(nds32)Linuxsupport.++configGENERIC_CALIBRATE_DELAY+def_booly++configGENERIC_CSUM+def_booly++configGENERIC_HWEIGHT+def_booly++configGENERIC_LOCKBREAK+def_booly+depends onPREEMPT++configRWSEM_GENERIC_SPINLOCK+def_booly++configTRACE_IRQFLAGS_SUPPORT+def_booly++configSTACKTRACE_SUPPORT+def_booly++configPGTABLE_LEVELS+default2++source"init/Kconfig"++menu"System Type"+source"arch/nds32/Kconfig.cpu"+configNR_CPUS+int+default1++configMMU+def_booly++configNDS32_BUILTIN_DTB+string"Builtin DTB"+default""+help+UsercanuseittospecifythedtsoftheSoC+endmenu++menu"Kernel Features"+source"kernel/Kconfig.preempt"+source"mm/Kconfig"+source"kernel/Kconfig.hz"+endmenu++menu"Executable file formats"+source"fs/Kconfig.binfmt"+endmenu++source"net/Kconfig"+source"drivers/Kconfig"+source"fs/Kconfig"+source"arch/nds32/Kconfig.debug"+source"security/Kconfig"+source"crypto/Kconfig"+source"lib/Kconfig"
@@ -0,0 +1,60 @@+LDFLAGS_vmlinux:=--no-undefined-X+OBJCOPYFLAGS:=-Obinary-R.note-R.note.gnu.build-id-R.comment-S++KBUILD_DEFCONFIG:=ae3xx_defconfig++comma=,++KBUILD_CFLAGS+=-mno-sched-prolog-epilog-mcmodel=large++KBUILD_CFLAGS+=$(arch-y)$(tune-y)+KBUILD_AFLAGS+=$(arch-y)$(tune-y)++#Default value+head-y:=arch/nds32/kernel/head.o+textaddr-y:=0xc000c000++TEXTADDR:=$(textaddr-y)++exportTEXTADDR+++# If we have a machine-specific directory, then include it in the build.+core-y+=arch/nds32/kernel/arch/nds32/mm/+libs-y+=arch/nds32/lib/+LIBGCC_PATH:=\+$(shell$(CC)$(KBUILD_CFLAGS)$(KCFLAGS)-print-libgcc-file-name)+libs-y+=$(LIBGCC_PATH)++ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'+BUILTIN_DTB:=y+else+BUILTIN_DTB:=n+endif++boot:=arch/nds32/boot+core-$(BUILTIN_DTB)+=$(boot)/dts/++.PHONY:FORCE++Image:vmlinux+$(Q)$(MAKE)$(build)=$(boot)$(boot)/$@+++PHONY+=vdso_install+vdso_install:+$(Q)$(MAKE)$(build)=arch/nds32/kernel/vdso$@++prepare:vdso_prepare+vdso_prepare:prepare0+$(Q)$(MAKE)$(build)=arch/nds32/kernel/vdsoinclude/generated/vdso-offsets.h++CLEAN_FILES+=include/asm-nds32/constants.h*++# We use MRPROPER_FILES and CLEAN_FILES now+archclean:+$(Q)$(MAKE)$(clean)=$(boot)++define archhelp+echo' Image - kernel image (arch/$(ARCH)/boot/Image)'+endef
@@ -0,0 +1,24 @@+#+# Makefile for the linux kernel.+#++CPPFLAGS_vmlinux.lds:=-DTEXTADDR=$(TEXTADDR)+AFLAGS_head.o:=-DTEXTADDR=$(TEXTADDR)++# Object file lists.++obj-y:=ex-entry.oex-exit.oex-scall.oirq.o\+process.optrace.osetup.osignal.o\+sys_nds32.otime.otraps.ocacheinfo.o\+dma.osyscall_table.ovdso.o++obj-$(CONFIG_MODULES)+=nds32_ksyms.omodule.o+obj-$(CONFIG_STACKTRACE)+=stacktrace.o+obj-$(CONFIG_OF)+=devtree.o+obj-$(CONFIG_EARLY_PRINTK)+=early_printk.o+obj-$(CONFIG_CACHE_L2)+=atl2c.o++extra-y:=head.ovmlinux.lds+++obj-y+=vdso/
@@ -0,0 +1,33 @@+* Andestech Processor Binding++This binding specifies what properties must be available in the device tree+representation of a Andestech Processor Core, which is the root node in the+tree.++Required properties:++ - compatible:+ Usage: required+ Value type: <string>+ Definition: should be one of:+ "andestech,n13"+ "andestech,n15"+ "andestech,d15"+ "andestech,n10"+ "andestech,d10"++ - device_type+ Usage: required+ Value type: <string>+ Definition: must be "cpu"++* Examples++/ {+ cpus {+ cpu@0 {+ device_type = "cpu";+ compatible = "andestech,n13", "andestech,n15";+ };+ };+};
@@ -0,0 +1,149 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/irq.h>+#include<linux/of.h>+#include<linux/of_irq.h>+#include<linux/of_address.h>+#include<linux/interrupt.h>+#include<linux/irqdomain.h>+#include<linux/irqchip.h>+#include<nds32_intrinsic.h>++staticvoidativic32_ack_irq(structirq_data*data)+{+__nds32__mtsr_dsb(1<<data->hwirq,NDS32_SR_INT_PEND2);+}++staticvoidativic32_mask_irq(structirq_data*data)+{+unsignedlongint_mask2=__nds32__mfsr(NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb(int_mask2&(~(1<<data->hwirq)),NDS32_SR_INT_MASK2);+}++staticvoidativic32_mask_ack_irq(structirq_data*data)+{+unsignedlongint_mask2=__nds32__mfsr(NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb(int_mask2&(~(1<<data->hwirq)),NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb((1<<data->hwirq),NDS32_SR_INT_PEND2);++}++staticvoidativic32_unmask_irq(structirq_data*data)+{+unsignedlongint_mask2=__nds32__mfsr(NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb(int_mask2|(1<<data->hwirq),NDS32_SR_INT_MASK2);+}++staticintativic32_set_type(structirq_data*data,unsignedintflow_type)+{+printk(KERN_WARNING"interrupt type is not configurable\n");+return0;+}++staticstructirq_chipativic32_chip={+.name="ativic32",+.irq_ack=ativic32_ack_irq,+.irq_mask=ativic32_mask_irq,+.irq_mask_ack=ativic32_mask_ack_irq,+.irq_unmask=ativic32_unmask_irq,+.irq_set_type=ativic32_set_type,+};++staticunsignedint__initdatanivic_map[6]={6,2,10,16,24,32};++structirq_domain*root_domain;+staticintativic32_irq_domain_map(structirq_domain*id,unsignedintvirq,+irq_hw_number_thw)+{++unsignedlongint_trigger_type;+int_trigger_type=__nds32__mfsr(NDS32_SR_INT_TRIGGER);+if(int_trigger_type&(1<<hw))+irq_set_chip_and_handler(virq,&ativic32_chip,handle_edge_irq);+else+irq_set_chip_and_handler(virq,&ativic32_chip,handle_level_irq);++return0;+}++staticstructirq_domain_opsativic32_ops={+.map=ativic32_irq_domain_map,+.xlate=irq_domain_xlate_onecell+};++staticintget_intr_src(void)+{+return((__nds32__mfsr(NDS32_SR_ITYPE)&ITYPE_mskVECTOR)>>ITYPE_offVECTOR)+-NDS32_VECTOR_offINTERRUPT;+}++asmlinkagevoidasm_do_IRQ(structpt_regs*regs)+{+structpt_regs*old_regs=set_irq_regs(regs);+intvirq;+intirq=get_intr_src();++/*+*Somehardwaregivesrandomlywronginterrupts.Rather+*thancrashing,dosomethingsensible.+*/+if(unlikely(irq>=NR_IRQS)){+pr_emerg("IRQ exceeds NR_IRQS\n");+BUG();+}++irq_enter();+virq=irq_find_mapping(root_domain,irq);+generic_handle_irq(virq);+irq_exit();+set_irq_regs(old_regs);++}++int__initativic32_init_irq(structdevice_node*node,structdevice_node*parent)+{+unsignedlongint_vec_base,nivic,i;++if(WARN(parent,"non-root ativic32 are not supported"))+return-EINVAL;++int_vec_base=__nds32__mfsr(NDS32_SR_IVB);++if(((int_vec_base&IVB_mskIVIC_VER)>>IVB_offIVIC_VER)==0){+panic("Unable to use NOINTC option to boot on this cpu\n");+}++nivic=(int_vec_base&IVB_mskNIVIC)>>IVB_offNIVIC;+if(nivic>=(sizeofnivic_map/sizeofnivic_map[0])){+panic+("The number of input for IVIC Controller is not supported on this cpu\n");+}+nivic=nivic_map[nivic];++root_domain=irq_domain_add_linear(node,nivic,+&ativic32_ops,NULL);++if(!root_domain)+panic("%s: unable to create IRQ domain\n",node->full_name);++for(i=0;i<nivic;i++)+irq_create_mapping(root_domain,i);++return0;++}+IRQCHIP_DECLARE(ativic32,"andestech,ativic32",ativic32_init_irq);
@@ -0,0 +1,27 @@+* Andestech Internal Vector Interrupt Controller++The Internal Vector Interrupt Controller (IVIC) is a basic interrupt controller+suitable for a simpler SoC platform not requiring a more sophisticated and+bigger External Vector Interrupt Controller.+++Main node required properties:++- compatible : should at least contain "andestech,ativic32".+- interrupt-parent: Empty for the interrupt controller itself+- interrupt-controller : Identifies the node as an interrupt controller+- #interrupt-cells: The number of cells to define the interrupts. Should be 2.+ The first cell is the IRQ number+ The second cell is used to specify mode:+ 1 = low-to-high edge triggered+ 2 = high-to-low edge triggered+ 4 = active high level-sensitive+ 8 = active low level-sensitive+ Default for internal sources should be set to 4 (active high).++Examples:+ intc: interrupt-controller {+ compatible = "andestech,ativic32";+ #interrupt-cells = <2>;+ interrupt-controller;+ };
@@ -0,0 +1,110 @@+CONFIG_CROSS_COMPILE="nds32le-linux-"+CONFIG_SYSVIPC=y+CONFIG_POSIX_MQUEUE=y+CONFIG_HIGH_RES_TIMERS=y+CONFIG_BSD_PROCESS_ACCT=y+CONFIG_BSD_PROCESS_ACCT_V3=y+CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y+CONFIG_LOG_BUF_SHIFT=14+CONFIG_NAMESPACES=y+CONFIG_USER_NS=y+CONFIG_RELAY=y+CONFIG_BLK_DEV_INITRD=y+CONFIG_SYSCTL_SYSCALL=y+CONFIG_KALLSYMS_ALL=y+CONFIG_EMBEDDED=y+# CONFIG_VM_EVENT_COUNTERS is not set+# CONFIG_SLUB_DEBUG is not set+CONFIG_PROFILING=y+CONFIG_MODULES=y+CONFIG_MODULE_UNLOAD=y+# CONFIG_BLK_DEV_BSG is not set+# CONFIG_HWZOL is not set+CONFIG_ANDES_PAGE_SIZE_8KB=y+CONFIG_NDS32_BUILTIN_DTB="ae3xx"+CONFIG_PREEMPT=y+# CONFIG_COMPACTION is not set+CONFIG_HZ_100=y+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set+CONFIG_NET=y+CONFIG_PACKET=y+CONFIG_UNIX=y+CONFIG_NET_KEY=y+CONFIG_INET=y+CONFIG_IP_MULTICAST=y+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set+# CONFIG_INET_XFRM_MODE_TUNNEL is not set+# CONFIG_INET_XFRM_MODE_BEET is not set+# CONFIG_INET_DIAG is not set+# CONFIG_IPV6 is not set+CONFIG_BRIDGE=y+CONFIG_BLK_DEV_LOOP=y+CONFIG_BLK_DEV_RAM=y+CONFIG_BLK_DEV_RAM_SIZE=8192+CONFIG_NETDEVICES=y+CONFIG_TUN=y+# CONFIG_NET_CADENCE is not set+# CONFIG_NET_VENDOR_BROADCOM is not set+CONFIG_FTMAC100=y+# CONFIG_NET_VENDOR_INTEL is not set+# CONFIG_NET_VENDOR_MARVELL is not set+# CONFIG_NET_VENDOR_MICREL is not set+# CONFIG_NET_VENDOR_NATSEMI is not set+# CONFIG_NET_VENDOR_SEEQ is not set+# CONFIG_NET_VENDOR_STMICRO is not set+# CONFIG_NET_VENDOR_WIZNET is not set+CONFIG_INPUT_EVDEV=y+# CONFIG_INPUT_KEYBOARD is not set+# CONFIG_INPUT_MOUSE is not set+CONFIG_INPUT_TOUCHSCREEN=y+# CONFIG_SERIO is not set+CONFIG_SERIAL_8250=y+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set+CONFIG_SERIAL_8250_CONSOLE=y+CONFIG_SERIAL_8250_NR_UARTS=3+CONFIG_SERIAL_8250_RUNTIME_UARTS=3+CONFIG_SERIAL_OF_PLATFORM=y+# CONFIG_HW_RANDOM is not set+# CONFIG_HWMON is not set+CONFIG_WATCHDOG=y+CONFIG_FB=y+# CONFIG_VGA_CONSOLE is not set+CONFIG_FRAMEBUFFER_CONSOLE=y+CONFIG_LOGO=y+CONFIG_SOUND=y+CONFIG_SND=y+# CONFIG_SND_SUPPORT_OLD_API is not set+# CONFIG_SND_VERBOSE_PROCFS is not set+# CONFIG_USB_SUPPORT is not set+CONFIG_MMC=y+CONFIG_RTC_CLASS=y+# CONFIG_RTC_HCTOSYS is not set+CONFIG_CLKSRC_ATCPIT100=y+CONFIG_EXT2_FS=y+CONFIG_FUSE_FS=y+CONFIG_MSDOS_FS=y+CONFIG_VFAT_FS=y+CONFIG_TMPFS=y+CONFIG_TMPFS_POSIX_ACL=y+CONFIG_CONFIGFS_FS=y+CONFIG_NFS_FS=y+CONFIG_NFS_V3_ACL=y+CONFIG_NFS_V4=y+CONFIG_NFS_V4_1=y+CONFIG_NFS_USE_LEGACY_DNS=y+CONFIG_NLS_CODEPAGE_437=y+CONFIG_NLS_ISO8859_1=y+CONFIG_DEBUG_INFO=y+CONFIG_DEBUG_INFO_DWARF4=y+CONFIG_GDB_SCRIPTS=y+CONFIG_READABLE_ASM=y+CONFIG_HEADERS_CHECK=y+CONFIG_DEBUG_SECTION_MISMATCH=y+CONFIG_MAGIC_SYSRQ=y+CONFIG_PANIC_ON_OOPS=y+# CONFIG_SCHED_DEBUG is not set+# CONFIG_DEBUG_PREEMPT is not set+CONFIG_STACKTRACE=y+CONFIG_RCU_CPU_STALL_TIMEOUT=300+# CONFIG_CRYPTO_HW is not set
@@ -0,0 +1,109 @@+CONFIG_CROSS_COMPILE="nds32le-linux-"+CONFIG_SYSVIPC=y+CONFIG_POSIX_MQUEUE=y+CONFIG_HIGH_RES_TIMERS=y+CONFIG_BSD_PROCESS_ACCT=y+CONFIG_BSD_PROCESS_ACCT_V3=y+CONFIG_IKCONFIG=y+CONFIG_IKCONFIG_PROC=y+CONFIG_LOG_BUF_SHIFT=14+CONFIG_NAMESPACES=y+CONFIG_USER_NS=y+CONFIG_RELAY=y+CONFIG_BLK_DEV_INITRD=y+CONFIG_SYSCTL_SYSCALL=y+CONFIG_KALLSYMS_ALL=y+CONFIG_EMBEDDED=y+# CONFIG_VM_EVENT_COUNTERS is not set+# CONFIG_SLUB_DEBUG is not set+CONFIG_PROFILING=y+CONFIG_MODULES=y+CONFIG_MODULE_UNLOAD=y+# CONFIG_BLK_DEV_BSG is not set+# CONFIG_HWZOL is not set+CONFIG_NDS32_BUILTIN_DTB="ag101p"+CONFIG_PREEMPT=y+# CONFIG_COMPACTION is not set+CONFIG_HZ_100=y+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set+CONFIG_NET=y+CONFIG_PACKET=y+CONFIG_UNIX=y+CONFIG_NET_KEY=y+CONFIG_INET=y+CONFIG_IP_MULTICAST=y+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set+# CONFIG_INET_XFRM_MODE_TUNNEL is not set+# CONFIG_INET_XFRM_MODE_BEET is not set+# CONFIG_INET_DIAG is not set+# CONFIG_IPV6 is not set+CONFIG_BRIDGE=y+CONFIG_BLK_DEV_LOOP=y+CONFIG_BLK_DEV_RAM=y+CONFIG_BLK_DEV_RAM_SIZE=8192+CONFIG_NETDEVICES=y+CONFIG_TUN=y+# CONFIG_NET_CADENCE is not set+# CONFIG_NET_VENDOR_BROADCOM is not set+CONFIG_FTMAC100=y+# CONFIG_NET_VENDOR_INTEL is not set+# CONFIG_NET_VENDOR_MARVELL is not set+# CONFIG_NET_VENDOR_MICREL is not set+# CONFIG_NET_VENDOR_NATSEMI is not set+# CONFIG_NET_VENDOR_SEEQ is not set+# CONFIG_NET_VENDOR_STMICRO is not set+# CONFIG_NET_VENDOR_WIZNET is not set+CONFIG_INPUT_EVDEV=y+# CONFIG_INPUT_KEYBOARD is not set+# CONFIG_INPUT_MOUSE is not set+CONFIG_INPUT_TOUCHSCREEN=y+# CONFIG_SERIO is not set+CONFIG_SERIAL_8250=y+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set+CONFIG_SERIAL_8250_CONSOLE=y+CONFIG_SERIAL_8250_NR_UARTS=3+CONFIG_SERIAL_8250_RUNTIME_UARTS=3+CONFIG_SERIAL_OF_PLATFORM=y+# CONFIG_HW_RANDOM is not set+# CONFIG_HWMON is not set+CONFIG_WATCHDOG=y+CONFIG_FB=y+# CONFIG_VGA_CONSOLE is not set+CONFIG_FRAMEBUFFER_CONSOLE=y+CONFIG_LOGO=y+CONFIG_SOUND=y+CONFIG_SND=y+# CONFIG_SND_SUPPORT_OLD_API is not set+# CONFIG_SND_VERBOSE_PROCFS is not set+# CONFIG_USB_SUPPORT is not set+CONFIG_MMC=y+CONFIG_RTC_CLASS=y+# CONFIG_RTC_HCTOSYS is not set+CONFIG_CLKSRC_ATFMR010=y+CONFIG_EXT2_FS=y+CONFIG_FUSE_FS=y+CONFIG_MSDOS_FS=y+CONFIG_VFAT_FS=y+CONFIG_TMPFS=y+CONFIG_TMPFS_POSIX_ACL=y+CONFIG_CONFIGFS_FS=y+CONFIG_NFS_FS=y+CONFIG_NFS_V3_ACL=y+CONFIG_NFS_V4=y+CONFIG_NFS_V4_1=y+CONFIG_NFS_USE_LEGACY_DNS=y+CONFIG_NLS_CODEPAGE_437=y+CONFIG_NLS_ISO8859_1=y+CONFIG_DEBUG_INFO=y+CONFIG_DEBUG_INFO_DWARF4=y+CONFIG_GDB_SCRIPTS=y+CONFIG_READABLE_ASM=y+CONFIG_HEADERS_CHECK=y+CONFIG_DEBUG_SECTION_MISMATCH=y+CONFIG_MAGIC_SYSRQ=y+CONFIG_PANIC_ON_OOPS=y+# CONFIG_SCHED_DEBUG is not set+# CONFIG_DEBUG_PREEMPT is not set+CONFIG_STACKTRACE=y+CONFIG_RCU_CPU_STALL_TIMEOUT=300+# CONFIG_CRYPTO_HW is not set
@@ -0,0 +1,45 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/memblock.h>+#include<linux/of_fdt.h>+#include<linux/bootmem.h>++void__initearly_init_dt_add_memory_arch(u64base,u64size)+{+size&=PAGE_MASK;+memblock_add_node(base,size,0);+}++void*__initearly_init_dt_alloc_memory_arch(u64size,u64align)+{+returnalloc_bootmem_align(size,align);+}++void__initearly_init_devtree(void*params)+{+if(!params||!early_init_dt_scan(params)){+pr_crit("\n"+"Error: invalid device tree blob at (virtual address 0x%p)\n"+"The dtb must be 8-byte aligned and must not exceed 8 KB in size\n"+"\nPlease check your bootloader.",params);++while(true)+cpu_relax();+}++dump_stack_set_arch_desc("%s (DT)",of_flat_dt_get_machine_name());+}
@@ -0,0 +1,370 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/errno.h>+#include<linux/signal.h>+#include<linux/ptrace.h>+#include<linux/personality.h>+#include<linux/freezer.h>+#include<linux/tracehook.h>+#include<linux/uaccess.h>++#include<asm/cacheflush.h>+#include<asm/ucontext.h>+#include<asm/unistd.h>++#include<asm/ptrace.h>+#include<asm/vdso.h>++structrt_sigframe{+structsiginfoinfo;+structucontextuc;+};++staticintrestore_sigframe(structpt_regs*regs,+structrt_sigframe__user*sf)+{+sigset_tset;+interr;++err=__copy_from_user(&set,&sf->uc.uc_sigmask,sizeof(set));+if(err==0){+set_current_blocked(&set);+}++__get_user_error(regs->uregs[0],&sf->uc.uc_mcontext.nds32_r0,err);+__get_user_error(regs->uregs[1],&sf->uc.uc_mcontext.nds32_r1,err);+__get_user_error(regs->uregs[2],&sf->uc.uc_mcontext.nds32_r2,err);+__get_user_error(regs->uregs[3],&sf->uc.uc_mcontext.nds32_r3,err);+__get_user_error(regs->uregs[4],&sf->uc.uc_mcontext.nds32_r4,err);+__get_user_error(regs->uregs[5],&sf->uc.uc_mcontext.nds32_r5,err);+__get_user_error(regs->uregs[6],&sf->uc.uc_mcontext.nds32_r6,err);+__get_user_error(regs->uregs[7],&sf->uc.uc_mcontext.nds32_r7,err);+__get_user_error(regs->uregs[8],&sf->uc.uc_mcontext.nds32_r8,err);+__get_user_error(regs->uregs[9],&sf->uc.uc_mcontext.nds32_r9,err);+__get_user_error(regs->uregs[10],&sf->uc.uc_mcontext.nds32_r10,err);+__get_user_error(regs->uregs[11],&sf->uc.uc_mcontext.nds32_r11,err);+__get_user_error(regs->uregs[12],&sf->uc.uc_mcontext.nds32_r12,err);+__get_user_error(regs->uregs[13],&sf->uc.uc_mcontext.nds32_r13,err);+__get_user_error(regs->uregs[14],&sf->uc.uc_mcontext.nds32_r14,err);+__get_user_error(regs->uregs[15],&sf->uc.uc_mcontext.nds32_r15,err);+__get_user_error(regs->uregs[16],&sf->uc.uc_mcontext.nds32_r16,err);+__get_user_error(regs->uregs[17],&sf->uc.uc_mcontext.nds32_r17,err);+__get_user_error(regs->uregs[18],&sf->uc.uc_mcontext.nds32_r18,err);+__get_user_error(regs->uregs[19],&sf->uc.uc_mcontext.nds32_r19,err);+__get_user_error(regs->uregs[20],&sf->uc.uc_mcontext.nds32_r20,err);++__get_user_error(regs->uregs[21],&sf->uc.uc_mcontext.nds32_r21,err);+__get_user_error(regs->uregs[22],&sf->uc.uc_mcontext.nds32_r22,err);+__get_user_error(regs->uregs[23],&sf->uc.uc_mcontext.nds32_r23,err);+__get_user_error(regs->uregs[24],&sf->uc.uc_mcontext.nds32_r24,err);+__get_user_error(regs->uregs[25],&sf->uc.uc_mcontext.nds32_r25,err);+__get_user_error(regs->fp,&sf->uc.uc_mcontext.nds32_fp,err);+__get_user_error(regs->gp,&sf->uc.uc_mcontext.nds32_gp,err);+__get_user_error(regs->lp,&sf->uc.uc_mcontext.nds32_lp,err);+__get_user_error(regs->sp,&sf->uc.uc_mcontext.nds32_sp,err);+__get_user_error(regs->ipc,&sf->uc.uc_mcontext.nds32_ipc,err);+#if defined(CONFIG_HWZOL)+__get_user_error(regs->lc,&sf->uc.uc_mcontext.zol.nds32_lc,err);+__get_user_error(regs->le,&sf->uc.uc_mcontext.zol.nds32_le,err);+__get_user_error(regs->lb,&sf->uc.uc_mcontext.zol.nds32_lb,err);+#endif++err|=!valid_user_regs(regs);++returnerr;+}++asmlinkageintsys_rt_sigreturn(structpt_regs*regs)+{+structrt_sigframe__user*frame;++/* Always make any pending restarted system calls return -EINTR */+current->restart_block.fn=do_no_restart_syscall;++/*+*Sincewestackedthesignalona64-bitboundary,+*then'sp'shouldbetwo-wordalignedhere.Ifit's+*not,thentheuseristryingtomesswithus.+*/+if(regs->sp&7)+gotobadframe;++frame=(structrt_sigframe__user*)regs->sp;++if(!access_ok(VERIFY_READ,frame,sizeof(*frame)))+gotobadframe;++if(restore_sigframe(regs,frame))+gotobadframe;++if(restore_altstack(&frame->uc.uc_stack))+gotobadframe;++returnregs->uregs[0];++badframe:+force_sig(SIGSEGV,current);+return0;+}++staticint+setup_sigframe(structrt_sigframe__user*sf,structpt_regs*regs,+sigset_t*set)+{+interr=0;+++__put_user_error(regs->uregs[0],&sf->uc.uc_mcontext.nds32_r0,err);+__put_user_error(regs->uregs[1],&sf->uc.uc_mcontext.nds32_r1,err);+__put_user_error(regs->uregs[2],&sf->uc.uc_mcontext.nds32_r2,err);+__put_user_error(regs->uregs[3],&sf->uc.uc_mcontext.nds32_r3,err);+__put_user_error(regs->uregs[4],&sf->uc.uc_mcontext.nds32_r4,err);+__put_user_error(regs->uregs[5],&sf->uc.uc_mcontext.nds32_r5,err);+__put_user_error(regs->uregs[6],&sf->uc.uc_mcontext.nds32_r6,err);+__put_user_error(regs->uregs[7],&sf->uc.uc_mcontext.nds32_r7,err);+__put_user_error(regs->uregs[8],&sf->uc.uc_mcontext.nds32_r8,err);+__put_user_error(regs->uregs[9],&sf->uc.uc_mcontext.nds32_r9,err);+__put_user_error(regs->uregs[10],&sf->uc.uc_mcontext.nds32_r10,err);+__put_user_error(regs->uregs[11],&sf->uc.uc_mcontext.nds32_r11,err);+__put_user_error(regs->uregs[12],&sf->uc.uc_mcontext.nds32_r12,err);+__put_user_error(regs->uregs[13],&sf->uc.uc_mcontext.nds32_r13,err);+__put_user_error(regs->uregs[14],&sf->uc.uc_mcontext.nds32_r14,err);+__put_user_error(regs->uregs[15],&sf->uc.uc_mcontext.nds32_r15,err);+__put_user_error(regs->uregs[16],&sf->uc.uc_mcontext.nds32_r16,err);+__put_user_error(regs->uregs[17],&sf->uc.uc_mcontext.nds32_r17,err);+__put_user_error(regs->uregs[18],&sf->uc.uc_mcontext.nds32_r18,err);+__put_user_error(regs->uregs[19],&sf->uc.uc_mcontext.nds32_r19,err);+__put_user_error(regs->uregs[20],&sf->uc.uc_mcontext.nds32_r20,err);++__put_user_error(regs->uregs[21],&sf->uc.uc_mcontext.nds32_r21,err);+__put_user_error(regs->uregs[22],&sf->uc.uc_mcontext.nds32_r22,err);+__put_user_error(regs->uregs[23],&sf->uc.uc_mcontext.nds32_r23,err);+__put_user_error(regs->uregs[24],&sf->uc.uc_mcontext.nds32_r24,err);+__put_user_error(regs->uregs[25],&sf->uc.uc_mcontext.nds32_r25,err);+__put_user_error(regs->fp,&sf->uc.uc_mcontext.nds32_fp,err);+__put_user_error(regs->gp,&sf->uc.uc_mcontext.nds32_gp,err);+__put_user_error(regs->lp,&sf->uc.uc_mcontext.nds32_lp,err);+__put_user_error(regs->sp,&sf->uc.uc_mcontext.nds32_sp,err);+__put_user_error(regs->ipc,&sf->uc.uc_mcontext.nds32_ipc,err);+#if defined(CONFIG_HWZOL)+__put_user_error(regs->lc,&sf->uc.uc_mcontext.zol.nds32_lc,err);+__put_user_error(regs->le,&sf->uc.uc_mcontext.zol.nds32_le,err);+__put_user_error(regs->lb,&sf->uc.uc_mcontext.zol.nds32_lb,err);+#endif++__put_user_error(current->thread.trap_no,&sf->uc.uc_mcontext.trap_no,+err);+__put_user_error(current->thread.error_code,+&sf->uc.uc_mcontext.error_code,err);+__put_user_error(current->thread.address,+&sf->uc.uc_mcontext.fault_address,err);+__put_user_error(set->sig[0],&sf->uc.uc_mcontext.oldmask,err);++err|=__copy_to_user(&sf->uc.uc_sigmask,set,sizeof(*set));++returnerr;+}++staticinlinevoid__user*get_sigframe(structksignal*ksig,+structpt_regs*regs,intframesize)+{+unsignedlongsp=sigsp(regs->sp,ksig);+void__user*frame;++/*+*ATPCSB01mandates8-bytealignment+*/+frame=(void__user*)((sp-framesize)&~7);++/*+*Checkthatwecanactuallywritetothesignalframe.+*/+if(!access_ok(VERIFY_WRITE,frame,framesize))+frame=NULL;++returnframe;+}++staticint+setup_return(structpt_regs*regs,structksignal*ksig,void__user*frame)+{+unsignedlonghandler=(unsignedlong)ksig->ka.sa.sa_handler;+unsignedlongretcode;++/*+*Maybeweneedtodelivera32-bitsignaltoa26-bittask.+*/+if(ksig->ka.sa.sa_flags&SA_RESTORER)+retcode=(unsignedlong)ksig->ka.sa.sa_restorer;+else+retcode=VDSO_SYMBOL(current->mm->context.vdso,rt_sigtramp);++regs->uregs[0]=ksig->sig;+regs->sp=(unsignedlong)frame;+regs->lp=retcode;+regs->ipc=handler;+/* Also store handler address in r15 for updating GP in the handler. */+regs->uregs[15]=handler;++return0;+}++staticint+setup_rt_frame(structksignal*ksig,sigset_t*set,structpt_regs*regs)+{+structrt_sigframe__user*frame=+get_sigframe(ksig,regs,sizeof(*frame));+interr=0;++if(!frame)+return1;++err|=copy_siginfo_to_user(&frame->info,&ksig->info);++__put_user_error(0,&frame->uc.uc_flags,err);+__put_user_error(NULL,&frame->uc.uc_link,err);++err|=__save_altstack(&frame->uc.uc_stack,regs->sp);+err|=setup_sigframe(frame,regs,set);+if(err==0){+setup_return(regs,ksig,frame);++if(err==0){+/*+*Forrealtimesignalswemustalsosetthesecondandthird+*argumentsforthesignalhandler.+*--PeterMaydell<pmaydell@chiark.greenend.org.uk>2000-12-06+*/+regs->uregs[1]=(unsignedlong)&frame->info;+regs->uregs[2]=(unsignedlong)&frame->uc;+}+}+returnerr;+}++/*+*OK,we'reinvokingahandler+*/+staticvoidhandle_signal(structksignal*ksig,structpt_regs*regs)+{+intret;+sigset_t*oldset=sigmask_to_save();++/*+*Setupthestackframe+*/+ret=setup_rt_frame(ksig,oldset,regs);++/*+*Checkthattheresultingregistersareactuallysane.+*/+ret|=!valid_user_regs(regs);++signal_setup_done(ret,ksig,0);+}++/*+*Notethat'init'isaspecialprocess:itdoesn'tgetsignalsitdoesn't+*wanttohandle.ThusyoucannotkillinitevenwithaSIGKILLevenby+*mistake.+*+*Notethatwegothroughthesignalstwice:oncetocheckthesignalsthat+*thekernelcanhandle,andthenwebuildalltheuser-levelsignalhandling+*stack-framesinonegoafterthat.+*/+staticintdo_signal(structpt_regs*regs,intsyscall)+{+unsignedintretval=0,continue_addr=0,restart_addr=0;+structksignalksig;+intrestart=0;++/*+*Wewantthecommoncasetogofast,which+*iswhywemayincertaincasesgetherefrom+*kernelmode.Justreturnwithoutdoinganything+*ifso.+*/+if(!user_mode(regs))+return0;++/*+*Ifwewerefromasystemcall,checkforsystemcallrestarting...+*/+if(syscall){+continue_addr=regs->ipc;+restart_addr=continue_addr-4;+retval=regs->uregs[0];++/*+*Prepareforsystemcallrestart.Wedothisheresothata+*debuggerwillseethealreadychangedPSW.+*/+switch(retval){+case-ERESTART_RESTARTBLOCK:+restart-=2;+case-ERESTARTNOHAND:+case-ERESTARTSYS:+case-ERESTARTNOINTR:+restart++;+regs->uregs[0]=regs->orig_r0;+regs->ipc=restart_addr;+break;+}+}++/*+*Getthesignaltodeliver.Whenrunningunderptrace,atthis+*pointthedebuggermaychangeallourregisters...+*/+/*+*Dependingonthesignalsettingswemayneedtorevertthe+*decisiontorestartthesystemcall.Butskipthisifa+*debuggerhaschosentorestartatadifferentPC.+*/+if(get_signal(&ksig)){+if(unlikely(restart)&®s->ipc==restart_addr){+if(retval==-ERESTARTNOHAND||+retval==-ERESTART_RESTARTBLOCK+||(retval==-ERESTARTSYS+&&!(ksig.ka.sa.sa_flags&SA_RESTART))){+regs->uregs[0]=-EINTR;+regs->ipc=continue_addr;+}+}+handle_signal(&ksig,regs);+}else{+restore_saved_sigmask();+if(unlikely(restart)&®s->ipc==restart_addr){+regs->ipc=continue_addr;+returnrestart;+}+}+return0;+}++asmlinkageint+do_notify_resume(structpt_regs*regs,unsignedintthread_flags,intsyscall)+{+if(thread_flags&_TIF_SIGPENDING)+returndo_signal(regs,syscall);++if(thread_flags&_TIF_NOTIFY_RESUME){+clear_thread_flag(TIF_NOTIFY_RESUME);+tracehook_notify_resume(regs);+}+return0;+}
@@ -0,0 +1,243 @@+/*+*VDSOimplementationforAArch64andvectorpagesetupforAArch32.+*+*Copyright(C)2012ARMLimited+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*+*Author:WillDeacon<will.deacon@arm.com>+*/++#include<linux/cache.h>+#include<linux/clocksource.h>+#include<linux/elf.h>+#include<linux/err.h>+#include<linux/errno.h>+#include<linux/gfp.h>+#include<linux/kernel.h>+#include<linux/mm.h>+#include<linux/sched.h>+#include<linux/signal.h>+#include<linux/slab.h>+#include<linux/timekeeper_internal.h>+#include<linux/vmalloc.h>++#include<linux/platform_device.h>+#include<linux/of_address.h>+#include<asm/cacheflush.h>+#include<asm/vdso.h>+#include<asm/vdso_datapage.h>+#include<linux/random.h>+#include<asm/cache_info.h>+externstructcache_infoL1_cache_info[2];+externcharvdso_start,vdso_end;+staticunsignedlongvdso_pages__ro_after_init;+structresourcetimer_res;++/*+*ThevDSOdatapage.+*/+staticstructpage*no_pages[]={NULL};++staticunion{+structvdso_datadata;+u8page[PAGE_SIZE];+}vdso_data_store__page_aligned_data;+structvdso_data*vdso_data=&vdso_data_store.data;+staticstructvm_special_mappingvdso_spec[2]__ro_after_init={+{+.name="[vvar]",+.pages=no_pages,+},+{+.name="[vdso]",+},+};++staticintgrab_timer_node_info(void)+{+structdevice_node*timer_node;++timer_node=of_find_node_by_name(NULL,"timer");+of_property_read_u32(timer_node,"cycle-count-offset",+&vdso_data->cycle_count_offset);+vdso_data->cycle_count_down=+of_property_read_bool(timer_node,"cycle-count-down");+returnof_address_to_resource(timer_node,0,&timer_res);+}++staticint__initvdso_init(void)+{+inti;+structpage**vdso_pagelist;++if(memcmp(&vdso_start,"\177ELF",4)){+pr_err("vDSO is not a valid ELF object!\n");+return-EINVAL;+}+/* Creat a timer io mapping to get clock cycles counter */+if(grab_timer_node_info())+return-ENODEV;++vdso_pages=(&vdso_end-&vdso_start)>>PAGE_SHIFT;+pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",+vdso_pages+1,vdso_pages,&vdso_start,1L,vdso_data);++/* Allocate the vDSO pagelist */+vdso_pagelist=kcalloc(vdso_pages,sizeof(structpage*),GFP_KERNEL);+if(vdso_pagelist==NULL)+return-ENOMEM;++for(i=0;i<vdso_pages;i++)+vdso_pagelist[i]=virt_to_page(&vdso_start+i*PAGE_SIZE);+vdso_spec[1].pages=&vdso_pagelist[0];++return0;+}++arch_initcall(vdso_init);++unsignedlonginlinevdso_random_addr(unsignedlongvdso_mapping_len)+{+unsignedlongstart=current->mm->mmap_base,end,offset,addr;+start=PAGE_ALIGN(start);++/* Round the lowest possible end address up to a PMD boundary. */+end=(start+vdso_mapping_len+PMD_SIZE-1)&PMD_MASK;+if(end>=TASK_SIZE)+end=TASK_SIZE;+end-=vdso_mapping_len;++if(end>start){+offset=get_random_int()%(((end-start)>>PAGE_SHIFT)+1);+addr=start+(offset<<PAGE_SHIFT);+}else{+addr=start;+}+returnaddr;+}++intarch_setup_additional_pages(structlinux_binprm*bprm,intuses_interp)+{+structmm_struct*mm=current->mm;+unsignedlongvdso_base,vdso_text_len,vdso_mapping_len;+structvm_area_struct*vma;+unsignedlongaddr=0;+pgprot_tprot;+intret;++vdso_text_len=vdso_pages<<PAGE_SHIFT;+/* Be sure to map the data page */+vdso_mapping_len=vdso_text_len+2*PAGE_SIZE;+#ifndef CONFIG_CPU_CACHE_NONALIASING+vdso_mapping_len+=L1_cache_info[DCACHE].aliasing_num-1;+#endif++if(down_write_killable(&mm->mmap_sem))+return-EINTR;++addr=vdso_random_addr(vdso_mapping_len);+vdso_base=get_unmapped_area(NULL,addr,vdso_mapping_len,0,0);+if(IS_ERR_VALUE(vdso_base)){+ret=vdso_base;+gotoup_fail;+}+#ifndef CONFIG_CPU_CACHE_NONALIASING+{+unsignedintaliasing_mask=+L1_cache_info[DCACHE].aliasing_mask;+unsignedintpage_colour_ofs;+page_colour_ofs=((unsignedint)vdso_data&aliasing_mask)-+(vdso_base&aliasing_mask);+vdso_base+=page_colour_ofs&aliasing_mask;+}+#endif+vma=_install_special_mapping(mm,vdso_base,2*PAGE_SIZE,+VM_READ|VM_MAYREAD,&vdso_spec[0]);+if(IS_ERR(vma)){+ret=PTR_ERR(vma);+gotoup_fail;+}++/*Map vdata to user space */+ret=io_remap_pfn_range(vma,vdso_base,+virt_to_phys(vdso_data)>>PAGE_SHIFT,+PAGE_SIZE,vma->vm_page_prot);+if(ret)+gotoup_fail;++/*Map timer to user space */+vdso_base+=PAGE_SIZE;+prot=__pgprot(_PAGE_V|_PAGE_M_UR_KR|_PAGE_D|+_PAGE_G|_PAGE_C_DEV);+ret=io_remap_pfn_range(vma,vdso_base,timer_res.start>>PAGE_SHIFT,+PAGE_SIZE,prot);+if(ret)+gotoup_fail;++/*Map vdso to user space */+vdso_base+=PAGE_SIZE;+mm->context.vdso=(void*)vdso_base;+vma=_install_special_mapping(mm,vdso_base,vdso_text_len,+VM_READ|VM_EXEC|+VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,+&vdso_spec[1]);+if(IS_ERR(vma)){+ret=PTR_ERR(vma);+gotoup_fail;+}++up_write(&mm->mmap_sem);+return0;++up_fail:+mm->context.vdso=NULL;+up_write(&mm->mmap_sem);+returnret;+}++staticvoidvdso_write_begin(structvdso_data*vdata)+{+++vdso_data->seq_count;+smp_wmb();/* Pairs with smp_rmb in vdso_read_retry */+}++staticvoidvdso_write_end(structvdso_data*vdata)+{+smp_wmb();/* Pairs with smp_rmb in vdso_read_begin */+++vdso_data->seq_count;+}++voidupdate_vsyscall(structtimekeeper*tk)+{+vdso_write_begin(vdso_data);+vdso_data->cs_mask=tk->tkr_mono.mask;+vdso_data->cs_mult=tk->tkr_mono.mult;+vdso_data->cs_shift=tk->tkr_mono.shift;+vdso_data->cs_cycle_last=tk->tkr_mono.cycle_last;+vdso_data->wtm_clock_sec=tk->wall_to_monotonic.tv_sec;+vdso_data->wtm_clock_nsec=tk->wall_to_monotonic.tv_nsec;+vdso_data->xtime_clock_sec=tk->xtime_sec;+vdso_data->xtime_clock_nsec=tk->tkr_mono.xtime_nsec;+vdso_data->xtime_coarse_sec=tk->xtime_sec;+vdso_data->xtime_coarse_nsec=tk->tkr_mono.xtime_nsec>>+tk->tkr_mono.shift;+vdso_write_end(vdso_data);+}++voidupdate_vsyscall_tz(void)+{+vdso_data->tz_minuteswest=sys_tz.tz_minuteswest;+vdso_data->tz_dsttime=sys_tz.tz_dsttime;+}
@@ -0,0 +1,82 @@+#+# Building a vDSO image for AArch64.+#+# Author: Will Deacon <will.deacon@arm.com>+# Heavily based on the vDSO Makefiles for other archs.+#++obj-vdso:=note.odatapage.osigreturn.ogettimeofday.o++# Build rules+targets:=$(obj-vdso)vdso.sovdso.so.dbg+obj-vdso:=$(addprefix$(obj)/,$(obj-vdso))++ccflags-y:=-shared-fno-common-fno-builtin+ccflags-y+=-nostdlib-Wl,-soname=linux-vdso.so.1\+$(callcc-ldoption,-Wl$(comma)--hash-style=sysv)+ccflags-y+=-fPIC-Wl,-shared-g++# Disable gcov profiling for VDSO code+GCOV_PROFILE:=n+++obj-y+=vdso.o+extra-y+=vdso.lds+CPPFLAGS_vdso.lds+=-P-C-U$(ARCH)++# Force dependency+$(obj)/vdso.o :$(obj)/vdso.so++# Link rule for the .so file, .lds has to be first+$(obj)/vdso.so.dbg:$(src)/vdso.lds$(obj-vdso)+$(callif_changed,vdsold)+++# Strip rule for the .so file+$(obj)/%.so:OBJCOPYFLAGS := -S+$(obj)/%.so:$(obj)/%.so.dbgFORCE+$(callif_changed,objcopy)++# Generate VDSO offsets using helper script+gen-vdsosym:=$(srctree)/$(src)/gen_vdso_offsets.sh+quiet_cmd_vdsosym=VDSOSYM$@+define cmd_vdsosym+$(NM)$<|$(gen-vdsosym)|LC_ALL=Csort>$@+endef++include/generated/vdso-offsets.h:$(obj)/vdso.so.dbgFORCE+$(callif_changed,vdsosym)++++# Assembly rules for the .S files++sigreturn.o :sigreturn.S+$(callif_changed_dep,vdsoas)++note.o :note.S+$(callif_changed_dep,vdsoas)++datapage.o :datapage.S+$(callif_changed_dep,vdsoas)++gettimeofday.o :gettimeofday.cFORCE+$(callif_changed_dep,vdsocc)++# Actual build commands+quiet_cmd_vdsold=VDSOL$@+cmd_vdsold=$(CC)$(c_flags)-Wl,-n-Wl,-T$^-o$@+quiet_cmd_vdsoas=VDSOA$@+cmd_vdsoas=$(CC)$(a_flags)-c-o$@$<+quiet_cmd_vdsocc=VDSOA$@+cmd_vdsocc=$(CC)$(c_flags)-c-o$@$<++# Install commands for the unstripped file+quiet_cmd_vdso_install=INSTALL$@+cmd_vdso_install=cp$(obj)/$@.dbg$(MODLIB)/vdso/$@++vdso.so:$(obj)/vdso.so.dbg+@mkdir-p$(MODLIB)/vdso+$(callcmd,vdso_install)++vdso_install:vdso.so
@@ -0,0 +1,15 @@+#!/bin/sh++#+# Match symbols in the DSO that look like VDSO_*; produce a header file+# of constant offsets into the shared object.+#+# Doing this inside the Makefile will break the $(filter-out) function,+# causing Kbuild to rebuild the vdso-offsets header file every time.+#+# Author: Will Deacon <will.deacon@arm.com+#++LC_ALL=C+sed-n-e's/^00*/0/'-e\+'s/^\([0-9a-fA-F]*\) . VDSO_\([a-zA-Z0-9_]*\)$/\#define vdso_offset_\2\t0x\1/p'
@@ -0,0 +1,478 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/types.h>+#include<linux/mm.h>+#include<linux/export.h>+#include<linux/string.h>+#include<linux/scatterlist.h>+#include<linux/dma-mapping.h>+#include<linux/io.h>+#include<linux/cache.h>+#include<linux/highmem.h>+#include<linux/slab.h>+#include<asm/cacheflush.h>+#include<asm/tlbflush.h>+#include<asm/dma-mapping.h>+#include<asm/proc-fns.h>++/*+*Thisisthepagetable(2MB)coveringuncached,DMAconsistentallocations+*/+staticpte_t*consistent_pte;+staticDEFINE_RAW_SPINLOCK(consistent_lock);++/*+*VMregionhandlingsupport.+*+*Thisshouldbecomesomethinggeneric,handlingVMregionallocationsfor+*vmallocandsimilar(ioremap,modulespace,etc).+*+*Ienvisagevmalloc()'ssupportingvm_structbecoming:+*+*structvm_struct{+*structvm_regionregion;+*unsignedlongflags;+*structpage**pages;+*unsignedintnr_pages;+*unsignedlongphys_addr;+*};+*+*get_vm_area()wouldthencallvm_region_allocwithanappropriate+*structvm_regionhead(eg):+*+*structvm_regionvmalloc_head={+*.vm_list=LIST_HEAD_INIT(vmalloc_head.vm_list),+*.vm_start=VMALLOC_START,+*.vm_end=VMALLOC_END,+*};+*+*However,vmalloc_head.vm_startisvariable(typically,itisdependenton+*theamountofRAMfoundatboottime.)Iwouldimaginethatget_vm_area()+*wouldhavetoinitialisethiseachtimepriortocallingvm_region_alloc().+*/+structarch_vm_region{+structlist_headvm_list;+unsignedlongvm_start;+unsignedlongvm_end;+structpage*vm_pages;+};++staticstructarch_vm_regionconsistent_head={+.vm_list=LIST_HEAD_INIT(consistent_head.vm_list),+.vm_start=CONSISTENT_BASE,+.vm_end=CONSISTENT_END,+};++staticstructarch_vm_region*vm_region_alloc(structarch_vm_region*head,+size_tsize,intgfp)+{+unsignedlongaddr=head->vm_start,end=head->vm_end-size;+unsignedlongflags;+structarch_vm_region*c,*new;++new=kmalloc(sizeof(structarch_vm_region),gfp);+if(!new)+gotoout;++raw_spin_lock_irqsave(&consistent_lock,flags);++list_for_each_entry(c,&head->vm_list,vm_list){+if((addr+size)<addr)+gotonospc;+if((addr+size)<=c->vm_start)+gotofound;+addr=c->vm_end;+if(addr>end)+gotonospc;+}++found:+/*+*Insertthisentry_before_theonewefound.+*/+list_add_tail(&new->vm_list,&c->vm_list);+new->vm_start=addr;+new->vm_end=addr+size;++raw_spin_unlock_irqrestore(&consistent_lock,flags);+returnnew;++nospc:+raw_spin_unlock_irqrestore(&consistent_lock,flags);+kfree(new);+out:+returnNULL;+}++staticstructarch_vm_region*vm_region_find(structarch_vm_region*head,+unsignedlongaddr)+{+structarch_vm_region*c;++list_for_each_entry(c,&head->vm_list,vm_list){+if(c->vm_start==addr)+gotoout;+}+c=NULL;+out:+returnc;+}++/* FIXME: attrs is not used. */+staticvoid*nds32_dma_alloc_coherent(structdevice*dev,size_tsize,+dma_addr_t*handle,gfp_tgfp,+unsignedlongattrs)+{+structpage*page;+structarch_vm_region*c;+unsignedlongorder;+u64mask=ISA_DMA_THRESHOLD,limit;+pgprot_tprot=pgprot_noncached(PAGE_KERNEL);++if(!consistent_pte){+pr_err("%s: not initialized\n",__func__);+dump_stack();+returnNULL;+}++if(dev){+mask=dev->coherent_dma_mask;++/*+*SanitychecktheDMAmask-itmustbenon-zero,and+*mustbeabletobesatisfiedbyaDMAallocation.+*/+if(mask==0){+dev_warn(dev,"coherent DMA mask is unset\n");+gotono_page;+}++if((~mask)&ISA_DMA_THRESHOLD){+dev_warn(dev,"coherent DMA mask %#llx is smaller "+"than system GFP_DMA mask %#llx\n",+mask,(unsignedlonglong)ISA_DMA_THRESHOLD);+gotono_page;+}+}++/*+*Sanitychecktheallocationsize.+*/+size=PAGE_ALIGN(size);+limit=(mask+1)&~mask;+if((limit&&size>=limit)||+size>=(CONSISTENT_END-CONSISTENT_BASE)){+pr_warn("coherent allocation too big "+"(requested %#x mask %#llx)\n",size,mask);+gotono_page;+}++order=get_order(size);++if(mask!=0xffffffff)+gfp|=GFP_DMA;++page=alloc_pages(gfp,order);+if(!page)+gotono_page;++/*+*Invalidateanydatathatmightbelurkinginthe+*kerneldirect-mappedregionfordeviceDMA.+*/+{+unsignedlongkaddr=(unsignedlong)page_address(page);+memset(page_address(page),0,size);+cpu_dma_wbinval_range(kaddr,kaddr+size);+}++/*+*Allocateavirtualaddressintheconsistentmappingregion.+*/+c=vm_region_alloc(&consistent_head,size,+gfp&~(__GFP_DMA|__GFP_HIGHMEM));+if(c){+pte_t*pte=consistent_pte+CONSISTENT_OFFSET(c->vm_start);+structpage*end=page+(1<<order);++c->vm_pages=page;++/*+*Setthe"dma handle"+*/+*handle=page_to_dma(dev,page);++do{+BUG_ON(!pte_none(*pte));++/*+*x86doesnotmarkthepagesreserved...+*/+SetPageReserved(page);+set_pte(pte,mk_pte(page,prot));+page++;+pte++;+}while(size-=PAGE_SIZE);++/*+*Freetheotherwiseunusedpages.+*/+while(page<end){+__free_page(page);+page++;+}++return(void*)c->vm_start;+}++if(page)+__free_pages(page,order);+no_page:+*handle=~0;+returnNULL;+}++staticvoidnds32_dma_free(structdevice*dev,size_tsize,void*cpu_addr,+dma_addr_thandle,unsignedlongattrs)+{+structarch_vm_region*c;+unsignedlongflags,addr;+pte_t*ptep;++size=PAGE_ALIGN(size);++raw_spin_lock_irqsave(&consistent_lock,flags);++c=vm_region_find(&consistent_head,(unsignedlong)cpu_addr);+if(!c)+gotono_area;++if((c->vm_end-c->vm_start)!=size){+pr_err("%s: freeing wrong coherent size (%ld != %d)\n",+__func__,c->vm_end-c->vm_start,size);+dump_stack();+size=c->vm_end-c->vm_start;+}++ptep=consistent_pte+CONSISTENT_OFFSET(c->vm_start);+addr=c->vm_start;+do{+pte_tpte=ptep_get_and_clear(&init_mm,addr,ptep);+unsignedlongpfn;++ptep++;+addr+=PAGE_SIZE;++if(!pte_none(pte)&&pte_present(pte)){+pfn=pte_pfn(pte);++if(pfn_valid(pfn)){+structpage*page=pfn_to_page(pfn);++/*+*x86doesnotmarkthepagesreserved...+*/+ClearPageReserved(page);++__free_page(page);+continue;+}+}++pr_crit("%s: bad page in kernel page table\n",__func__);+}while(size-=PAGE_SIZE);++flush_tlb_kernel_range(c->vm_start,c->vm_end);++list_del(&c->vm_list);++raw_spin_unlock_irqrestore(&consistent_lock,flags);++kfree(c);+return;++no_area:+raw_spin_unlock_irqrestore(&consistent_lock,flags);+pr_err("%s: trying to free invalid coherent area: %p\n",+__func__,cpu_addr);+dump_stack();+}++/*+*Initialisetheconsistentmemoryallocation.+*/+staticint__initconsistent_init(void)+{+pgd_t*pgd;+pmd_t*pmd;+pte_t*pte;+intret=0;++do{+pgd=pgd_offset(&init_mm,CONSISTENT_BASE);+pmd=pmd_alloc(&init_mm,pgd,CONSISTENT_BASE);+if(!pmd){+pr_err("%s: no pmd tables\n",__func__);+ret=-ENOMEM;+break;+}+/* The first level mapping may be created in somewhere.+*It'snotnecessarytowarnhere.*/+/* WARN_ON(!pmd_none(*pmd)); */++pte=pte_alloc_kernel(pmd,CONSISTENT_BASE);+if(!pte){+ret=-ENOMEM;+break;+}++consistent_pte=pte;+}while(0);++returnret;+}++core_initcall(consistent_init);+staticvoidconsistent_sync(void*vaddr,size_tsize,intdirection);+staticdma_addr_tnds32_dma_map_page(structdevice*dev,structpage*page,+unsignedlongoffset,size_tsize,+enumdma_data_directiondir,+unsignedlongattrs)+{+consistent_sync((void*)(page_address(page)+offset),size,dir);+returnpage_to_phys(page)+offset;+}++staticvoidnds32_dma_unmap_page(structdevice*dev,dma_addr_thandle,+size_tsize,enumdma_data_directiondir,+unsignedlongattrs)+{+consistent_sync(phys_to_virt(handle),size,dir);+}++/*+*Makeanareaconsistentfordevices.+*/+staticvoidconsistent_sync(void*vaddr,size_tsize,intdirection)+{+unsignedlongstart=(unsignedlong)vaddr;+unsignedlongend=start+size;++switch(direction){+caseDMA_FROM_DEVICE:/* invalidate only */+cpu_dma_inval_range(start,end);+break;+caseDMA_TO_DEVICE:/* writeback only */+cpu_dma_wb_range(start,end);+break;+caseDMA_BIDIRECTIONAL:/* writeback and invalidate */+cpu_dma_wbinval_range(start,end);+break;+default:+BUG();+}+}++staticintnds32_dma_map_sg(structdevice*dev,structscatterlist*sg,+intnents,enumdma_data_directiondir,+unsignedlongattrs)+{+inti;++for(i=0;i<nents;i++,sg++){+void*virt;+unsignedlongpfn;+structpage*page=sg_page(sg);++sg->dma_address=page_to_dma(dev,page)+sg->offset;+pfn=page_to_pfn(page)+sg->offset/PAGE_SIZE;+page=pfn_to_page(pfn);+if(PageHighMem(page)){+virt=kmap_atomic(page);+consistent_sync(virt,sg->length,dir);+kunmap_atomic(virt);+}else{+if(sg->offset>PAGE_SIZE)+panic("sg->offset:%08x > PAGE_SIZE\n",+sg->offset);+virt=page_address(page)+sg->offset;+consistent_sync(virt,sg->length,dir);+}+}+returnnents;+}++staticvoidnds32_dma_unmap_sg(structdevice*dev,structscatterlist*sg,+intnhwentries,enumdma_data_directiondir,+unsignedlongattrs)+{+}++staticvoid+nds32_dma_sync_single_for_cpu(structdevice*dev,dma_addr_thandle,+size_tsize,enumdma_data_directiondir)+{+consistent_sync((void*)dma_to_virt(dev,handle),size,dir);+}++staticvoid+nds32_dma_sync_single_for_device(structdevice*dev,dma_addr_thandle,+size_tsize,enumdma_data_directiondir)+{+consistent_sync((void*)dma_to_virt(dev,handle),size,dir);+}++staticvoid+nds32_dma_sync_sg_for_cpu(structdevice*dev,structscatterlist*sg,intnents,+enumdma_data_directiondir)+{+inti;++for(i=0;i<nents;i++,sg++){+char*virt=+page_address((structpage*)sg->page_link)+sg->offset;+consistent_sync(virt,sg->length,dir);+}+}++staticvoid+nds32_dma_sync_sg_for_device(structdevice*dev,structscatterlist*sg,+intnents,enumdma_data_directiondir)+{+inti;++for(i=0;i<nents;i++,sg++){+char*virt=+page_address((structpage*)sg->page_link)+sg->offset;+consistent_sync(virt,sg->length,dir);+}+}++structdma_map_opsnds32_dma_ops={+.alloc=nds32_dma_alloc_coherent,+.free=nds32_dma_free,+.map_page=nds32_dma_map_page,+.unmap_page=nds32_dma_unmap_page,+.map_sg=nds32_dma_map_sg,+.unmap_sg=nds32_dma_unmap_sg,+.sync_single_for_device=nds32_dma_sync_single_for_device,+.sync_single_for_cpu=nds32_dma_sync_single_for_cpu,+.sync_sg_for_cpu=nds32_dma_sync_sg_for_cpu,+.sync_sg_for_device=nds32_dma_sync_sg_for_device,+};++EXPORT_SYMBOL(nds32_dma_ops);
@@ -0,0 +1,420 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/extable.h>+#include<linux/module.h>+#include<linux/signal.h>+#include<linux/ptrace.h>+#include<linux/mm.h>+#include<linux/init.h>+#include<linux/hardirq.h>++#include<asm/pgtable.h>+#include<asm/tlbflush.h>+#include<asm/uaccess.h>++externvoiddie(constchar*str,structpt_regs*regs,longerr);++/*+*Thisisusefultodumpoutthepagetablesassociatedwith+*'addr'inmm'mm'.+*/+voidshow_pte(structmm_struct*mm,unsignedlongaddr)+{+pgd_t*pgd;+if(!mm)+mm=&init_mm;++pr_alert("pgd = %p\n",mm->pgd);+pgd=pgd_offset(mm,addr);+pr_alert("[%08lx] *pgd=%08lx",addr,pgd_val(*pgd));++do{+pmd_t*pmd;++if(pgd_none(*pgd))+break;++if(pgd_bad(*pgd)){+pr_alert("(bad)");+break;+}++pmd=pmd_offset(pgd,addr);+#if PTRS_PER_PMD != 1+pr_alert(", *pmd=%08lx",pmd_val(*pmd));+#endif++if(pmd_none(*pmd))+break;++if(pmd_bad(*pmd)){+pr_alert("(bad)");+break;+}+#ifndef CONFIG_HIGHMEM+{+pte_t*pte;+/* We must not map this if we have highmem enabled */+pte=pte_offset_map(pmd,addr);+pr_alert(", *pte=%08lx",pte_val(*pte));+pte_unmap(pte);+}+#endif+}while(0);++pr_alert("\n");+}++voiddo_page_fault(unsignedlongentry,unsignedlongaddr,+unsignedinterror_code,structpt_regs*regs)+{+structtask_struct*tsk;+structmm_struct*mm;+structvm_area_struct*vma;+siginfo_tinfo;+intfault;+unsignedintmask=VM_READ|VM_WRITE|VM_EXEC;+unsignedintflags=FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE;++error_code=error_code&(ITYPE_mskINST|ITYPE_mskETYPE);+tsk=current;+mm=tsk->mm;+info.si_code=SEGV_MAPERR;+/*+*Wefault-inkernel-spacevirtualmemoryon-demand.The+*'reference'pagetableisinit_mm.pgd.+*+*NOTE!WeMUSTNOTtakeanylocksforthiscase.Wemay+*beinaninterruptoracriticalregion,andshould+*onlycopytheinformationfromthemasterpagetable,+*nothingmore.+*/+if(addr>=TASK_SIZE){+if(user_mode(regs))+gotobad_area_nosemaphore;++if(addr>=TASK_SIZE&&addr<VMALLOC_END+&&(entry==ENTRY_PTE_NOT_PRESENT))+gotovmalloc_fault;+else+gotono_context;+}++/* Send a signal to the task for handling the unalignment access. */+if(entry==ENTRY_GENERAL_EXCPETION+&&error_code==ETYPE_ALIGNMENT_CHECK){+if(user_mode(regs))+gotobad_area_nosemaphore;+else+gotono_context;+}++/*+*Ifwe'reinaninterruptorhavenouser+*context,wemustnottakethefault..+*/+if(unlikely(in_atomic()||!mm))+gotono_context;++/*+*Asperx86,wemaydeadlockhere.However,sincethekernelonly+*validlyreferencesuserspacefromwelldefinedareasofthecode,+*wecanbugoutearlyifthisisfromcodewhichshouldn't.+*/+if(unlikely(!down_read_trylock(&mm->mmap_sem))){+if(!user_mode(regs)&&+!search_exception_tables(instruction_pointer(regs)))+gotono_context;+retry:+down_read(&mm->mmap_sem);+}else{+/*+*Theabovedown_read_trylock()mighthavesucceededinwhich+*case,we'llhavemissedthemight_sleep()fromdown_read().+*/+might_sleep();+#ifdef CONFIG_DEBUG_VM+if(!user_mode(regs)&&+!search_exception_tables(instruction_pointer(regs)))+gotono_context;+#endif+}++vma=find_vma(mm,addr);++if(unlikely(!vma))+gotobad_area;++if(vma->vm_start<=addr)+gotogood_area;++if(unlikely(!(vma->vm_flags&VM_GROWSDOWN)))+gotobad_area;++if(unlikely(expand_stack(vma,addr)))+gotobad_area;++/*+*Ok,wehaveagoodvm_areaforthismemoryaccess,so+*wecanhandleit..+*/++good_area:+info.si_code=SEGV_ACCERR;++/* first do some preliminary protection checks */+if(entry==ENTRY_PTE_NOT_PRESENT){+if(error_code&ITYPE_mskINST)+mask=VM_EXEC;+else{+mask=VM_READ|VM_WRITE;+if(vma->vm_flags&VM_WRITE)+flags|=FAULT_FLAG_WRITE;+}+}elseif(entry==ENTRY_TLB_MISC){+switch(error_code&ITYPE_mskETYPE){+caseRD_PROT:+mask=VM_READ;+break;+caseWRT_PROT:+mask=VM_WRITE;+flags|=FAULT_FLAG_WRITE;+break;+caseNOEXEC:+mask=VM_EXEC;+break;+casePAGE_MODIFY:+mask=VM_WRITE;+flags|=FAULT_FLAG_WRITE;+break;+caseACC_BIT:+BUG();+default:+break;+}++}+if(!(vma->vm_flags&mask))+gotobad_area;++/*+*Ifforanyreasonatallwecouldn'thandlethefault,+*makesureweexitgracefullyratherthanendlesslyredo+*thefault.+*/++fault=handle_mm_fault(vma,addr,flags);++/*+*Ifweneedtoretrybutafatalsignalispending,handlethe+*signalfirst.Wedonotneedtoreleasethemmap_sembecauseit+*wouldalreadybereleasedin__lock_page_or_retryinmm/filemap.c.+*/+if((fault&VM_FAULT_RETRY)&&fatal_signal_pending(current))+return;++if(unlikely(fault&VM_FAULT_ERROR)){+if(fault&VM_FAULT_OOM)+gotoout_of_memory;+elseif(fault&VM_FAULT_SIGBUS)+gotodo_sigbus;+else+gotobad_area;+}++/*+*Major/minorpagefaultaccountingisonlydoneontheinitial+*attempt.Ifwegothrougharetry,itisextremelylikelythatthe+*pagewillbefoundinpagecacheatthatpoint.+*/+if(flags&FAULT_FLAG_ALLOW_RETRY){+if(fault&VM_FAULT_MAJOR)+tsk->maj_flt++;+else+tsk->min_flt++;+if(fault&VM_FAULT_RETRY){+flags&=~FAULT_FLAG_ALLOW_RETRY;+flags|=FAULT_FLAG_TRIED;++/* No need to up_read(&mm->mmap_sem) as we would+*havealreadyreleaseditin__lock_page_or_retry+*inmm/filemap.c.+*/+gotoretry;+}+}++up_read(&mm->mmap_sem);+return;++/*+*Somethingtriedtoaccessmemorythatisn'tinourmemorymap..+*Fixit,butcheckifit'skerneloruserfirst..+*/+bad_area:+up_read(&mm->mmap_sem);++bad_area_nosemaphore:++/* User mode accesses just cause a SIGSEGV */++if(user_mode(regs)){+tsk->thread.address=addr;+tsk->thread.error_code=error_code;+tsk->thread.trap_no=entry;+info.si_signo=SIGSEGV;+info.si_errno=0;+/* info.si_code has been set above */+info.si_addr=(void*)addr;+force_sig_info(SIGSEGV,&info,tsk);+return;+}++no_context:++/* Are we prepared to handle this kernel fault?+*+*(Thekernelhasvalidexception-pointsinthesource+*whenitacessesuser-memory.Whenitfailsinone+*ofthosepoints,wefinditinatableanddoajump+*tosomefixupcodethatloadsanappropriateerror+*code)+*/++{+conststructexception_table_entry*entry;++if((entry=+search_exception_tables(instruction_pointer(regs)))!=+NULL){+/* Adjust the instruction pointer in the stackframe */+instruction_pointer(regs)=entry->fixup;+return;+}+}++/*+*Oops.Thekerneltriedtoaccesssomebadpage.We'llhaveto+*terminatethingswithextremeprejudice.+*/++bust_spinlocks(1);+pr_alert("Unable to handle kernel %s at virtual address %08lx\n",+(addr<PAGE_SIZE)?"NULL pointer dereference":+"paging request",addr);++show_pte(mm,addr);+die("Oops",regs,error_code);+bust_spinlocks(0);+do_exit(SIGKILL);++return;++/*+*Weranoutofmemory,orsomeotherthinghappenedtousthatmade+*usunabletohandlethepagefaultgracefully.+*/++out_of_memory:+up_read(&mm->mmap_sem);+if(!user_mode(regs))+gotono_context;+pagefault_out_of_memory();+return;++do_sigbus:+up_read(&mm->mmap_sem);++/* Kernel mode? Handle exceptions or die */+if(!user_mode(regs))+gotono_context;++/*+*Sendasigbus+*/+tsk->thread.address=addr;+tsk->thread.error_code=error_code;+tsk->thread.trap_no=entry;+info.si_signo=SIGBUS;+info.si_errno=0;+info.si_code=BUS_ADRERR;+info.si_addr=(void*)addr;+force_sig_info(SIGBUS,&info,tsk);++return;++vmalloc_fault:+{+/*+*Synchronizethistask'stoplevelpage-table+*withthe'reference'pagetable.+*+*Usecurrent_pgdinsteadoftsk->active_mm->pgd+*sincethelattermightbeunavailableifthis+*codeisexecutedinamisfortunatelyrunirq+*(likeinsideschedule()betweenswitch_mmand+*switch_to...).+*/++unsignedintindex=pgd_index(addr);+pgd_t*pgd,*pgd_k;+pud_t*pud,*pud_k;+pmd_t*pmd,*pmd_k;+pte_t*pte_k;++pgd=(pgd_t*)__va(__nds32__mfsr(NDS32_SR_L1_PPTB))+index;+pgd_k=init_mm.pgd+index;++if(!pgd_present(*pgd_k))+gotono_context;++pud=pud_offset(pgd,addr);+pud_k=pud_offset(pgd_k,addr);+if(!pud_present(*pud_k))+gotono_context;++pmd=pmd_offset(pud,addr);+pmd_k=pmd_offset(pud_k,addr);+if(!pmd_present(*pmd_k))+gotono_context;++if(!pmd_present(*pmd))+set_pmd(pmd,*pmd_k);+else+BUG_ON(pmd_page(*pmd)!=pmd_page(*pmd_k));++/*+*Sincethevmallocareaisglobal,wedon't+*needtocopyindividualPTE's,itisenoughto+*copythepgdpointerintotheptepageofthe+*roottask.Ifthatisthere,we'llfindourpteif+*itexists.+*/++/* Make sure the actual PTE exists as well to+*catchkernelvmalloc-areaaccessestonon-mapped+*addres.Ifwedon'tdothis,thiswilljust+*silentlyloopforever.+*/++pte_k=pte_offset_kernel(pmd_k,addr);+if(!pte_present(*pte_k))+gotono_context;++return;+}+}
@@ -0,0 +1,328 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/kernel.h>+#include<linux/errno.h>+#include<linux/swap.h>+#include<linux/init.h>+#include<linux/bootmem.h>+#include<linux/mman.h>+#include<linux/nodemask.h>+#include<linux/initrd.h>+#include<linux/highmem.h>+#include<linux/memblock.h>++#include<asm/sections.h>+#include<asm/setup.h>+#include<asm/tlb.h>+#include<asm/page.h>++DEFINE_PER_CPU(structmmu_gather,mmu_gathers);+DEFINE_SPINLOCK(anon_alias_lock);+externpgd_tswapper_pg_dir[PTRS_PER_PGD];+externunsignedlongphys_initrd_start;+externunsignedlongphys_initrd_size;++/*+*empty_zero_pageisaspecialpagethatisusedfor+*zero-initializeddataandCOW.+*/+structpage*empty_zero_page;+#ifdef CONFIG_EARLY_PRINTK+#include<asm/fixmap.h>++/*+*UsingtlboptocreateanearlyI/Omapping+*/+void__iomem*__initearly_io_map(phys_addr_tpa)+{+unsignedlongva;+pa&=PAGE_MASK;+pa+=pgprot_val(PAGE_DEVICE);+va=__fix_to_virt(FIX_EARLY_DEBUG);+/* insert and lock this page to tlb entry directly */++__nds32__mtsr_dsb(va,NDS32_SR_TLB_VPN);+__nds32__tlbop_rwlk(pa);+__nds32__isb();+return(void__iomem*)va;+}++int__initearly_io_unmap(void)+{+unsignedlongva;+va=__fix_to_virt(FIX_EARLY_DEBUG);+__nds32__tlbop_unlk(va);+__nds32__tlbop_inv(va);+__nds32__isb();+return0;+}++late_initcall(early_io_unmap);+#endif++staticvoid__initzone_sizes_init(void)+{+unsignedlongzones_size[MAX_NR_ZONES];++/* Clear the zone sizes */+memset(zones_size,0,sizeof(zones_size));++zones_size[ZONE_NORMAL]=max_low_pfn;+#ifdef CONFIG_HIGHMEM+zones_size[ZONE_HIGHMEM]=max_pfn;+#endif+free_area_init_nodes(zones_size);++}++/*+*Mapallphysicalmemoryunderhigh_memoryintokernel'saddressspace.+*+*Thisisexplicitlycodedfortwo-levelpagetables,soifyouneed+*somethingelsethenthisneedstochange.+*/+staticvoid__initmap_ram(void)+{+unsignedlongv,p,e;+pgd_t*pge;+pud_t*pue;+pmd_t*pme;+pte_t*pte;+/* These mark extents of read-only kernel pages...+*...fromvmlinux.lds.S+*/++p=(u32)memblock_start_of_DRAM()&PAGE_MASK;+e=min((u32)memblock_end_of_DRAM(),(u32)__pa(high_memory));++v=(u32)__va(p);+pge=pgd_offset_k(v);++while(p<e){+intj;+pue=pud_offset(pge,v);+pme=pmd_offset(pue,v);++if((u32)pue!=(u32)pge||(u32)pme!=(u32)pge){+panic("%s: Kernel hardcoded for "+"two-level page tables",__func__);+}++/* Alloc one page for holding PTE's... */+pte=(pte_t*)alloc_bootmem_low_pages(PAGE_SIZE);+set_pmd(pme,__pmd(__pa(pte)+_PAGE_KERNEL_TABLE));++/* Fill the newly allocated page with PTE'S */+for(j=0;p<e&&j<PTRS_PER_PTE;+v+=PAGE_SIZE,p+=PAGE_SIZE,j++,pte++){+/* Create mapping between p and v. */+/* TODO: more fine grant for page access permission */+set_pte(pte,__pte(p+pgprot_val(PAGE_KERNEL)));+}++pge++;+}+}++staticvoid__initfixedrange_init(void)+{+unsignedlongvaddr;+pgd_t*pgd;+pud_t*pud;+pmd_t*pmd;+pte_t*pte;++/*+*Fixedmappings:+*/+vaddr=__fix_to_virt(__end_of_fixed_addresses-1);+pgd=swapper_pg_dir+pgd_index(vaddr);+pud=pud_offset(pgd,vaddr);+pmd=pmd_offset(pud,vaddr);+pte=(pte_t*)alloc_bootmem_low_pages(PAGE_SIZE);+set_pmd(pmd,__pmd(__pa(pte)+_PAGE_KERNEL_TABLE));++#ifdef CONFIG_HIGHMEM+/*+*Permanentkmaps:+*/+vaddr=PKMAP_BASE;++pgd=swapper_pg_dir+pgd_index(vaddr);+pud=pud_offset(pgd,vaddr);+pmd=pmd_offset(pud,vaddr);+pte=(pte_t*)alloc_bootmem_low_pages(PAGE_SIZE);+set_pmd(pmd,__pmd(__pa(pte)+_PAGE_KERNEL_TABLE));+pkmap_page_table=pte;+#endif /* CONFIG_HIGHMEM */+}++/*+*paging_init()setsupthepagetables,initialisesthezonememory+*maps,andsetsupthezeropage,badpageandbadpagetables.+*/+void__initpaging_init(void)+{+void*zero_page;+inti;++pr_info("Setting up paging and PTEs.\n");+/* clear out the init_mm.pgd that will contain the kernel's mappings */+for(i=0;i<PTRS_PER_PGD;i++)+swapper_pg_dir[i]=__pgd(1);++map_ram();++fixedrange_init();++/* allocate space for empty_zero_page */+zero_page=alloc_bootmem_low_pages(PAGE_SIZE);+memset(zero_page,0,PAGE_SIZE);++zone_sizes_init();++empty_zero_page=virt_to_page(zero_page);+flush_dcache_page(empty_zero_page);+}++staticinlineintfree_area(unsignedlongaddr,unsignedlongend,char*s)+{+unsignedintsize=(end-addr)>>10;+intpages=0;++for(;addr<end;addr+=PAGE_SIZE){+structpage*page=virt_to_page(addr);+ClearPageReserved(page);+init_page_count(page);+free_page(addr);+totalram_pages++;+pages++;+}++if(size&&s)+pr_info("free_area: Freeing %s memory: %dK\n",s,size);++returnpages;+}++staticinlinevoid__initfree_highmem(void)+{+#ifdef CONFIG_HIGHMEM+unsignedlongpfn;+for(pfn=PFN_UP(__pa(high_memory));pfn<max_pfn;pfn++){+phys_addr_tpaddr=(phys_addr_t)pfn<<PAGE_SHIFT;+if(!memblock_is_reserved(paddr))+free_highmem_page(pfn_to_page(pfn));+}+#endif+}++staticvoid__initset_max_mapnr_init(void)+{+max_mapnr=max_pfn;+}++/*+*mem_init()marksthefreeareasinthemem_mapandtellsushowmuch+*memoryisfree.Thisisdoneaftervariouspartsofthesystemhave+*claimedtheirmemoryafterthekernelimage.+*/+void__initmem_init(void)+{+phys_addr_tmemory_start=memblock_start_of_DRAM();+BUG_ON(!mem_map);+set_max_mapnr_init();++free_highmem();++/* this will put all low memory onto the freelists */+free_all_bootmem();++pr_info("virtual kernel memory layout:\n"+" fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"+#ifdef CONFIG_HIGHMEM+" pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"+#endif+" consist : 0x%08lx - 0x%08lx (%4ld MB)\n"+" vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"+" lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"+" .init : 0x%08lx - 0x%08lx (%4ld kB)\n"+" .data : 0x%08lx - 0x%08lx (%4ld kB)\n"+" .text : 0x%08lx - 0x%08lx (%4ld kB)\n",+FIXADDR_START,FIXADDR_TOP,(FIXADDR_TOP-FIXADDR_START)>>10,+#ifdef CONFIG_HIGHMEM+PKMAP_BASE,PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,+(LAST_PKMAP*PAGE_SIZE)>>10,+#endif+CONSISTENT_BASE,CONSISTENT_END,+((CONSISTENT_END)-(CONSISTENT_BASE))>>20,VMALLOC_START,+(unsignedlong)VMALLOC_END,(VMALLOC_END-VMALLOC_START)>>20,+(unsignedlong)__va(memory_start),(unsignedlong)high_memory,+((unsignedlong)high_memory-+(unsignedlong)__va(memory_start))>>20,+(unsignedlong)&__init_begin,(unsignedlong)&__init_end,+((unsignedlong)&__init_end-+(unsignedlong)&__init_begin)>>10,(unsignedlong)&_etext,+(unsignedlong)&_edata,+((unsignedlong)&_edata-(unsignedlong)&_etext)>>10,+(unsignedlong)&_text,(unsignedlong)&_etext,+((unsignedlong)&_etext-(unsignedlong)&_text)>>10);++/*+*Checkboundariestwice:Somefundamentalinconsistenciescan+*bedetectedatbuildtimealready.+*/+#ifdef CONFIG_HIGHMEM+BUILD_BUG_ON(PKMAP_BASE+LAST_PKMAP*PAGE_SIZE>FIXADDR_START);+BUILD_BUG_ON((CONSISTENT_END)>PKMAP_BASE);+#endif+BUILD_BUG_ON(VMALLOC_END>CONSISTENT_BASE);+BUILD_BUG_ON(VMALLOC_START>=VMALLOC_END);++#ifdef CONFIG_HIGHMEM+BUG_ON(PKMAP_BASE+LAST_PKMAP*PAGE_SIZE>FIXADDR_START);+BUG_ON(CONSISTENT_END>PKMAP_BASE);+#endif+BUG_ON(VMALLOC_END>CONSISTENT_BASE);+BUG_ON(VMALLOC_START>=VMALLOC_END);+BUG_ON((unsignedlong)high_memory>VMALLOC_START);++return;+}++voidfree_initmem(void)+{+free_initmem_default(-1);+}++#ifdef CONFIG_BLK_DEV_INITRD+staticintkeep_initrd;++voidfree_initrd_mem(unsignedlongstart,unsignedlongend)+{+if(!keep_initrd)+free_area(start,end,"initrd");+}++staticint__initkeepinitrd_setup(char*__unused)+{+keep_initrd=1;+return1;+}++__setup("keepinitrd",keepinitrd_setup);+#endif
@@ -0,0 +1,406 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/cpu.h>+#include<linux/bootmem.h>+#include<linux/seq_file.h>+#include<linux/memblock.h>+#include<linux/console.h>+#include<linux/screen_info.h>+#include<linux/delay.h>+#include<linux/dma-mapping.h>+#include<linux/of_fdt.h>+#include<linux/of_platform.h>+#include<asm/setup.h>+#include<asm/sections.h>+#include<asm/proc-fns.h>+#include<asm/cache_info.h>+#include<asm/elf.h>+#include<nds32_intrinsic.h>++#define HWCAP_MFUSR_PC 0x000001+#define HWCAP_EXT 0x000002+#define HWCAP_EXT2 0x000004+#define HWCAP_FPU 0x000008+#define HWCAP_AUDIO 0x000010+#define HWCAP_BASE16 0x000020+#define HWCAP_STRING 0x000040+#define HWCAP_REDUCED_REGS 0x000080+#define HWCAP_VIDEO 0x000100+#define HWCAP_ENCRYPT 0x000200+#define HWCAP_EDM 0x000400+#define HWCAP_LMDMA 0x000800+#define HWCAP_PFM 0x001000+#define HWCAP_HSMP 0x002000+#define HWCAP_TRACE 0x004000+#define HWCAP_DIV 0x008000+#define HWCAP_MAC 0x010000+#define HWCAP_L2C 0x020000+#define HWCAP_FPU_DP 0x040000+#define HWCAP_V2 0x080000+#define HWCAP_DX_REGS 0x100000++externstructmm_structinit_mm;+unsignedlongcpu_id,cpu_rev,cpu_cfgid;+charcpu_series;+char*endianness=NULL;++unsignedint__atags_pointer__initdata;+unsignedintelf_hwcap;+EXPORT_SYMBOL(elf_hwcap);++externvoid__initearly_init_devtree(void*params);+externvoid__initearly_trap_init(void);+/*+*Thefollowingstringtable,mustsyncwithHWCAP_xxbitmask,+*whichisdefinedin<asm/procinfo.h>+*/+staticconstchar*hwcap_str[]={+"mfusr_pc",+"perf1",+"perf2",+"fpu",+"audio",+"16b",+"string",+"reduced_regs",+"video",+"encrypt",+"edm",+"lmdma",+"pfm",+"hsmp",+"trace",+"div",+"mac",+"l2c",+"dx_regs",+"v2",+NULL,+};++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH+#define WRITE_METHOD "write through"+#else+#define WRITE_METHOD "write back"+#endif++structcache_infoL1_cache_info[2];+staticvoid__initdump_cpu_info(intcpu)+{+inti,p=0;+charstr[sizeof(hwcap_str)+16];++for(i=0;hwcap_str[i];i++){+if(elf_hwcap&(1<<i)){+sprintf(str+p,"%s ",hwcap_str[i]);+p+=strlen(hwcap_str[i])+1;+}+}++pr_info("CPU%d Featuretures: %s\n",cpu,str);++L1_cache_info[ICACHE].ways=CACHE_WAY(ICACHE);+L1_cache_info[ICACHE].line_size=CACHE_LINE_SIZE(ICACHE);+L1_cache_info[ICACHE].sets=CACHE_SET(ICACHE);+L1_cache_info[ICACHE].size=+L1_cache_info[ICACHE].ways*L1_cache_info[ICACHE].line_size*+L1_cache_info[ICACHE].sets/1024;+pr_info("L1I:%dKB/%dS/%dW/%dB\n",L1_cache_info[ICACHE].size,+L1_cache_info[ICACHE].sets,L1_cache_info[ICACHE].ways,+L1_cache_info[ICACHE].line_size);+L1_cache_info[DCACHE].ways=CACHE_WAY(DCACHE);+L1_cache_info[DCACHE].line_size=CACHE_LINE_SIZE(DCACHE);+L1_cache_info[DCACHE].sets=CACHE_SET(DCACHE);+L1_cache_info[DCACHE].size=+L1_cache_info[DCACHE].ways*L1_cache_info[DCACHE].line_size*+L1_cache_info[DCACHE].sets/1024;+pr_info("L1D:%dKB/%dS/%dW/%dB\n",L1_cache_info[DCACHE].size,+L1_cache_info[DCACHE].sets,L1_cache_info[DCACHE].ways,+L1_cache_info[DCACHE].line_size);+pr_info("L1 D-Cache is %s\n",WRITE_METHOD);+if(L1_cache_info[DCACHE].size!=L1_CACHE_BYTES)+pr_crit+("The cache line size(%d) of this processor is not the same as L1_CACHE_BYTES(%d).\n",+L1_cache_info[DCACHE].size,L1_CACHE_BYTES);+#if !defined(CONFIG_CPU_CACHE_NONALIASING)+{+intaliasing_num;+aliasing_num=+L1_cache_info[ICACHE].size*1024/PAGE_SIZE/+L1_cache_info[ICACHE].ways;+L1_cache_info[ICACHE].aliasing_num=aliasing_num;+L1_cache_info[ICACHE].aliasing_mask=+(aliasing_num-1)<<PAGE_SHIFT;+aliasing_num=+L1_cache_info[DCACHE].size*1024/PAGE_SIZE/+L1_cache_info[DCACHE].ways;+L1_cache_info[DCACHE].aliasing_num=aliasing_num;+L1_cache_info[DCACHE].aliasing_mask=+(aliasing_num-1)<<PAGE_SHIFT;+}+#endif++}++staticvoid__initsetup_cpuinfo(void)+{+unsignedlongtmp=0,cpu_name;++cpu_dcache_inval_all();+cpu_icache_inval_all();+__nds32__isb();++cpu_id=(__nds32__mfsr(NDS32_SR_CPU_VER)&CPU_VER_mskCPUID)>>CPU_VER_offCPUID;+cpu_name=((cpu_id)&0xf0)>>4;+cpu_series=cpu_name?cpu_name-10+'A':'N';+cpu_id=cpu_id&0xf;+cpu_rev=(__nds32__mfsr(NDS32_SR_CPU_VER)&CPU_VER_mskREV)>>CPU_VER_offREV;+cpu_cfgid=(__nds32__mfsr(NDS32_SR_CPU_VER)&CPU_VER_mskCFGID)>>CPU_VER_offCFGID;++pr_info("CPU:%c%ld, CPU_VER 0x%08x(id %lu, rev %lu, cfg %lu)\n",+cpu_series,cpu_id,__nds32__mfsr(NDS32_SR_CPU_VER),cpu_id,cpu_rev,cpu_cfgid);++elf_hwcap|=HWCAP_MFUSR_PC;++if(((__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskBASEV)>>MSC_CFG_offBASEV)==0){+if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskDIV)+elf_hwcap|=HWCAP_DIV;++if((__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskMAC)+||(cpu_id==12&&cpu_rev<4))+elf_hwcap|=HWCAP_MAC;+}else{+elf_hwcap|=HWCAP_V2;+elf_hwcap|=HWCAP_DIV;+elf_hwcap|=HWCAP_MAC;+}++if(cpu_cfgid&0x0001)+elf_hwcap|=HWCAP_EXT;++if(cpu_cfgid&0x0002)+elf_hwcap|=HWCAP_BASE16;++if(cpu_cfgid&0x0004)+elf_hwcap|=HWCAP_EXT2;++if(cpu_cfgid&0x0008)+elf_hwcap|=HWCAP_FPU;++if(cpu_cfgid&0x0010)+elf_hwcap|=HWCAP_STRING;++if(__nds32__mfsr(NDS32_SR_MMU_CFG)&MMU_CFG_mskDE)+endianness="MSB";+else+endianness="LSB";++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskEDM)+elf_hwcap|=HWCAP_EDM;++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskLMDMA)+elf_hwcap|=HWCAP_LMDMA;++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskPFM)+elf_hwcap|=HWCAP_PFM;++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskHSMP)+elf_hwcap|=HWCAP_HSMP;++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskTRACE)+elf_hwcap|=HWCAP_TRACE;++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskAUDIO)+elf_hwcap|=HWCAP_AUDIO;++if(__nds32__mfsr(NDS32_SR_MSC_CFG)&MSC_CFG_mskL2C)+elf_hwcap|=HWCAP_L2C;++tmp=__nds32__mfsr(NDS32_SR_CACHE_CTL);+#ifndef CONFIG_CPU_DCACHE_DISABLE+tmp|=CACHE_CTL_mskDC_EN;+#endif++#ifndef CONFIG_CPU_ICACHE_DISABLE+tmp|=CACHE_CTL_mskIC_EN;+#endif+__nds32__mtsr_isb(tmp,NDS32_SR_CACHE_CTL);++dump_cpu_info(smp_processor_id());+}++staticunsignedlong__initsetup_memory(void)+{+unsignedlongbootmap_size;+unsignedlongram_start_pfn;+unsignedlongfree_ram_start_pfn;+phys_addr_tmemory_start,memory_end;+structmemblock_region*region;++memory_end=memory_start=0;++/* Find main memory where is the kernel */+for_each_memblock(memory,region){+memory_start=region->base;+memory_end=region->base+region->size;+pr_info("%s: Memory: 0x%x-0x%x\n",__func__,+memory_start,memory_end);+}++if(!memory_end){+panic("No memory!");+}++ram_start_pfn=PFN_UP(memblock_start_of_DRAM());+/* free_ram_start_pfn is first page after kernel */+free_ram_start_pfn=PFN_UP(__pa(&_end));+max_pfn=PFN_DOWN(memblock_end_of_DRAM());++/* it could update max_pfn */+if(max_pfn-ram_start_pfn<=MAXMEM_PFN)+max_low_pfn=max_pfn;+else{+max_low_pfn=MAXMEM_PFN+ram_start_pfn;+#ifndef CONFIG_HIGHMEM+max_pfn=MAXMEM_PFN+ram_start_pfn;+#endif+}+/* high_memory is related with VMALLOC */+high_memory=(void*)__va(max_low_pfn*PAGE_SIZE);+min_low_pfn=free_ram_start_pfn;++/*+*initializetheboot-timeallocator(withlowmemoryonly).+*+*Thismakesthememoryfromtheendofthekerneltotheendof+*RAMusable.+*init_bootmemsetstheglobalvaluesmin_low_pfn,max_low_pfn.+*/+bootmap_size=init_bootmem_node(NODE_DATA(0),free_ram_start_pfn,+ram_start_pfn,max_low_pfn);+free_bootmem(PFN_PHYS(free_ram_start_pfn),+(max_low_pfn-free_ram_start_pfn)<<PAGE_SHIFT);+reserve_bootmem(PFN_PHYS(free_ram_start_pfn),bootmap_size,+BOOTMEM_DEFAULT);++for_each_memblock(reserved,region){+if(region->size!=0){+pr_info("Reserved - 0x%08x-0x%08x\n",+(u32)region->base,(u32)region->size);+reserve_bootmem(region->base,region->size,+BOOTMEM_DEFAULT);+}+}+returnmax_low_pfn;+}++void__initsetup_arch(char**cmdline_p)+{+early_init_devtree(__atags_pointer?+phys_to_virt(__atags_pointer):__dtb_start);++setup_cpuinfo();++init_mm.start_code=(unsignedlong)&_stext;+init_mm.end_code=(unsignedlong)&_etext;+init_mm.end_data=(unsignedlong)&_edata;+init_mm.brk=(unsignedlong)&_end;++/* use generic way to parse */+parse_early_param();++/* setup bootmem allocator */+setup_memory();++/* paging_init() sets up the MMU and marks all pages as reserved */+paging_init();++unflatten_and_copy_device_tree();++#if defined(CONFIG_VT)+#if defined(CONFIG_VGA_CONSOLE)+conswitchp=&vga_con;+#elif defined(CONFIG_DUMMY_CONSOLE)+conswitchp=&dummy_con;+#endif+#endif++*cmdline_p=boot_command_line;+early_trap_init();+}++staticint__initnds32_device_probe(void)+{+returnof_platform_populate(NULL,NULL,NULL,NULL);+}++device_initcall(nds32_device_probe);++staticintc_show(structseq_file*m,void*v)+{+inti;++seq_printf(m,"Processor\t: %c%ld (id %lu, rev %lu, cfg %lu)\n",+cpu_series,cpu_id,cpu_id,cpu_rev,cpu_cfgid);++seq_printf(m,"L1I\t\t: %luKB/%luS/%luW/%luB\n",+CACHE_SET(ICACHE)*CACHE_WAY(ICACHE)*+CACHE_LINE_SIZE(ICACHE)/1024,CACHE_SET(ICACHE),+CACHE_WAY(ICACHE),CACHE_LINE_SIZE(ICACHE));++seq_printf(m,"L1D\t\t: %luKB/%luS/%luW/%luB\n",+CACHE_SET(DCACHE)*CACHE_WAY(DCACHE)*+CACHE_LINE_SIZE(DCACHE)/1024,CACHE_SET(DCACHE),+CACHE_WAY(DCACHE),CACHE_LINE_SIZE(DCACHE));++seq_printf(m,"BogoMIPS\t: %lu.%02lu\n",+loops_per_jiffy/(500000/HZ),+(loops_per_jiffy/(5000/HZ))%100);++/* dump out the processor features */+seq_puts(m,"Features\t: ");++for(i=0;hwcap_str[i];i++)+if(elf_hwcap&(1<<i))+seq_printf(m,"%s ",hwcap_str[i]);++seq_puts(m,"\n\n");++return0;+}++staticvoid*c_start(structseq_file*m,loff_t*pos)+{+return*pos<1?(void*)1:NULL;+}++staticvoid*c_next(structseq_file*m,void*v,loff_t*pos)+{+++*pos;+returnNULL;+}++staticvoidc_stop(structseq_file*m,void*v)+{+}++structseq_operationscpuinfo_op={+.start=c_start,+.next=c_next,+.stop=c_stop,+.show=c_show+};
+static int mode = 0x3;
+module_param(mode, int, S_IWUSR | S_IRUGO);
It's an interesting question how to best handle alignment faults, both in
kernel and user mode. While it can help for debugging to have the handler,
I'd argue that you are better off in the long run not fixing up the faults
automatically but to modify the code that triggers them instead.
How about making the faults disabled by default?
+static int _do_unaligned_access(unsigned long entry, unsigned long addr,
+ unsigned long type, struct pt_regs *regs)
+{
+ unsigned long inst;
+ int ret = -EFAULT;
+
+ if (user_mode(regs)) {
+ /* user mode */
+ if (!va_present(current->mm, addr))
+ return ret;
+ } else {
+ /* kernel mode */
+ if (!va_kernel_present(addr))
+ return ret;
+ }
This looks racy, the address might be present when you get here, but not
later when you actually access it. I think what you need here is something
like ARM does with get32_unaligned_check() etc and their fixup tables.
This should really be a sysctl rather than an open-coded procfs file,
for consistency with other architectures.
Please have a look at that interface on other architectures and pick
whatever the majority do.
Arnd
On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu [off-list ref] wrote:
+/*
+ * The DMA mask corresponding to the maximum bus address allocatable
+ * using GFP_DMA. The default here places no restriction on DMA
+ * allocations. This must be the smallest DMA mask in the system,
+ * so a successful GFP_DMA allocation will always satisfy this.
+ */
+#ifndef ISA_DMA_THRESHOLD
+#define ISA_DMA_THRESHOLD (0xffffffffULL)
+#endif
I see this one only in powerpc, I think it can be removed.
+
+/*
+ * Optional device DMA address remapping. Do _not_ use directly!
+ * We should really eliminate virt_to_bus() here - it's deprecated.
+ */
+#define page_to_dma(dev, page) ((dma_addr_t)__virt_to_phys((unsigned long)page_address(page)))
+#define dma_to_virt(dev, addr) ((void *)__phys_to_virt(addr))
+#define virt_to_dma(dev, addr) ((dma_addr_t)__virt_to_phys((unsigned long)(addr)))
This looks like an older comment, I think we have eliminated them from the
mainline kernel in all drivers, so you should remove them here too.
+
+/*
+ * This should be the size of the virtually indexed cache/ways,
+ * whichever is greater since the cache aliases every size/ways
+ * bytes.
+ */
+#define SHMLBA (4 * PAGE_SIZE) /* attach addr a multiple of this */
+#define REALSHMLBA SHMLBA
I don't see REALSHMLBA anywhere in the kernel, do you need it?
For SHMLBA, I think it should be defined as an absolute number, using
the maximum
that you might need for any possible value of PAGE_SIZE. Otherwise user space
has a much harder time figuring out what it should use.
Arnd
I see you have copied this from ARM. Do you actually need the same complexity,
with the ability to build either optimal code for a particular CPU or
a multi-CPU
version?
Most other architectures seem to have settled for doing just one of the two
models. How many CPU implementations to you expect to support that
differ in all of those functions?
Arnd
On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu [off-list ref] wrote:
quoted
+/*
+ * The DMA mask corresponding to the maximum bus address allocatable
+ * using GFP_DMA. The default here places no restriction on DMA
+ * allocations. This must be the smallest DMA mask in the system,
+ * so a successful GFP_DMA allocation will always satisfy this.
+ */
+#ifndef ISA_DMA_THRESHOLD
+#define ISA_DMA_THRESHOLD (0xffffffffULL)
+#endif
I see this one only in powerpc, I think it can be removed.
Thanks. I will remove it in next version patch.
quoted
+
+/*
+ * Optional device DMA address remapping. Do _not_ use directly!
+ * We should really eliminate virt_to_bus() here - it's deprecated.
+ */
+#define page_to_dma(dev, page) ((dma_addr_t)__virt_to_phys((unsigned long)page_address(page)))
+#define dma_to_virt(dev, addr) ((void *)__phys_to_virt(addr))
+#define virt_to_dma(dev, addr) ((dma_addr_t)__virt_to_phys((unsigned long)(addr)))
This looks like an older comment, I think we have eliminated them from the
mainline kernel in all drivers, so you should remove them here too.
+
+/*
+ * This should be the size of the virtually indexed cache/ways,
+ * whichever is greater since the cache aliases every size/ways
+ * bytes.
+ */
+#define SHMLBA (4 * PAGE_SIZE) /* attach addr a multiple of this */
+#define REALSHMLBA SHMLBA
I don't see REALSHMLBA anywhere in the kernel, do you need it?
For SHMLBA, I think it should be defined as an absolute number, using
the maximum
that you might need for any possible value of PAGE_SIZE. Otherwise user space
has a much harder time figuring out what it should use.
Thanks. I will remove REALSHMLBA. I will consider to use 8KB or larger
page size in the next version patch.
This was removed from the other architectures in commit
952111d7db02 ("arch: Remove spin_unlock_wait() arch-specific definitions")
Please remove this as well.
Palmer, I see riscv has the same thing, please also add a patch to your
tree to remove it.
The coding style seems inconsistent here, the other inline asm uses real tabs
instead of \t, and 'asm volatile' is generally preferred over '__asm__
__volatile__'.
Arnd
I see you have copied this from ARM. Do you actually need the same complexity,
with the ability to build either optimal code for a particular CPU or
a multi-CPU
version?
Most other architectures seem to have settled for doing just one of the two
models. How many CPU implementations to you expect to support that
differ in all of those functions?
I think we can simplify the implementations because we may not have that
many implementations. I will refine it in the next version patch.
asm-generic/io.h now provides an ioremap_nocache() helper along with
ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
ioremap_nocache definition here. You might also be able to remove
__ioremap and __iounmap, and only provide ioremap/iounmap, plus
the identity macro 'define ioremap ioremap'
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+ unsigned long flags, unsigned long align)
The 'align' argument is unused here, and not used on other architectures
either.
+{
+ struct vm_struct *area;
+ unsigned long addr, offset, last_addr;
+ pgprot_t prot;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
Better use get_vm_area_caller here to have the ioremap areas show up
in a more useful form in /proc/vmallocinfo
Please also have a look at what you can do for memremap().
Since you have no cacheable version of ioremap_wb/wt, it will
return an uncached mapping all the time, which is not ideal.
Arnd
You do the same cache operations for _to_cpu and _to_device, which
usually works,
but is more expensive than you need. It's better to take the ownership into
account and only do what you need.
Arnd
This gets set from include/asm-generic/unistd.h if you include that file.
+#define __ARCH_WANT_SYS_CLONE
This seems ok, though it would be nice to have the reverse logic and have
architectures opt-out of the generic version when they need to provide their
own, rather than having most architectures set it.
Usually we handle those overrides by defining the macros in asm/unistd.h
before including the asm-generic version. Can you do that as well for
consistency?
I don't see a reason for sys_ipc, sys_sysfs or sys_old_mmap() here
in a new architecture. Can you drop those or explain why you need them?
--- /dev/null+++ b/arch/nds32/kernel/sys_nds32.c
+
+long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ if (pgoff & (~PAGE_MASK >> 12))
+ return -EINVAL;
+
+ return sys_mmap_pgoff(addr, len, prot, flags, fd,
+ pgoff >> (PAGE_SHIFT - 12));
+}
+
+asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
+ loff_t len)
+{
+ return sys_fadvise64_64(fd, offset, len, advice);
+}
You should always use SYSCALL_DEFINE*() macros to define entry points
for your own syscalls in C code for consistency. I also wonder if we should
just move those two into common code, a lot of architectures need the first
one in particular.
Arnd
+#ifndef __ASM_VDSO_DATAPAGE_H
+#define __ASM_VDSO_DATAPAGE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct vdso_data {
+ bool cycle_count_down; /* timer cyclye counter is decrease with time */
+ u32 cycle_count_offset; /* offset of timer cycle counter register */
+ u32 seq_count; /* sequence count - odd during updates */
+ u32 xtime_coarse_sec; /* coarse time */
+ u32 xtime_coarse_nsec;
+
+ u32 wtm_clock_sec; /* wall to monotonic offset */
+ u32 wtm_clock_nsec;
+ u32 xtime_clock_sec; /* CLOCK_REALTIME - seconds */
+ u32 cs_mult; /* clocksource multiplier */
+ u32 cs_shift; /* Cycle to nanosecond divisor (power of two) */
+
+ u64 cs_cycle_last; /* last cycle value */
+ u64 cs_mask; /* clocksource mask */
+
+ u64 xtime_clock_nsec; /* CLOCK_REALTIME sub-ns base */
+ u32 tz_minuteswest; /* timezone info for gettimeofday(2) */
+ u32 tz_dsttime;
+};
I need some insight from Deepa and Palmer here: to prepare for 64-bit
time_t in the
future, would it make sense to define the vdso to use 64-bit seconds numbers
consistently, and provide vdso symbols that return 64-bit times, having the
glibc convert that to normal timespec values, or should we leave it for now?
For the normal syscalls I think we are better off keeping things consistent
between architectures, but the vdso is architecture specific by definition, so
we may as well use 64-bit times there now (same for risc-v, which still
has time to modify this before the 4.15 release and glibc merge).
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ LINUX_2.6 {
+ global:
+ __kernel_rt_sigreturn;
+ __vdso_gettimeofday;
+ __vdso_clock_getres;
+ __vdso_clock_gettime;
+ local: *;
+ };
+}
I still struggle to understand how symbol versioning is supposed to work
in a vdso (as opposed to a library you compile against), but I think this should
use the version from the kernel that you plan to merge into, i.e. LINUX_4
or LINUX_4_16.
Arnd
but here you actually have a symbol with that name, it gets turned
into a runtime error. I think the first one needs to get renamed to
actually work as expected and force the link error in built-in code
(it works in modules ins __get_user_bad is not exported).
Could be implemented using earlycon (the 8250 drivers already supports
it) instead of duplicating functionality in arch/nds32? See e.g. the
nios2 port for how this could be done, specifically commit e118c3fec9c0
("nios2: remove custom early console implementation").
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu [off-list ref] wrote:
From: Greentime Hu <redacted>
Signed-off-by: Vincent Chen <redacted>
Signed-off-by: Greentime Hu <redacted>
+
+/* This is defined for head.S to use due to device tree is not yet built. */
+#define L2CC_PA_BASE 0x90F00000
This looks problematic, since it prevents you from using the same head.S for
multiple SoCs that have different L2 controllers or that have them at different
addresses.
What does head.S actually do to the L2CC? Could the boot protocol require
that to be done by the boot loader before entering the kernel instead?
Arnd
ae3xx looks like a wildcard name for multiple boards. Please always
have compatible
names without wildcards. You usually also want to list both the SoC
and the board
here.
Remove the earlyprintk option from the bootargs here, regular boards
should never rely
on earlyprintk. The "earlycon" support in the uart drivers works
almost as well (it starts
slightly later in the boot process), and it will pick up the uart from
the chosen/stdout-path
property.
+ if (!params || !early_init_dt_scan(params)) {
+ pr_crit("\n"
+ "Error: invalid device tree blob at (virtual address 0x%p)\n"
+ "The dtb must be 8-byte aligned and must not exceed 8 KB in size\n"
+ "\nPlease check your bootloader.", params);
What is the 8KB limit for the dtb for? This sounds really limiting
once you get to
more complex SoCs.
Arnd
Does the architecture define a high-resolution clock source? If yes,
then it's better
to use that to get exact timing than to rely on the loop calibration.
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
I don't understand why you would want to override any of those.
Changing them unfortunately means rebuilding all of your user
space, but I think it would be better to do that now than to suffer
from this later on.
Arnd
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu [off-list ref] wrote:
From: Greentime Hu <redacted>
Signed-off-by: Vincent Chen <redacted>
Signed-off-by: Greentime Hu <redacted>
---
arch/nds32/configs/ae3xx_defconfig | 110 +++++++++++++++++++++++++++++++++++
arch/nds32/configs/ag101p_defconfig | 109 ++++++++++++++++++++++++++++++++++
Are those two incompatible? I would recommend starting without board
specific defconfig
files, it just gets messy once you get more than a few machines you
want to support.
You usually don't want to select 'CONFIG_EMBEDDED' for regular
builds, it's should only be needed to disable options that are
usually considered essential.
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
You have a framebuffer console here, but no framebuffer driver?
+CONFIG_MMC=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_CLKSRC_ATCPIT100=y
+CONFIG_EXT2_FS=y
-----Original Message-----
From: arndbergmann@gmail.com [mailto:arndbergmann@gmail.com] On
Behalf Of Arnd Bergmann
Sent: Wednesday, November 08, 2017 4:54 PM
To: Greentime Hu
Cc: Greentime Ying-Han Hu(胡英漢); Linux Kernel Mailing List; linux-arch;
Thomas Gleixner; Jason Cooper; Marc Zyngier; Rob Herring; Networking;
Vincent Ren-Wei Chen(陳人維); Palmer Dabbelt
Subject: Re: [PATCH 11/31] nds32: Atomic operations
On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu [off-list ref]
wrote:
This was removed from the other architectures in commit
952111d7db02 ("arch: Remove spin_unlock_wait() arch-specific definitions")
Please remove this as well.
Dear Arnd:
I will remove them in the next version patch.
Palmer, I see riscv has the same thing, please also add a patch to your tree to
remove it.
The coding style seems inconsistent here, the other inline asm uses real tabs
instead of \t, and 'asm volatile' is generally preferred over '__asm__
__volatile__'.
Arnd
OK, I will modify it in the next version patch.
Thanks
Best regards
Vincent
CONFIDENTIALITY NOTICE:
This e-mail (and its attachments) may contain confidential and legally privileged information or information protected from disclosure. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein is strictly prohibited. In this case, please immediately notify the sender by return e-mail, delete the message (and any accompanying documents) and destroy all printed hard copies. Thank you for your cooperation.
Copyright ANDES TECHNOLOGY CORPORATION - All Rights Reserved.
@@ -0,0 +1,107 @@+#+# For a description of the syntax of this configuration file,+# see Documentation/kbuild/kconfig-language.txt.+#++configNDS32+def_booly+selectARCH_HAS_RAW_COPY_USER+selectARCH_WANT_FRAME_POINTERSifFTRACE+selectARCH_WANT_IPC_PARSE_VERSION+selectCLKSRC_MMIO+selectCLONE_BACKWARDS+selectTIMER_OF+selectFRAME_POINTER+selectGENERIC_ATOMIC64+selectGENERIC_CPU_DEVICES+selectGENERIC_CLOCKEVENTS+selectGENERIC_IOMAP+selectGENERIC_IRQ_CHIP+selectGENERIC_IRQ_PROBE+selectGENERIC_IRQ_SHOW+selectGENERIC_STRNCPY_FROM_USER+selectGENERIC_STRNLEN_USER+selectGENERIC_TIME_VSYSCALL+selectHAVE_ARCH_TRACEHOOK+selectHAVE_GENERIC_IOMAP
You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
has special instructions to trigger PCI I/O port access.
I don't see what SYS_SUPPORTS_APM_EMULATION gains you.
+config GENERIC_CALIBRATE_DELAY
+ def_bool y
It's better to avoid the delay loop completely and skip the calibration,
if your hardware allows.
+
+config NDS32_BUILTIN_DTB
+ string "Builtin DTB"
+ default ""
+ help
+ User can use it to specify the dts of the SoC
Better leave this up to the boot loader.
+config ALIGNMENT_TRAP
+ tristate "Kernel support unaligned access handling"
+ default y
+ help
+ Andes processors cannot fetch/store information which is not
+ naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+ address divisible by 4. On 32-bit Andes processors, these non-aligned
+ fetch/store instructions will be emulated in software if you say
+ here, which has a severe performance impact. This is necessary for
+ correct operation of some network protocols. With an IP-only
+ configuration it is safe to say N, otherwise say Y.
Which network protocols are you referring to?
+config HIGHMEM
+ bool "High Memory Support"
+ depends on MMU && CPU_CACHE_NONALIASING
+ help
+ The address space of Andes processors is only 4 Gigabytes large
+ and it has to accommodate user address space, kernel address
+ space as well as some memory mapped IO. That means that, if you
+ have a large amount of physical memory and/or IO, not all of the
+ memory can be "permanently mapped" by the kernel. The physical
+ memory that is not permanently mapped is called "high memory".
+
+ Depending on the selected kernel/user memory split, minimum
+ vmalloc space and actual amount of RAM, you may not need this
+ option which should result in a slightly faster kernel.
+
+ If unsure, say N.
Generally speaking, highmem support is a mess, and it's better to avoid it.
I see that the two device tree files you have list 1GB of memory. Do you think
that is a common configuration for actual products? Do you expect any to
have more than 1GB (or more than 4GB) in the future, or is that the upper
end of the scale?
If 1GB is a reasonable upper bound, then you could change the vmsplit
to give slightly less address space to user space and have 1GB of direct-mapped
kernel memory plus 256MB of vmalloc space reserved for the kernel,
and completely avoid highmem.
+config MEMORY_START
+ hex "Physical memory start address"
+ default "0x00000000"
+ help
+ Physical memory start address, you may modify it if it is porting to
+ a new SoC with different start address.
+endmenu
On ARM, we found options like this to be rather problematic since it prevents
you from running the same kernel on boards that are otherwise compatible.
If the architecture easily allows the memory to start at address 0, could
you require this address for all SoCs that want to run Linux, and get
rid of the compile-time option?
Arnd
Yes, it is but only supporting elf-toolchain now. We will do the
upstream for Linux-toolchain in the next step.
Is the Linux toolchain only required for building user space, or do
you also need it
for building kernels? It's often possible to build kernels with a bare
toolchain, and
that helps a lot for automated testing.
Arnd
On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu [off-list ref] wrote:
This patchset adds core architecture support to Linux for Andestech's
N13, N15, D15, N10, D10 processor cores.
Based on the 16/32-bit AndeStar RISC-like architecture, we designed the
configurable AndesCore series of embedded processor families. AndesCores
range from highly performance-efficient small-footprint cores for
microcontrollers and deeply-embedded applications to 1GHz+ cores running
Linux, covering general-purpose N-series cores for a wide range of computing
need, DSP-capable D-series cores for digital signal control,
instruction-extensible E-series cores for application-specific acceleration,
and secure S-series cores for best protection of the most valuable.
I looked at the entire patch series now and commented on anything I noticed
that could be improved, overall this looks very nice, great work!
Most of my comments are about tiny details that are easy to address.
I see two areas that need to be looked at carefully, and that may take a
few more rounds to get right:
- In the user space ABI, you have a couple of things that differ from the
normal asm-generic definitions, i.e. s few syscall entry points and some
types in asm/posix-types.h. I guess you did that to remain compatible
with an older glibc port, but IMHO this compatibility should be broken
in favor of having the standard ABI before the port gets merged.
- For the boot interface, you need to clearly define what can be expected
and what cannot. This involves the presence of the l2cc, the physical
memory address, the built-in dtb, and probably a few more things I
missed. For long-term maintainability, you probably want to ensure that
you can build a kernel that runs on as much diverse hardware as possible.
Arnd
@@ -0,0 +1,33 @@+* Andestech Processor Binding++This binding specifies what properties must be available in the device tree+representation of a Andestech Processor Core, which is the root node in the+tree.++Required properties:++ - compatible:+ Usage: required+ Value type: <string>+ Definition: should be one of:+ "andestech,n13"+ "andestech,n15"+ "andestech,d15"+ "andestech,n10"+ "andestech,d10"
SMP supported for any of these?
+
+ - device_type
+ Usage: required
+ Value type: <string>
+ Definition: must be "cpu"
+
+* Examples
+
+/ {
+ cpus {
+ cpu@0 {
@@ -0,0 +1,27 @@+* Andestech Internal Vector Interrupt Controller++The Internal Vector Interrupt Controller (IVIC) is a basic interrupt controller+suitable for a simpler SoC platform not requiring a more sophisticated and+bigger External Vector Interrupt Controller.+++Main node required properties:++- compatible : should at least contain "andestech,ativic32".+- interrupt-parent: Empty for the interrupt controller itself
Drop this.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells: The number of cells to define the interrupts. Should be 2.
+ The first cell is the IRQ number
+ The second cell is used to specify mode:
+ 1 = low-to-high edge triggered
+ 2 = high-to-low edge triggered
+ 4 = active high level-sensitive
+ 8 = active low level-sensitive
Just state 2 cells and refer to interrupt-controller/interrupts.txt.
+ Default for internal sources should be set to 4 (active high).
+
+Examples:
+ intc: interrupt-controller {
+ compatible = "andestech,ativic32";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ };
--
1.7.9.5
@@ -0,0 +1,149 @@+/*+*Copyright(C)2005-2017AndesTechnologyCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/irq.h>+#include<linux/of.h>+#include<linux/of_irq.h>+#include<linux/of_address.h>+#include<linux/interrupt.h>+#include<linux/irqdomain.h>+#include<linux/irqchip.h>+#include<nds32_intrinsic.h>++staticvoidativic32_ack_irq(structirq_data*data)+{+__nds32__mtsr_dsb(1<<data->hwirq,NDS32_SR_INT_PEND2);+}++staticvoidativic32_mask_irq(structirq_data*data)+{+unsignedlongint_mask2=__nds32__mfsr(NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb(int_mask2&(~(1<<data->hwirq)),NDS32_SR_INT_MASK2);+}++staticvoidativic32_mask_ack_irq(structirq_data*data)+{+unsignedlongint_mask2=__nds32__mfsr(NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb(int_mask2&(~(1<<data->hwirq)),NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb((1<<data->hwirq),NDS32_SR_INT_PEND2);++}++staticvoidativic32_unmask_irq(structirq_data*data)+{+unsignedlongint_mask2=__nds32__mfsr(NDS32_SR_INT_MASK2);+__nds32__mtsr_dsb(int_mask2|(1<<data->hwirq),NDS32_SR_INT_MASK2);+}++staticintativic32_set_type(structirq_data*data,unsignedintflow_type)+{+printk(KERN_WARNING"interrupt type is not configurable\n");
If it is not configurable, what is the point of having each interrupt
carry a trigger type in DT?
Why can't you use handle_domain_irq() directly instead of what looks
like a copy of it (this is where the comment comes from...)?
+
+}
+
+int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
+{
+ unsigned long int_vec_base, nivic, i;
+
+ if (WARN(parent, "non-root ativic32 are not supported"))
+ return -EINVAL;
+
+ int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
+
+ if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) {
+ panic("Unable to use NOINTC option to boot on this cpu\n");
+ }
+
+ nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
+ if (nivic >= (sizeof nivic_map / sizeof nivic_map[0])) {
+ panic
+ ("The number of input for IVIC Controller is not supported on this cpu\n");
Irk. Please leave this on a single line... Or better yet, get rid of it
(see below).
+ }
+ nivic = nivic_map[nivic];
If you have multiple configurations, I'd rather they live in DT,
specially if the IP is easily configurable.
+#ifndef __ASM_VDSO_DATAPAGE_H
+#define __ASM_VDSO_DATAPAGE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct vdso_data {
+ bool cycle_count_down; /* timer cyclye counter is decrease with time */
+ u32 cycle_count_offset; /* offset of timer cycle counter register */
+ u32 seq_count; /* sequence count - odd during updates */
+ u32 xtime_coarse_sec; /* coarse time */
+ u32 xtime_coarse_nsec;
+
+ u32 wtm_clock_sec; /* wall to monotonic offset */
+ u32 wtm_clock_nsec;
+ u32 xtime_clock_sec; /* CLOCK_REALTIME - seconds */
+ u32 cs_mult; /* clocksource multiplier */
+ u32 cs_shift; /* Cycle to nanosecond divisor (power of two) */
+
+ u64 cs_cycle_last; /* last cycle value */
+ u64 cs_mask; /* clocksource mask */
+
+ u64 xtime_clock_nsec; /* CLOCK_REALTIME sub-ns base */
+ u32 tz_minuteswest; /* timezone info for gettimeofday(2) */
+ u32 tz_dsttime;
+};
I need some insight from Deepa and Palmer here: to prepare for 64-bit
time_t in the
future, would it make sense to define the vdso to use 64-bit seconds numbers
consistently, and provide vdso symbols that return 64-bit times, having the
glibc convert that to normal timespec values, or should we leave it for now?
Other architectures also have a similar way of defining these as u32
(eg: x86) I think for performance reasons on 32 bit systems.
u32 still works until 2106 as the timekeeping structures are s64. I
was planning to leave it that way for x86.
If this architecture can live with u64, then it will be better to use it here.
For the normal syscalls I think we are better off keeping things consistent
between architectures, but the vdso is architecture specific by definition, so
we may as well use 64-bit times there now (same for risc-v, which still
has time to modify this before the 4.15 release and glibc merge).
But, I don't think this vdso can return 64 bit times without syscalls
for the architecture also supporting that. The problem is that all
fallback paths depend on syscalls directly.
Also I couldn't find any arch specific handling of vdso interfaces in
glibc. I think they expect the vdso wrappers in the kernel to handle
this part.
-Deepa
On Wed, Nov 8, 2017 at 9:00 PM, Deepa Dinamani [off-list ref] wrote:
On Wed, Nov 8, 2017 at 1:37 AM, Arnd Bergmann [off-list ref] wrote:
quoted
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu [off-list ref] wrote:
quoted
I need some insight from Deepa and Palmer here: to prepare for 64-bit
time_t in the
future, would it make sense to define the vdso to use 64-bit seconds numbers
consistently, and provide vdso symbols that return 64-bit times, having the
glibc convert that to normal timespec values, or should we leave it for now?
Other architectures also have a similar way of defining these as u32
(eg: x86) I think for performance reasons on 32 bit systems.
u32 still works until 2106 as the timekeeping structures are s64. I
was planning to leave it that way for x86.
Right, good point.
If this architecture can live with u64, then it will be better to use it here.
As long as we don't need a division, using u64 is probably cheap enough,
we already need the retry loop.
quoted
For the normal syscalls I think we are better off keeping things consistent
between architectures, but the vdso is architecture specific by definition, so
we may as well use 64-bit times there now (same for risc-v, which still
has time to modify this before the 4.15 release and glibc merge).
But, I don't think this vdso can return 64 bit times without syscalls
for the architecture also supporting that. The problem is that all
fallback paths depend on syscalls directly.
Also I couldn't find any arch specific handling of vdso interfaces in
glibc. I think they expect the vdso wrappers in the kernel to handle
this part.
Do applications call into the vdso directly and expect to get a timespec
out? If they always go through the C library as an intermediate, then
the glibc clock_gettime() could do the conversion.
Arnd
Do applications call into the vdso directly and expect to get a timespec
out? If they always go through the C library as an intermediate, then
the glibc clock_gettime() could do the conversion.
It is recommended that applications do not call vdso symbols directly.
According to manpage:
"If you're trying to call the vDSO in your own application rather than
using the C library, you're most likely doing it wrong."
-Deepa
Are those actually worth bothering? IOW, have you compared behaviour
with and without them?
+ENTRY(__arch_copy_to_user)
+ push $r0
+ push $r2
+ beqz $r2, ctu_exit
+ srli $p0, $r2, #2 ! $p0 = number of word to clear
+ andi $r2, $r2, #3 ! Bytes less than a word to copy
+ beqz $p0, byte_ctu ! Only less than a word to copy
+word_ctu:
+ lmw.bim $p1, [$r1], $p1 ! Load the next word
+USER( smw.bim,$p1, [$r0], $p1) ! Store the next word
Umm... It's that happy with unaligned loads and stores? Your memcpy seems
to be trying to avoid those...
+9001:
+ pop $p1 ! Original $r2, n
+ pop $p0 ! Original $r0, void *to
+ sub $r1, $r0, $p0 ! Bytes copied
+ sub $r2, $p1, $r1 ! Bytes left to copy
+ push $lp
+ move $r0, $p0
+ bal memzero ! Clean up the memory
Just what memory are you zeroing here? The one you had been
unable to store into in the first place?
+ENTRY(__arch_copy_from_user)
+9001:
+ pop $p1 ! Original $r2, n
+ pop $p0 ! Original $r0, void *to
+ sub $r1, $r1, $p0 ! Bytes copied
+ sub $r2, $p1, $r1 ! Bytes left to copy
+ push $lp
+ bal memzero ! Clean up the memory
Ditto, only this one is even worse - instead of just oopsing on
you, it will quietly destroy data past the area you've copied
into. raw_copy_..._user() MUST NOT ZERO ANYTHING. Ever.
IDGI... Where do you modify ->ipsw at all and how can valid_user_regs() come
to be false here?
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ /*
+ * Since we stacked the signal on a 64-bit boundary,
+ * then 'sp' should be two-word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ if (regs->sp & 7)
+ goto badframe;
+
+ frame = (struct rt_sigframe __user *)regs->sp;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (restore_sigframe(regs, frame))
+ goto badframe;
+
+ if (restore_altstack(&frame->uc.uc_stack))
+ goto badframe;
+
+ return regs->uregs[0];
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
AFAICS, you are copying arm; take a good look at sys_rt_sigreturn_wrapper
there - specifically, the 'mov why, #0' part. Consider what happens if
you get an interrupt at the moment when $r0 contains -ERESTARTSYS (for
example) and signal arrives while we are processing the interrupt. It
will be handled on the way out, without any syscall restart crap ('why'
is 0 on that codepath). So far, so good, but think what'll happen when
you are done with the signal handler. sigreturn() is called, the values
we had stashed in sigcontext go back into registers (OK, pt_regs on
kernel stack that will be used to reload the registers on return to
userland)... and the signals that had been blocked for the duration of
handlers (see sa_mask in sigaction(2)) get unblocked. And it turns
out that you have one of those pending - it had arrived while we'd been
in the handler.
Now we are fucked. You have TIF_SIGPENDING set, so do_notify_resume()
is called. And everything looks exactly as if you had a syscall restart
situation - regs->uregs[0] being one of -ERESTART... and 'syscall' flag
being true. So we go into the second signal handler (as we ought to)
with saved ->ipc set 4 bytes back from where we were going to return.
It would've been the right thing to do if it *was* a syscall restart,
but we were returning to the location where the original interrupt
had caught us.
Result: with the right timing, an interrupt arriving when userland process
has $r0 equal -512 may lead to instruction pointer jumping 4 bytes back.
Pity the poor sod trying to debug that kind of breakage...
Restart should *NOT* be triggered upon sigreturn(2).
+static int
+setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame)
+{
+ unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
+ unsigned long retcode;
+
+ /*
+ * Maybe we need to deliver a 32-bit signal to a 26-bit task.
Deliver to what, again? That comment made sense (if rather sad one) on arm, but
what is it doing here?
+static int do_signal(struct pt_regs *regs, int syscall)
+{
+ unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
+ struct ksignal ksig;
+ int restart = 0;
+
+ /*
+ * 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;
asm-generic/io.h now provides an ioremap_nocache() helper along with
ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
ioremap_nocache definition here. You might also be able to remove
__ioremap and __iounmap, and only provide ioremap/iounmap, plus
the identity macro 'define ioremap ioremap'
Thanks. I will try to use generic ioremap_nocache() helper in the next
version patch.
quoted
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+ unsigned long flags, unsigned long align)
The 'align' argument is unused here, and not used on other architectures
either.
Thanks. I will remove this argument in the next version patch.
quoted
+{
+ struct vm_struct *area;
+ unsigned long addr, offset, last_addr;
+ pgprot_t prot;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
Better use get_vm_area_caller here to have the ioremap areas show up
in a more useful form in /proc/vmallocinfo
Thanks.
I will use get_vm_area_caller() in the next version patch.
Please also have a look at what you can do for memremap().
Since you have no cacheable version of ioremap_wb/wt, it will
return an uncached mapping all the time, which is not ideal.
You do the same cache operations for _to_cpu and _to_device, which
usually works,
but is more expensive than you need. It's better to take the ownership into
account and only do what you need.
Could be implemented using earlycon (the 8250 drivers already supports
it) instead of duplicating functionality in arch/nds32? See e.g. the
nios2 port for how this could be done, specifically commit e118c3fec9c0
("nios2: remove custom early console implementation").
Thanks.
I will try to use earlycon in the next version patch.
I will remove this patch if earlycon is able to be used in nds32.
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu [off-list ref] wrote:
quoted
From: Greentime Hu <redacted>
Signed-off-by: Vincent Chen <redacted>
Signed-off-by: Greentime Hu <redacted>
quoted
+
+/* This is defined for head.S to use due to device tree is not yet built. */
+#define L2CC_PA_BASE 0x90F00000
This looks problematic, since it prevents you from using the same head.S for
multiple SoCs that have different L2 controllers or that have them at different
addresses.
What does head.S actually do to the L2CC? Could the boot protocol require
that to be done by the boot loader before entering the kernel instead?
Thanks.
It will disable and invalidate L2 cache. I think we can do these
things in bootloader.
I will refine it in the next version patch.
For new architectures, I think it's better to not support built-in dtb
but instead require the
boot loader to be aware of device trees.
Thanks.
I got your point and we have uboot supporting DTB too.
But we use gdb to load vmlinux without uboot sometimes, it can help us
to verify kernel more easily.
If dtb pointer is set by uboot, we will use it instead of using built-in dtb.
ae3xx looks like a wildcard name for multiple boards. Please always
have compatible
names without wildcards. You usually also want to list both the SoC
and the board
here.
Thanks.
It looks a little bit weird but its not a wildcards. :p
I will list all the names instead of wildcards if I need to add more platforms.
Remove the earlyprintk option from the bootargs here, regular boards
should never rely
on earlyprintk. The "earlycon" support in the uart drivers works
almost as well (it starts
slightly later in the boot process), and it will pick up the uart from
the chosen/stdout-path
property.
Thanks.
I will remove it.
quoted
+ if (!params || !early_init_dt_scan(params)) {
+ pr_crit("\n"
+ "Error: invalid device tree blob at (virtual address 0x%p)\n"
+ "The dtb must be 8-byte aligned and must not exceed 8 KB in size\n"
+ "\nPlease check your bootloader.", params);
What is the 8KB limit for the dtb for? This sounds really limiting
once you get to
more complex SoCs.
Thanks.
We allow uboot to set its start address and we think it might not be
too big thus we limit it to 8KB.
Maybe I should use a big size for complex SoCs.
I will update it in the next version patch.
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu [off-list ref] wrote:
quoted
From: Greentime Hu <redacted>
Signed-off-by: Vincent Chen <redacted>
Signed-off-by: Greentime Hu <redacted>
---
arch/nds32/configs/ae3xx_defconfig | 110 +++++++++++++++++++++++++++++++++++
arch/nds32/configs/ag101p_defconfig | 109 ++++++++++++++++++++++++++++++++++
Are those two incompatible? I would recommend starting without board
specific defconfig
files, it just gets messy once you get more than a few machines you
want to support.
Thanks.
These 2 are incompatible.
They use different drivers. I may still keep these 2 defconfigs.
You usually don't want to select 'CONFIG_EMBEDDED' for regular
builds, it's should only be needed to disable options that are
usually considered essential.
Thanks.
I will remove this config in the next version patch.
quoted
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
You have a framebuffer console here, but no framebuffer driver?
Thanks.
I shall enable it when I push our framebuffer in the next time.
I will disable it in the next version patch.
quoted
+CONFIG_MMC=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_CLKSRC_ATCPIT100=y
+CONFIG_EXT2_FS=y
Maybe use EXT4, not EXT2, in the defconfig?
Thanks.
I will enable EXT4 instead of EXT2 in the defconfig.
@@ -0,0 +1,107 @@+#+# For a description of the syntax of this configuration file,+# see Documentation/kbuild/kconfig-language.txt.+#++configNDS32+def_booly+selectARCH_HAS_RAW_COPY_USER+selectARCH_WANT_FRAME_POINTERSifFTRACE+selectARCH_WANT_IPC_PARSE_VERSION+selectCLKSRC_MMIO+selectCLONE_BACKWARDS+selectTIMER_OF+selectFRAME_POINTER+selectGENERIC_ATOMIC64+selectGENERIC_CPU_DEVICES+selectGENERIC_CLOCKEVENTS+selectGENERIC_IOMAP+selectGENERIC_IRQ_CHIP+selectGENERIC_IRQ_PROBE+selectGENERIC_IRQ_SHOW+selectGENERIC_STRNCPY_FROM_USER+selectGENERIC_STRNLEN_USER+selectGENERIC_TIME_VSYSCALL+selectHAVE_ARCH_TRACEHOOK+selectHAVE_GENERIC_IOMAP
You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
has special instructions to trigger PCI I/O port access.
Thanks.
I will remove it in the next version patch.
quoted
+ select HAVE_DEBUG_KMEMLEAK
+ select HAVE_IDE
You certainly don't want HAVE_IDE
Thanks.
I will remove it in the next version patch.
I don't see what SYS_SUPPORTS_APM_EMULATION gains you.
Thanks.
I will remove it in the next version patch.
quoted
+config GENERIC_CALIBRATE_DELAY
+ def_bool y
It's better to avoid the delay loop completely and skip the calibration,
if your hardware allows.
Thanks.
Do you mean that this config should be def_bool n?
why? Almost all arch enable it.
quoted
+
+config NDS32_BUILTIN_DTB
+ string "Builtin DTB"
+ default ""
+ help
+ User can use it to specify the dts of the SoC
Better leave this up to the boot loader.
Thanks.
uboot will pass it too.
quoted
+config ALIGNMENT_TRAP
+ tristate "Kernel support unaligned access handling"
+ default y
+ help
+ Andes processors cannot fetch/store information which is not
+ naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+ address divisible by 4. On 32-bit Andes processors, these non-aligned
+ fetch/store instructions will be emulated in software if you say
+ here, which has a severe performance impact. This is necessary for
+ correct operation of some network protocols. With an IP-only
+ configuration it is safe to say N, otherwise say Y.
Which network protocols are you referring to?
I will modify these descriptions. It was written by someone I don't know. :p
This case only happened when I found is compiler code gen issue or
wrong pointer usage.
quoted
+config HIGHMEM
+ bool "High Memory Support"
+ depends on MMU && CPU_CACHE_NONALIASING
+ help
+ The address space of Andes processors is only 4 Gigabytes large
+ and it has to accommodate user address space, kernel address
+ space as well as some memory mapped IO. That means that, if you
+ have a large amount of physical memory and/or IO, not all of the
+ memory can be "permanently mapped" by the kernel. The physical
+ memory that is not permanently mapped is called "high memory".
+
+ Depending on the selected kernel/user memory split, minimum
+ vmalloc space and actual amount of RAM, you may not need this
+ option which should result in a slightly faster kernel.
+
+ If unsure, say N.
Generally speaking, highmem support is a mess, and it's better to avoid it.
I see that the two device tree files you have list 1GB of memory. Do you think
that is a common configuration for actual products? Do you expect any to
have more than 1GB (or more than 4GB) in the future, or is that the upper
end of the scale?
If 1GB is a reasonable upper bound, then you could change the vmsplit
to give slightly less address space to user space and have 1GB of direct-mapped
kernel memory plus 256MB of vmalloc space reserved for the kernel,
and completely avoid highmem.
Thanks.
We do realy use 1GB ram in some products.
We also verify CONFIG_HIGHMEM with LTP too.
It seems fine but I will study vmsplit to see if we should use it.
quoted
+config MEMORY_START
+ hex "Physical memory start address"
+ default "0x00000000"
+ help
+ Physical memory start address, you may modify it if it is porting to
+ a new SoC with different start address.
+endmenu
On ARM, we found options like this to be rather problematic since it prevents
you from running the same kernel on boards that are otherwise compatible.
If the architecture easily allows the memory to start at address 0, could
you require this address for all SoCs that want to run Linux, and get
rid of the compile-time option?
Thanks.
The reason we need this config is because we need to define PHYS_OFFSET.
#define PHYS_OFFSET (CONFIG_MEMORY_START)
It needs to be set in compile-time. I don't know how to get rid of it.
Yes, it is but only supporting elf-toolchain now. We will do the
upstream for Linux-toolchain in the next step.
Is the Linux toolchain only required for building user space, or do
you also need it
for building kernels? It's often possible to build kernels with a bare
toolchain, and
that helps a lot for automated testing.
Yes, nds32 kernel is able to be built with elf-toolchain too.
On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu [off-list ref] wrote:
quoted
This patchset adds core architecture support to Linux for Andestech's
N13, N15, D15, N10, D10 processor cores.
Based on the 16/32-bit AndeStar RISC-like architecture, we designed the
configurable AndesCore series of embedded processor families. AndesCores
range from highly performance-efficient small-footprint cores for
microcontrollers and deeply-embedded applications to 1GHz+ cores running
Linux, covering general-purpose N-series cores for a wide range of computing
need, DSP-capable D-series cores for digital signal control,
instruction-extensible E-series cores for application-specific acceleration,
and secure S-series cores for best protection of the most valuable.
I looked at the entire patch series now and commented on anything I noticed
that could be improved, overall this looks very nice, great work!
Most of my comments are about tiny details that are easy to address.
I see two areas that need to be looked at carefully, and that may take a
few more rounds to get right:
- In the user space ABI, you have a couple of things that differ from the
normal asm-generic definitions, i.e. s few syscall entry points and some
types in asm/posix-types.h. I guess you did that to remain compatible
with an older glibc port, but IMHO this compatibility should be broken
in favor of having the standard ABI before the port gets merged.
- For the boot interface, you need to clearly define what can be expected
and what cannot. This involves the presence of the l2cc, the physical
memory address, the built-in dtb, and probably a few more things I
missed. For long-term maintainability, you probably want to ensure that
you can build a kernel that runs on as much diverse hardware as possible.
Many thanks to all your feedbacks. We will prepare the V2 patch to fix
them ASAP. :)