⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtc.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (C) 2004 Mips Technologies, Inc */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/cpumask.h>#include <linux/interrupt.h>#include <asm/cpu.h>#include <asm/processor.h>#include <asm/atomic.h>#include <asm/system.h>#include <asm/hardirq.h>#include <asm/hazards.h>#include <asm/mmu_context.h>#include <asm/smp.h>#include <asm/mipsregs.h>#include <asm/cacheflush.h>#include <asm/time.h>#include <asm/addrspace.h>#include <asm/smtc.h>#include <asm/smtc_ipi.h>#include <asm/smtc_proc.h>/* * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. *//* * MIPSCPU_INT_BASE is identically defined in both * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h, * but as yet there's no properly organized include structure that * will ensure that the right *int.h file will be included for a * given platform build. */#define MIPSCPU_INT_BASE	16#define MIPS_CPU_IPI_IRQ	1#define LOCK_MT_PRA() \	local_irq_save(flags); \	mtflags = dmt()#define UNLOCK_MT_PRA() \	emt(mtflags); \	local_irq_restore(flags)#define LOCK_CORE_PRA() \	local_irq_save(flags); \	mtflags = dvpe()#define UNLOCK_CORE_PRA() \	evpe(mtflags); \	local_irq_restore(flags)/* * Data structures purely associated with SMTC parallelism *//* * Table for tracking ASIDs whose lifetime is prolonged. */asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];/* * Clock interrupt "latch" buffers, per "CPU" */unsigned int ipi_timer_latch[NR_CPUS];/* * Number of InterProcessor Interupt (IPI) message buffers to allocate */#define IPIBUF_PER_CPU 4struct smtc_ipi_q IPIQ[NR_CPUS];struct smtc_ipi_q freeIPIq;/* Forward declarations */void ipi_decode(struct pt_regs *, struct smtc_ipi *);void post_direct_ipi(int cpu, struct smtc_ipi *pipi);void setup_cross_vpe_interrupts(void);void init_smtc_stats(void);/* Global SMTC Status */unsigned int smtc_status = 0;/* Boot command line configuration overrides */static int vpelimit = 0;static int tclimit = 0;static int ipibuffers = 0;static int nostlb = 0;static int asidmask = 0;unsigned long smtc_asid_mask = 0xff;static int __init maxvpes(char *str){	get_option(&str, &vpelimit);	return 1;}static int __init maxtcs(char *str){	get_option(&str, &tclimit);	return 1;}static int __init ipibufs(char *str){	get_option(&str, &ipibuffers);	return 1;}static int __init stlb_disable(char *s){	nostlb = 1;	return 1;}static int __init asidmask_set(char *str){	get_option(&str, &asidmask);	switch(asidmask) {	case 0x1:	case 0x3:	case 0x7:	case 0xf:	case 0x1f:	case 0x3f:	case 0x7f:	case 0xff:		smtc_asid_mask = (unsigned long)asidmask;		break;	default:		printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask);	}	return 1;}__setup("maxvpes=", maxvpes);__setup("maxtcs=", maxtcs);__setup("ipibufs=", ipibufs);__setup("nostlb", stlb_disable);__setup("asidmask=", asidmask_set);/* Enable additional debug checks before going into CPU idle loop */#define SMTC_IDLE_HOOK_DEBUG#ifdef SMTC_IDLE_HOOK_DEBUGstatic int hang_trig = 0;static int __init hangtrig_enable(char *s){	hang_trig = 1;	return 1;}__setup("hangtrig", hangtrig_enable);#define DEFAULT_BLOCKED_IPI_LIMIT 32static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT;static int __init tintq(char *str){	get_option(&str, &timerq_limit);	return 1;}__setup("tintq=", tintq);int imstuckcount[2][8];/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}};int tcnoprog[NR_CPUS];static atomic_t idle_hook_initialized = {0};static int clock_hang_reported[NR_CPUS];#endif /* SMTC_IDLE_HOOK_DEBUG *//* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */void __init sanitize_tlb_entries(void){	printk("Deprecated sanitize_tlb_entries() invoked\n");}/* * Configure shared TLB - VPC configuration bit must be set by caller */void smtc_configure_tlb(void){	int i,tlbsiz,vpes;	unsigned long mvpconf0;	unsigned long config1val;	/* Set up ASID preservation table */	for (vpes=0; vpes<MAX_SMTC_TLBS; vpes++) {	    for(i = 0; i < MAX_SMTC_ASIDS; i++) {		smtc_live_asid[vpes][i] = 0;	    }	}	mvpconf0 = read_c0_mvpconf0();	if ((vpes = ((mvpconf0 & MVPCONF0_PVPE)			>> MVPCONF0_PVPE_SHIFT) + 1) > 1) {	    /* If we have multiple VPEs, try to share the TLB */	    if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) {		/*		 * If TLB sizing is programmable, shared TLB		 * size is the total available complement.		 * Otherwise, we have to take the sum of all		 * static VPE TLB entries.		 */		if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE)				>> MVPCONF0_PTLBE_SHIFT)) == 0) {		    /*		     * If there's more than one VPE, there had better		     * be more than one TC, because we need one to bind		     * to each VPE in turn to be able to read		     * its configuration state!		     */		    settc(1);		    /* Stop the TC from doing anything foolish */		    write_tc_c0_tchalt(TCHALT_H);		    mips_ihb();		    /* No need to un-Halt - that happens later anyway */		    for (i=0; i < vpes; i++) {		    	write_tc_c0_tcbind(i);			/*			 * To be 100% sure we're really getting the right			 * information, we exit the configuration state			 * and do an IHB after each rebinding.			 */			write_c0_mvpcontrol(				read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );			mips_ihb();			/*			 * Only count if the MMU Type indicated is TLB			 */			if(((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {				config1val = read_vpe_c0_config1();				tlbsiz += ((config1val >> 25) & 0x3f) + 1;			}			/* Put core back in configuration state */			write_c0_mvpcontrol(				read_c0_mvpcontrol() | MVPCONTROL_VPC );			mips_ihb();		    }		}		write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);		/*		 * Setup kernel data structures to use software total,		 * rather than read the per-VPE Config1 value. The values		 * for "CPU 0" gets copied to all the other CPUs as part		 * of their initialization in smtc_cpu_setup().		 */		tlbsiz = tlbsiz & 0x3f;	/* MIPS32 limits TLB indices to 64 */		cpu_data[0].tlbsize = tlbsiz;		smtc_status |= SMTC_TLB_SHARED;		printk("TLB of %d entry pairs shared by %d VPEs\n",			tlbsiz, vpes);	    } else {		printk("WARNING: TLB Not Sharable on SMTC Boot!\n");	    }	}}/* * Incrementally build the CPU map out of constituent MIPS MT cores, * using the specified available VPEs and TCs.  Plaform code needs * to ensure that each MIPS MT core invokes this routine on reset, * one at a time(!). * * This version of the build_cpu_map and prepare_cpus routines assumes * that *all* TCs of a MIPS MT core will be used for Linux, and that * they will be spread across *all* available VPEs (to minimise the * loss of efficiency due to exception service serialization). * An improved version would pick up configuration information and * possibly leave some TCs/VPEs as "slave" processors. * * Use c0_MVPConf0 to find out how many TCs are available, setting up * phys_cpu_present_map and the logical/physical mappings. */int __init mipsmt_build_cpu_map(int start_cpu_slot){	int i, ntcs;	/*	 * The CPU map isn't actually used for anything at this point,	 * so it's not clear what else we should do apart from set	 * everything up so that "logical" = "physical".	 */	ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;	for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {		cpu_set(i, phys_cpu_present_map);		__cpu_number_map[i] = i;		__cpu_logical_map[i] = i;	}	/* Initialize map of CPUs with FPUs */	cpus_clear(mt_fpu_cpumask);	/* One of those TC's is the one booting, and not a secondary... */	printk("%i available secondary CPU TC(s)\n", i - 1);	return i;}/* * Common setup before any secondaries are started * Make sure all CPU's are in a sensible state before we boot any of the * secondaries. * * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly * as possible across the available VPEs. */static void smtc_tc_setup(int vpe, int tc, int cpu){	settc(tc);	write_tc_c0_tchalt(TCHALT_H);	mips_ihb();	write_tc_c0_tcstatus((read_tc_c0_tcstatus()			& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))			| TCSTATUS_A);	write_tc_c0_tccontext(0);	/* Bind tc to vpe */	write_tc_c0_tcbind(vpe);	/* In general, all TCs should have the same cpu_data indications */	memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));	/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */	if (cpu_data[0].cputype == CPU_34K)		cpu_data[cpu].options &= ~MIPS_CPU_FPU;	cpu_data[cpu].vpe_id = vpe;	cpu_data[cpu].tc_id = tc;}void mipsmt_prepare_cpus(void){	int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;	unsigned long flags;	unsigned long val;	int nipi;	struct smtc_ipi *pipi;	/* disable interrupts so we can disable MT */	local_irq_save(flags);	/* disable MT so we can configure */	dvpe();	dmt();	freeIPIq.lock = SPIN_LOCK_UNLOCKED;	/*	 * We probably don't have as many VPEs as we do SMP "CPUs",	 * but it's possible - and in any case we'll never use more!	 */	for (i=0; i<NR_CPUS; i++) {		IPIQ[i].head = IPIQ[i].tail = NULL;		IPIQ[i].lock = SPIN_LOCK_UNLOCKED;		IPIQ[i].depth = 0;		ipi_timer_latch[i] = 0;	}	/* cpu_data index starts at zero */	cpu = 0;	cpu_data[cpu].vpe_id = 0;	cpu_data[cpu].tc_id = 0;	cpu++;	/* Report on boot-time options */	mips_mt_set_cpuoptions ();	if (vpelimit > 0)		printk("Limit of %d VPEs set\n", vpelimit);	if (tclimit > 0)		printk("Limit of %d TCs set\n", tclimit);	if (nostlb) {		printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n");	}	if (asidmask)		printk("ASID mask value override to 0x%x\n", asidmask);	/* Temporary */#ifdef SMTC_IDLE_HOOK_DEBUG	if (hang_trig)		printk("Logic Analyser Trigger on suspected TC hang\n");#endif /* SMTC_IDLE_HOOK_DEBUG */	/* Put MVPE's into 'configuration state' */	write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );	val = read_c0_mvpconf0();	nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;	if (vpelimit > 0 && nvpe > vpelimit)		nvpe = vpelimit;	ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;	if (ntc > NR_CPUS)		ntc = NR_CPUS;	if (tclimit > 0 && ntc > tclimit)		ntc = tclimit;	tcpervpe = ntc / nvpe;	slop = ntc % nvpe;	/* Residual TCs, < NVPE */	/* Set up shared TLB */	smtc_configure_tlb();	for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {		/*		 * Set the MVP bits.		 */		settc(tc);		write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);		if (vpe != 0)			printk(", ");		printk("VPE %d: TC", vpe);		for (i = 0; i < tcpervpe; i++) {			/*			 * TC 0 is bound to VPE 0 at reset,			 * and is presumably executing this			 * code.  Leave it alone!			 */			if (tc != 0) {				smtc_tc_setup(vpe,tc, cpu);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -