Exemple #1
3
/*
 * balance_dirty_pages() must be called by processes which are generating dirty
 * data.  It looks at the number of dirty pages in the machine and will force
 * the caller to perform writeback if the system is over `vm_dirty_ratio'.
 * If we're over `background_thresh' then the writeback threads are woken to
 * perform some writeout.
 */
static void balance_dirty_pages(struct address_space *mapping,
				unsigned long write_chunk)
{
	long nr_reclaimable, bdi_nr_reclaimable;
	long nr_writeback, bdi_nr_writeback;
	unsigned long background_thresh;
	unsigned long dirty_thresh;
	unsigned long bdi_thresh;
	unsigned long pages_written = 0;
	unsigned long pause = 1;
	bool dirty_exceeded = false;
	struct backing_dev_info *bdi = mapping->backing_dev_info;

	for (;;) {
		struct writeback_control wbc = {
			.sync_mode	= WB_SYNC_NONE,
			.older_than_this = NULL,
			.nr_to_write	= write_chunk,
			.range_cyclic	= 1,
		};

		nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
					global_page_state(NR_UNSTABLE_NFS);
		nr_writeback = global_page_state(NR_WRITEBACK);

		global_dirty_limits(&background_thresh, &dirty_thresh);

		/*
		 * Throttle it only when the background writeback cannot
		 * catch-up. This avoids (excessively) small writeouts
		 * when the bdi limits are ramping up.
		 */
		if (nr_reclaimable + nr_writeback <=
				(background_thresh + dirty_thresh) / 2)
			break;

		bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh);
		bdi_thresh = task_dirty_limit(current, bdi_thresh);

		/*
		 * In order to avoid the stacked BDI deadlock we need
		 * to ensure we accurately count the 'dirty' pages when
		 * the threshold is low.
		 *
		 * Otherwise it would be possible to get thresh+n pages
		 * reported dirty, even though there are thresh-m pages
		 * actually dirty; with m+n sitting in the percpu
		 * deltas.
		 */
		if (bdi_thresh < 2*bdi_stat_error(bdi)) {
			bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE);
			bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK);
		} else {
			bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
			bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
		}

		/*
		 * The bdi thresh is somehow "soft" limit derived from the
		 * global "hard" limit. The former helps to prevent heavy IO
		 * bdi or process from holding back light ones; The latter is
		 * the last resort safeguard.
		 */
		dirty_exceeded =
			(bdi_nr_reclaimable + bdi_nr_writeback > bdi_thresh)
			|| (nr_reclaimable + nr_writeback > dirty_thresh);

		if (!dirty_exceeded)
			break;

		if (!bdi->dirty_exceeded)
			bdi->dirty_exceeded = 1;

		/* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
		 * Unstable writes are a feature of certain networked
		 * filesystems (i.e. NFS) in which data may have been
		 * written to the server's write cache, but has not yet
		 * been flushed to permanent storage.
		 * Only move pages to writeback if this bdi is over its
		 * threshold otherwise wait until the disk writes catch
		 * up.
		 */
		trace_wbc_balance_dirty_start(&wbc, bdi);
#if 1	
		/* card atto  */
		if(bdi_nr_reclaimable == 0 && background_thresh == 0 && dirty_thresh == 0){
			//printk("[%s %d] \n", __FUNCTION__, __LINE__);
			break;
		}
#endif
		if (bdi_nr_reclaimable > bdi_thresh) {
#if 1 //card exfat atto test
			if(nr_writeback > wbc_page_num_threshold){
				msleep(wbc_trans_sleep_time * 2); //   0.5s or 1s  or (3s overtime)
			}
#endif
			writeback_inodes_wb(&bdi->wb, &wbc);
			pages_written += write_chunk - wbc.nr_to_write;
			trace_wbc_balance_dirty_written(&wbc, bdi);
			if (pages_written >= write_chunk)
				break;		/* We've done our duty */
		}
		trace_wbc_balance_dirty_wait(&wbc, bdi);
		__set_current_state(TASK_UNINTERRUPTIBLE);
		io_schedule_timeout(pause);

		/*
		 * Increase the delay for each loop, up to our previous
		 * default of taking a 100ms nap.
		 */
		pause <<= 1;
		if (pause > HZ / 10)
			pause = HZ / 10;
	}

	if (!dirty_exceeded && bdi->dirty_exceeded)
		bdi->dirty_exceeded = 0;

	if (writeback_in_progress(bdi))
		return;

	/*
	 * In laptop mode, we wait until hitting the higher threshold before
	 * starting background writeout, and then write out all the way down
	 * to the lower threshold.  So slow writers cause minimal disk activity.
	 *
	 * In normal mode, we start background writeout at the lower
	 * background_thresh, to keep the amount of dirty memory low.
	 */
	if ((laptop_mode && pages_written) ||
	    (!laptop_mode && (nr_reclaimable > background_thresh)))
		bdi_start_background_writeback(bdi);
}

void set_page_dirty_balance(struct page *page, int page_mkwrite)
{
	if (set_page_dirty(page) || page_mkwrite) {
		struct address_space *mapping = page_mapping(page);

		if (mapping)
			balance_dirty_pages_ratelimited(mapping);
	}
}

static DEFINE_PER_CPU(unsigned long, bdp_ratelimits) = 0;

/**
 * balance_dirty_pages_ratelimited_nr - balance dirty memory state
 * @mapping: address_space which was dirtied
 * @nr_pages_dirtied: number of pages which the caller has just dirtied
 *
 * Processes which are dirtying memory should call in here once for each page
 * which was newly dirtied.  The function will periodically check the system's
 * dirty state and will initiate writeback if needed.
 *
 * On really big machines, get_writeback_state is expensive, so try to avoid
 * calling it too often (ratelimiting).  But once we're over the dirty memory
 * limit we decrease the ratelimiting by a lot, to prevent individual processes
 * from overshooting the limit by (ratelimit_pages) each.
 */
void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
					unsigned long nr_pages_dirtied)
{
	unsigned long ratelimit;
	unsigned long *p;

	ratelimit = ratelimit_pages;
	if (mapping->backing_dev_info->dirty_exceeded)
		ratelimit = 128;

	/*
	 * Check the rate limiting. Also, we do not want to throttle real-time
	 * tasks in balance_dirty_pages(). Period.
	 */
	preempt_disable();
	p =  &__get_cpu_var(bdp_ratelimits);
	*p += nr_pages_dirtied;
	if (unlikely(*p >= ratelimit)) {
		ratelimit = sync_writeback_pages(*p);
		*p = 0;
		preempt_enable();
		balance_dirty_pages(mapping, ratelimit);
		return;
	}
	preempt_enable();
}
Exemple #2
1
NORET_TYPE void panic(const char * fmt, ...)
{
	long i;
	static char buf[1024];
	va_list args;
#if defined(CONFIG_S390)
	unsigned long caller = (unsigned long) __builtin_return_address(0);
#endif

	/*
	 * It's possible to come here directly from a panic-assertion and not
	 * have preempt disabled. Some functions called from here want
	 * preempt to be disabled. No point enabling it later though...
	 */
	preempt_disable();

	bust_spinlocks(1);
	va_start(args, fmt);
	vsnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);
	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
	bust_spinlocks(0);

	/*
	 * If we have crashed and we have a crash kernel loaded let it handle
	 * everything else.
	 * Do we want to call this before we try to display a message?
	 */
	crash_kexec(NULL);

#ifdef CONFIG_SMP
	/*
	 * Note smp_send_stop is the usual smp shutdown function, which
	 * unfortunately means it may not be hardened to work in a panic
	 * situation.
	 */
	smp_send_stop();
#endif

	atomic_notifier_call_chain(&panic_notifier_list, 0, buf);

	if (!panic_blink)
		panic_blink = no_blink;

	if (panic_timeout > 0) {
		/*
	 	 * Delay timeout seconds before rebooting the machine. 
		 * We can't use the "normal" timers since we just panicked..
	 	 */
		printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
		for (i = 0; i < panic_timeout*1000; ) {
			touch_nmi_watchdog();
			i += panic_blink(i);
			mdelay(1);
			i++;
		}
		/*	This will not be a clean reboot, with everything
		 *	shutting down.  But if there is a chance of
		 *	rebooting the system it will be rebooted.
		 */
		emergency_restart();
	}
#ifdef __sparc__
	{
		extern int stop_a_enabled;
		/* Make sure the user can actually press Stop-A (L1-A) */
		stop_a_enabled = 1;
		printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n");
	}
#endif
#if defined(CONFIG_S390)
	disabled_wait(caller);
#endif
	local_irq_enable();
	for (i = 0;;) {
		touch_softlockup_watchdog();
		i += panic_blink(i);
		mdelay(1);
		i++;
	}
}
Exemple #3
0
void __lockfunc _spin_lock(spinlock_t *lock)
{
	preempt_disable();
	_raw_spin_lock(lock);
}
Exemple #4
0
static inline void vperfctr_task_lock(struct task_struct *p)
{
	preempt_disable();
}
asmlinkage int vprintk(const char *fmt, va_list args)
{
	int printed_len = 0;
	int current_log_level = default_message_loglevel;
	unsigned long flags;
	int this_cpu;
	char *p;

	boot_delay_msec();
	printk_delay();

	preempt_disable();
	/* This stops the holder of console_sem just where we want him */
	raw_local_irq_save(flags);
	this_cpu = smp_processor_id();

	/*
	 * Ouch, printk recursed into itself!
	 */
	if (unlikely(printk_cpu == this_cpu)) {
		/*
		 * If a crash is occurring during printk() on this CPU,
		 * then try to get the crash message out but make sure
		 * we can't deadlock. Otherwise just return to avoid the
		 * recursion and return - but flag the recursion so that
		 * it can be printed at the next appropriate moment:
		 */
		if (!oops_in_progress) {
			recursion_bug = 1;
			goto out_restore_irqs;
		}
		zap_locks();
	}

	lockdep_off();
	spin_lock(&logbuf_lock);
	printk_cpu = this_cpu;

	if (recursion_bug) {
		recursion_bug = 0;
		strcpy(printk_buf, recursion_bug_msg);
		printed_len = strlen(recursion_bug_msg);
	}
	/* Emit the output into the temporary buffer */
	printed_len += vscnprintf(printk_buf + printed_len,
				  sizeof(printk_buf) - printed_len, fmt, args);

#ifdef	CONFIG_DEBUG_LL
	printascii(printk_buf);
#endif

	p = printk_buf;

	/* Do we have a loglevel in the string? */
	if (p[0] == '<') {
		unsigned char c = p[1];
		if (c && p[2] == '>') {
			switch (c) {
			case '0' ... '7': /* loglevel */
				current_log_level = c - '0';
			/* Fallthrough - make sure we're on a new line */
			case 'd': /* KERN_DEFAULT */
				if (!new_text_line) {
					emit_log_char('\n');
					new_text_line = 1;
				}
			/* Fallthrough - skip the loglevel */
			case 'c': /* KERN_CONT */
				p += 3;
				break;
			}
		}
	}
Exemple #6
0
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
	unsigned long unused, struct task_struct *p, struct pt_regs *regs)
{
	struct thread_info *ti = task_thread_info(p);
	struct pt_regs *childregs;
	unsigned long childksp;
	p->set_child_tid = p->clear_child_tid = NULL;

	childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;

	preempt_disable();

	if (is_fpu_owner())
		save_fp(p);

	if (cpu_has_dsp)
		save_dsp(p);

	preempt_enable();

	/* set up new TSS. */
	childregs = (struct pt_regs *) childksp - 1;
	/*  Put the stack after the struct pt_regs.  */
	childksp = (unsigned long) childregs;
	*childregs = *regs;
	childregs->regs[7] = 0;	/* Clear error flag */

#if defined(CONFIG_BINFMT_IRIX)
	if (current->personality != PER_LINUX) {
		/* Under IRIX things are a little different. */
		childregs->regs[3] = 1;
		regs->regs[3] = 0;
	}
#endif
	childregs->regs[2] = 0;	/* Child gets zero as return value */

	if (childregs->cp0_status & ST0_CU0) {
		childregs->regs[28] = (unsigned long) ti;
		childregs->regs[29] = childksp;
		ti->addr_limit = KERNEL_DS;
	} else {
		childregs->regs[29] = usp;
		ti->addr_limit = USER_DS;
	}
	p->thread.reg29 = (unsigned long) childregs;
	p->thread.reg31 = (unsigned long) ret_from_fork;

	/*
	 * New tasks lose permission to use the fpu. This accelerates context
	 * switching for most programs since they don't use the fpu.
	 */
	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
	clear_tsk_thread_flag(p, TIF_USEDFPU);

#ifdef CONFIG_MIPS_MT_FPAFF
	/*
	 * FPU affinity support is cleaner if we track the
	 * user-visible CPU affinity from the very beginning.
	 * The generic cpus_allowed mask will already have
	 * been copied from the parent before copy_thread
	 * is invoked.
	 */
	p->thread.user_cpus_allowed = p->cpus_allowed;
#endif /* CONFIG_MIPS_MT_FPAFF */

	if (clone_flags & CLONE_SETTLS)
		ti->tp_value = regs->regs[7];

	return 0;
}
Exemple #7
0
/*
 * Lock a mutex (possibly interruptible), slowpath:
 */
static inline int __sched
__mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
		    struct lockdep_map *nest_lock, unsigned long ip)
{
	struct task_struct *task = current;
	struct mutex_waiter waiter;
	unsigned long flags;

	preempt_disable();
	mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip);

#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
	/*
	 * Optimistic spinning.
	 *
	 * We try to spin for acquisition when we find that there are no
	 * pending waiters and the lock owner is currently running on a
	 * (different) CPU.
	 *
	 * The rationale is that if the lock owner is running, it is likely to
	 * release the lock soon.
	 *
	 * Since this needs the lock owner, and this mutex implementation
	 * doesn't track the owner atomically in the lock field, we need to
	 * track it non-atomically.
	 *
	 * We can't do this for DEBUG_MUTEXES because that relies on wait_lock
	 * to serialize everything.
	 */

	for (;;) {
		struct task_struct *owner;

		/*
		 * If there's an owner, wait for it to either
		 * release the lock or go to sleep.
		 */
		owner = ACCESS_ONCE(lock->owner);
		if (owner && !mutex_spin_on_owner(lock, owner))
			break;

		if (atomic_cmpxchg(&lock->count, 1, 0) == 1) {  
			lock_acquired(&lock->dep_map, ip);
			mutex_set_owner(lock);
			preempt_enable();
			return 0;
		}

		/*
		 * When there's no owner, we might have preempted between the
		 * owner acquiring the lock and setting the owner field. If
		 * we're an RT task that will live-lock because we won't let
		 * the owner complete.
		 */
		if (!owner && (need_resched() || rt_task(task)))
			break;

		/*
		 * The cpu_relax() call is a compiler barrier which forces
		 * everything in this loop to be re-loaded. We don't need
		 * memory barriers as we'll eventually observe the right
		 * values at the cost of a few extra spins.
		 */
		arch_mutex_cpu_relax();
	}
#endif
	spin_lock_mutex(&lock->wait_lock, flags);

	debug_mutex_lock_common(lock, &waiter);
	debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));

	/* add waiting tasks to the end of the waitqueue (FIFO): */
	list_add_tail(&waiter.list, &lock->wait_list);
	waiter.task = task;

	if (atomic_xchg(&lock->count, -1) == 1)  
		goto done;

	lock_contended(&lock->dep_map, ip);

	for (;;) {
		/*
		 * Lets try to take the lock again - this is needed even if
		 * we get here for the first time (shortly after failing to
		 * acquire the lock), to make sure that we get a wakeup once
		 * it's unlocked. Later on, if we sleep, this is the
		 * operation that gives us the lock. We xchg it to -1, so
		 * that when we release the lock, we properly wake up the
		 * other waiters:
		 */
		if (atomic_xchg(&lock->count, -1) == 1) 
			break;

		/*
		 * got a signal? (This code gets eliminated in the
		 * TASK_UNINTERRUPTIBLE case.)
		 */
		if (unlikely(signal_pending_state(state, task))) {
			mutex_remove_waiter(lock, &waiter,
					    task_thread_info(task));
			mutex_release(&lock->dep_map, 1, ip);
			spin_unlock_mutex(&lock->wait_lock, flags);

			debug_mutex_free_waiter(&waiter);
			preempt_enable();
			return -EINTR;
		}
		__set_task_state(task, state);

		/* didn't get the lock, go to sleep: */
		spin_unlock_mutex(&lock->wait_lock, flags);
		preempt_enable_no_resched();
		schedule();
		preempt_disable();
		spin_lock_mutex(&lock->wait_lock, flags);
	}

done:
	lock_acquired(&lock->dep_map, ip);
	/* got the lock - rejoice! */
	mutex_remove_waiter(lock, &waiter, current_thread_info());
	mutex_set_owner(lock);

	/* set it to 0 if there are no waiters left: */
	if (likely(list_empty(&lock->wait_list)))
		atomic_set(&lock->count, 0);

	spin_unlock_mutex(&lock->wait_lock, flags);

	debug_mutex_free_waiter(&waiter);
	preempt_enable();

	return 0;
}
Exemple #8
0
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
			sigset_t *set, struct pt_regs *regs)
{
	struct rt_sigframe __user *frame;
	int err = 0;
	int signal;
	unsigned long address = 0;
#ifdef CONFIG_MMU
	pmd_t *pmdp;
	pte_t *ptep;
#endif

	frame = get_sigframe(ka, regs, sizeof(*frame));

	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		goto give_sigsegv;

	signal = current_thread_info()->exec_domain
		&& current_thread_info()->exec_domain->signal_invmap
		&& sig < 32
		? current_thread_info()->exec_domain->signal_invmap[sig]
		: sig;

	if (info)
		err |= copy_siginfo_to_user(&frame->info, info);

	/* Create the ucontext. */
	err |= __put_user(0, &frame->uc.uc_flags);
	err |= __put_user(NULL, &frame->uc.uc_link);
	err |= __save_altstack(&frame->uc.uc_stack, regs->r1);
	err |= setup_sigcontext(&frame->uc.uc_mcontext,
			regs, set->sig[0]);
	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));

	/* Set up to return from userspace. If provided, use a stub
	 already in userspace. */
	/* minus 8 is offset to cater for "rtsd r15,8" */
	/* addi r12, r0, __NR_sigreturn */
	err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
			frame->tramp + 0);
	/* brki r14, 0x8 */
	err |= __put_user(0xb9cc0008, frame->tramp + 1);

	/* Return from sighandler will jump to the tramp.
	 Negative 8 offset because return is rtsd r15, 8 */
	regs->r15 = ((unsigned long)frame->tramp)-8;

	address = ((unsigned long)frame->tramp);
#ifdef CONFIG_MMU
	pmdp = pmd_offset(pud_offset(
			pgd_offset(current->mm, address),
					address), address);

	preempt_disable();
	ptep = pte_offset_map(pmdp, address);
	if (pte_present(*ptep)) {
		address = (unsigned long) page_address(pte_page(*ptep));
		/* MS: I need add offset in page */
		address += ((unsigned long)frame->tramp) & ~PAGE_MASK;
		/* MS address is virtual */
		address = __virt_to_phys(address);
		invalidate_icache_range(address, address + 8);
		flush_dcache_range(address, address + 8);
	}
	pte_unmap(ptep);
	preempt_enable();
#else
	flush_icache_range(address, address + 8);
	flush_dcache_range(address, address + 8);
#endif
	if (err)
		goto give_sigsegv;

	/* Set up registers for signal handler */
	regs->r1 = (unsigned long) frame;

	/* Signal handler args: */
	regs->r5 = signal; /* arg 0: signum */
	regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
	regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
	/* Offset to handle microblaze rtid r14, 0 */
	regs->pc = (unsigned long)ka->sa.sa_handler;

	set_fs(USER_DS);

#ifdef DEBUG_SIG
	pr_info("SIG deliver (%s:%d): sp=%p pc=%08lx\n",
		current->comm, current->pid, frame, regs->pc);
#endif

	return 0;

give_sigsegv:
	force_sigsegv(sig, current);
	return -EFAULT;
}
Exemple #9
0
/*
 * balance_dirty_pages() must be called by processes which are generating dirty
 * data.  It looks at the number of dirty pages in the machine and will force
 * the caller to perform writeback if the system is over `vm_dirty_ratio'.
 * If we're over `background_thresh' then pdflush is woken to perform some
 * writeout.
 */
static void balance_dirty_pages(struct address_space *mapping)
{
	long nr_reclaimable, bdi_nr_reclaimable;
	long nr_writeback, bdi_nr_writeback;
	long background_thresh;
	long dirty_thresh;
	long bdi_thresh;
	unsigned long pages_written = 0;
	unsigned long write_chunk = sync_writeback_pages();

	struct backing_dev_info *bdi = mapping->backing_dev_info;

	for (;;) {
		struct writeback_control wbc = {
			.bdi		= bdi,
			.sync_mode	= WB_SYNC_NONE,
			.older_than_this = NULL,
			.nr_to_write	= write_chunk,
			.range_cyclic	= 1,
		};

		get_dirty_limits(&background_thresh, &dirty_thresh,
				&bdi_thresh, bdi);

		nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
					global_page_state(NR_UNSTABLE_NFS);
		nr_writeback = global_page_state(NR_WRITEBACK);

		bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
		bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);

		if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh)
			break;

		/*
		 * Throttle it only when the background writeback cannot
		 * catch-up. This avoids (excessively) small writeouts
		 * when the bdi limits are ramping up.
		 */
		if (nr_reclaimable + nr_writeback <
				(background_thresh + dirty_thresh) / 2)
			break;

		if (!bdi->dirty_exceeded)
			bdi->dirty_exceeded = 1;

		/* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
		 * Unstable writes are a feature of certain networked
		 * filesystems (i.e. NFS) in which data may have been
		 * written to the server's write cache, but has not yet
		 * been flushed to permanent storage.
		 */
		if (bdi_nr_reclaimable) {
			writeback_inodes(&wbc);
			pages_written += write_chunk - wbc.nr_to_write;
			get_dirty_limits(&background_thresh, &dirty_thresh,
				       &bdi_thresh, bdi);
		}

		/*
		 * In order to avoid the stacked BDI deadlock we need
		 * to ensure we accurately count the 'dirty' pages when
		 * the threshold is low.
		 *
		 * Otherwise it would be possible to get thresh+n pages
		 * reported dirty, even though there are thresh-m pages
		 * actually dirty; with m+n sitting in the percpu
		 * deltas.
		 */
		if (bdi_thresh < 2*bdi_stat_error(bdi)) {
			bdi_nr_reclaimable = bdi_stat_sum(bdi, BDI_RECLAIMABLE);
			bdi_nr_writeback = bdi_stat_sum(bdi, BDI_WRITEBACK);
		} else if (bdi_nr_reclaimable) {
			bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
			bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
		}

		if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh)
			break;
		if (pages_written >= write_chunk)
			break;		/* We've done our duty */

		congestion_wait(WRITE, HZ/10);
	}

	if (bdi_nr_reclaimable + bdi_nr_writeback < bdi_thresh &&
			bdi->dirty_exceeded)
		bdi->dirty_exceeded = 0;

	if (writeback_in_progress(bdi))
		return;		/* pdflush is already working this queue */

	/*
	 * In laptop mode, we wait until hitting the higher threshold before
	 * starting background writeout, and then write out all the way down
	 * to the lower threshold.  So slow writers cause minimal disk activity.
	 *
	 * In normal mode, we start background writeout at the lower
	 * background_thresh, to keep the amount of dirty memory low.
	 */
	if ((laptop_mode && pages_written) ||
			(!laptop_mode && (global_page_state(NR_FILE_DIRTY)
					  + global_page_state(NR_UNSTABLE_NFS)
					  > background_thresh)))
		pdflush_operation(background_writeout, 0);
}

void set_page_dirty_balance(struct page *page, int page_mkwrite)
{
	if (set_page_dirty(page) || page_mkwrite) {
		struct address_space *mapping = page_mapping(page);

		if (mapping)
			balance_dirty_pages_ratelimited(mapping);
	}
}

/**
 * balance_dirty_pages_ratelimited_nr - balance dirty memory state
 * @mapping: address_space which was dirtied
 * @nr_pages_dirtied: number of pages which the caller has just dirtied
 *
 * Processes which are dirtying memory should call in here once for each page
 * which was newly dirtied.  The function will periodically check the system's
 * dirty state and will initiate writeback if needed.
 *
 * On really big machines, get_writeback_state is expensive, so try to avoid
 * calling it too often (ratelimiting).  But once we're over the dirty memory
 * limit we decrease the ratelimiting by a lot, to prevent individual processes
 * from overshooting the limit by (ratelimit_pages) each.
 */
void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
					unsigned long nr_pages_dirtied)
{
	static DEFINE_PER_CPU(unsigned long, ratelimits) = 0;
	unsigned long ratelimit;
	unsigned long *p;

	ratelimit = ratelimit_pages;
	if (mapping->backing_dev_info->dirty_exceeded)
		ratelimit = 8;

	/*
	 * Check the rate limiting. Also, we do not want to throttle real-time
	 * tasks in balance_dirty_pages(). Period.
	 */
	preempt_disable();
	p =  &__get_cpu_var(ratelimits);
	*p += nr_pages_dirtied;
	if (unlikely(*p >= ratelimit)) {
		*p = 0;
		preempt_enable();
		balance_dirty_pages(mapping);
		return;
	}
	preempt_enable();
}
EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr);

void throttle_vm_writeout(gfp_t gfp_mask)
{
	long background_thresh;
	long dirty_thresh;

        for ( ; ; ) {
		get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL);

                /*
                 * Boost the allowable dirty threshold a bit for page
                 * allocators so they don't get DoS'ed by heavy writers
                 */
                dirty_thresh += dirty_thresh / 10;      /* wheeee... */

                if (global_page_state(NR_UNSTABLE_NFS) +
			global_page_state(NR_WRITEBACK) <= dirty_thresh)
                        	break;
                congestion_wait(WRITE, HZ/10);

		/*
		 * The caller might hold locks which can prevent IO completion
		 * or progress in the filesystem.  So we cannot just sit here
		 * waiting for IO to complete.
		 */
		if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO))
			break;
        }
}
Exemple #10
0
int copy_thread(unsigned long clone_flags, unsigned long usp,
	unsigned long unused, struct task_struct *p, struct pt_regs *regs)
{
	struct thread_info *ti = task_thread_info(p);
	struct pt_regs *childregs;
	unsigned long childksp;
	p->set_child_tid = p->clear_child_tid = NULL;

	childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;

	preempt_disable();

	if (is_fpu_owner())
		save_fp(p);

	if (cpu_has_dsp)
		save_dsp(p);

	preempt_enable();

	/* set up new TSS. */
	childregs = (struct pt_regs *) childksp - 1;
	/*  Put the stack after the struct pt_regs.  */
	childksp = (unsigned long) childregs;
	*childregs = *regs;
	childregs->regs[7] = 0;	/* Clear error flag */

	childregs->regs[2] = 0;	/* Child gets zero as return value */

	if (childregs->cp0_status & ST0_CU0) {
		childregs->regs[28] = (unsigned long) ti;
		childregs->regs[29] = childksp;
		ti->addr_limit = KERNEL_DS;
	} else {
		childregs->regs[29] = usp;
		ti->addr_limit = USER_DS;
	}
	p->thread.reg29 = (unsigned long) childregs;
	p->thread.reg31 = (unsigned long) ret_from_fork;

	/*
	 * New tasks lose permission to use the fpu. This accelerates context
	 * switching for most programs since they don't use the fpu.
	 */
	p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);

#ifdef CONFIG_MIPS_MT_SMTC
	/*
	 * SMTC restores TCStatus after Status, and the CU bits
	 * are aliased there.
	 */
	childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1);
#endif
	clear_tsk_thread_flag(p, TIF_USEDFPU);

#ifdef CONFIG_MIPS_MT_FPAFF
	clear_tsk_thread_flag(p, TIF_FPUBOUND);
#endif /* CONFIG_MIPS_MT_FPAFF */

	if (clone_flags & CLONE_SETTLS)
		ti->tp_value = regs->regs[7];

	return 0;
}
Exemple #11
0
/**
 * speedstep_set_state - set the SpeedStep state
 * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
 *
 */
static void speedstep_set_state(unsigned int state)
{
	unsigned int result = 0, command, new_state, dummy;
	unsigned long flags;
	unsigned int function = SET_SPEEDSTEP_STATE;
	unsigned int retry = 0;

	if (state > 0x1)
		return;

	/* Disable IRQs */
	preempt_disable();
	local_irq_save(flags);

	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);

	pr_debug("trying to set frequency to state %u "
		"with command %x at port %x\n",
		state, command, smi_port);

	do {
		if (retry) {
			/*
			 * We need to enable interrupts, otherwise the blockage
			 * won't resolve.
			 *
			 * We disable preemption so that other processes don't
			 * run. If other processes were running, they could
			 * submit more DMA requests, making the blockage worse.
			 */
			pr_debug("retry %u, previous result %u, waiting...\n",
					retry, result);
			local_irq_enable();
			mdelay(retry * 50);
			local_irq_disable();
		}
		retry++;
		__asm__ __volatile__(
			"push %%ebp\n"
			"out %%al, (%%dx)\n"
			"pop %%ebp"
			: "=b" (new_state), "=D" (result),
			  "=c" (dummy), "=a" (dummy),
			  "=d" (dummy), "=S" (dummy)
			: "a" (command), "b" (function), "c" (state),
			  "d" (smi_port), "S" (0), "D" (0)
			);
	} while ((new_state != state) && (retry <= SMI_TRIES));

	/* enable IRQs */
	local_irq_restore(flags);
	preempt_enable();

	if (new_state == state)
		pr_debug("change to %u MHz succeeded after %u tries "
			"with result %u\n",
			(speedstep_freqs[new_state].frequency / 1000),
			retry, result);
	else
		pr_err("change to state %u failed with new_state %u and result %u\n",
		       state, new_state, result);

	return;
}
Exemple #12
0
void __lockfunc _spin_lock_bh(spinlock_t *lock)
{
	local_bh_disable();
	preempt_disable();
	_raw_spin_lock(lock);
}
Exemple #13
0
void __lockfunc _read_lock(rwlock_t *lock)
{
	preempt_disable();
	_raw_read_lock(lock);
}
Exemple #14
0
void __lockfunc _write_lock(rwlock_t *lock)
{
	preempt_disable();
	_raw_write_lock(lock);
}
int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
	u32 inst;
	enum emulation_result emulated = EMULATE_DONE;
	int ax_rd, ax_ra, ax_rb, ax_rc;
	short full_d;
	u64 *fpr_d, *fpr_a, *fpr_b, *fpr_c;

	bool rcomp;
	u32 cr;
#ifdef DEBUG
	int i;
#endif

	emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst);
	if (emulated != EMULATE_DONE)
		return emulated;

	ax_rd = inst_get_field(inst, 6, 10);
	ax_ra = inst_get_field(inst, 11, 15);
	ax_rb = inst_get_field(inst, 16, 20);
	ax_rc = inst_get_field(inst, 21, 25);
	full_d = inst_get_field(inst, 16, 31);

	fpr_d = &VCPU_FPR(vcpu, ax_rd);
	fpr_a = &VCPU_FPR(vcpu, ax_ra);
	fpr_b = &VCPU_FPR(vcpu, ax_rb);
	fpr_c = &VCPU_FPR(vcpu, ax_rc);

	rcomp = (inst & 1) ? true : false;
	cr = kvmppc_get_cr(vcpu);

	if (!kvmppc_inst_is_paired_single(vcpu, inst))
		return EMULATE_FAIL;

	if (!(kvmppc_get_msr(vcpu) & MSR_FP)) {
		kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
		return EMULATE_AGAIN;
	}

	kvmppc_giveup_ext(vcpu, MSR_FP);
	preempt_disable();
	enable_kernel_fp();
	/* Do we need to clear FE0 / FE1 here? Don't think so. */

#ifdef DEBUG
	for (i = 0; i < ARRAY_SIZE(vcpu->arch.fp.fpr); i++) {
		u32 f;
		kvm_cvt_df(&VCPU_FPR(vcpu, i), &f);
		dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx    QPR[%d] = 0x%x\n",
			i, f, VCPU_FPR(vcpu, i), i, vcpu->arch.qpr[i]);
	}
#endif

	switch (get_op(inst)) {
	case OP_PSQ_L:
	{
		ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
		bool w = inst_get_field(inst, 16, 16) ? true : false;
		int i = inst_get_field(inst, 17, 19);

		addr += get_d_signext(inst);
		emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);
		break;
	}
	case OP_PSQ_LU:
	{
		ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
		bool w = inst_get_field(inst, 16, 16) ? true : false;
		int i = inst_get_field(inst, 17, 19);

		addr += get_d_signext(inst);
		emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);

		if (emulated == EMULATE_DONE)
			kvmppc_set_gpr(vcpu, ax_ra, addr);
		break;
	}
	case OP_PSQ_ST:
	{
		ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
		bool w = inst_get_field(inst, 16, 16) ? true : false;
		int i = inst_get_field(inst, 17, 19);

		addr += get_d_signext(inst);
		emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);
		break;
	}
	case OP_PSQ_STU:
	{
		ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
		bool w = inst_get_field(inst, 16, 16) ? true : false;
		int i = inst_get_field(inst, 17, 19);

		addr += get_d_signext(inst);
		emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);

		if (emulated == EMULATE_DONE)
			kvmppc_set_gpr(vcpu, ax_ra, addr);
		break;
	}
	case 4:
		/* X form */
		switch (inst_get_field(inst, 21, 30)) {
		case OP_4X_PS_CMPU0:
			/* XXX */
			emulated = EMULATE_FAIL;
			break;
		case OP_4X_PSQ_LX:
		{
			ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
			bool w = inst_get_field(inst, 21, 21) ? true : false;
			int i = inst_get_field(inst, 22, 24);

			addr += kvmppc_get_gpr(vcpu, ax_rb);
			emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);
			break;
		}
		case OP_4X_PS_CMPO0:
			/* XXX */
			emulated = EMULATE_FAIL;
			break;
		case OP_4X_PSQ_LUX:
		{
			ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
			bool w = inst_get_field(inst, 21, 21) ? true : false;
			int i = inst_get_field(inst, 22, 24);

			addr += kvmppc_get_gpr(vcpu, ax_rb);
			emulated = kvmppc_emulate_psq_load(run, vcpu, ax_rd, addr, w, i);

			if (emulated == EMULATE_DONE)
				kvmppc_set_gpr(vcpu, ax_ra, addr);
			break;
		}
		case OP_4X_PS_NEG:
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
			VCPU_FPR(vcpu, ax_rd) ^= 0x8000000000000000ULL;
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
			vcpu->arch.qpr[ax_rd] ^= 0x80000000;
			break;
		case OP_4X_PS_CMPU1:
			/* XXX */
			emulated = EMULATE_FAIL;
			break;
		case OP_4X_PS_MR:
			WARN_ON(rcomp);
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
			break;
		case OP_4X_PS_CMPO1:
			/* XXX */
			emulated = EMULATE_FAIL;
			break;
		case OP_4X_PS_NABS:
			WARN_ON(rcomp);
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
			VCPU_FPR(vcpu, ax_rd) |= 0x8000000000000000ULL;
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
			vcpu->arch.qpr[ax_rd] |= 0x80000000;
			break;
		case OP_4X_PS_ABS:
			WARN_ON(rcomp);
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rb);
			VCPU_FPR(vcpu, ax_rd) &= ~0x8000000000000000ULL;
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
			vcpu->arch.qpr[ax_rd] &= ~0x80000000;
			break;
		case OP_4X_PS_MERGE00:
			WARN_ON(rcomp);
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_ra);
			/* vcpu->arch.qpr[ax_rd] = VCPU_FPR(vcpu, ax_rb); */
			kvm_cvt_df(&VCPU_FPR(vcpu, ax_rb),
				   &vcpu->arch.qpr[ax_rd]);
			break;
		case OP_4X_PS_MERGE01:
			WARN_ON(rcomp);
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_ra);
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
			break;
		case OP_4X_PS_MERGE10:
			WARN_ON(rcomp);
			/* VCPU_FPR(vcpu, ax_rd) = vcpu->arch.qpr[ax_ra]; */
			kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
				   &VCPU_FPR(vcpu, ax_rd));
			/* vcpu->arch.qpr[ax_rd] = VCPU_FPR(vcpu, ax_rb); */
			kvm_cvt_df(&VCPU_FPR(vcpu, ax_rb),
				   &vcpu->arch.qpr[ax_rd]);
			break;
		case OP_4X_PS_MERGE11:
			WARN_ON(rcomp);
			/* VCPU_FPR(vcpu, ax_rd) = vcpu->arch.qpr[ax_ra]; */
			kvm_cvt_fd(&vcpu->arch.qpr[ax_ra],
				   &VCPU_FPR(vcpu, ax_rd));
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb];
			break;
		}
		/* XW form */
		switch (inst_get_field(inst, 25, 30)) {
		case OP_4XW_PSQ_STX:
		{
			ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;
			bool w = inst_get_field(inst, 21, 21) ? true : false;
			int i = inst_get_field(inst, 22, 24);

			addr += kvmppc_get_gpr(vcpu, ax_rb);
			emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);
			break;
		}
		case OP_4XW_PSQ_STUX:
		{
			ulong addr = kvmppc_get_gpr(vcpu, ax_ra);
			bool w = inst_get_field(inst, 21, 21) ? true : false;
			int i = inst_get_field(inst, 22, 24);

			addr += kvmppc_get_gpr(vcpu, ax_rb);
			emulated = kvmppc_emulate_psq_store(run, vcpu, ax_rd, addr, w, i);

			if (emulated == EMULATE_DONE)
				kvmppc_set_gpr(vcpu, ax_ra, addr);
			break;
		}
		}
		/* A form */
		switch (inst_get_field(inst, 26, 30)) {
		case OP_4A_PS_SUM1:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_rb, ax_ra, SCALAR_NO_PS0 | SCALAR_HIGH, fps_fadds);
			VCPU_FPR(vcpu, ax_rd) = VCPU_FPR(vcpu, ax_rc);
			break;
		case OP_4A_PS_SUM0:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rb, SCALAR_NO_PS1 | SCALAR_LOW, fps_fadds);
			vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rc];
			break;
		case OP_4A_PS_MULS0:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, SCALAR_HIGH, fps_fmuls);
			break;
		case OP_4A_PS_MULS1:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, SCALAR_LOW, fps_fmuls);
			break;
		case OP_4A_PS_MADDS0:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_HIGH, fps_fmadds);
			break;
		case OP_4A_PS_MADDS1:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_LOW, fps_fmadds);
			break;
		case OP_4A_PS_DIV:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rb, SCALAR_NONE, fps_fdivs);
			break;
		case OP_4A_PS_SUB:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rb, SCALAR_NONE, fps_fsubs);
			break;
		case OP_4A_PS_ADD:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rb, SCALAR_NONE, fps_fadds);
			break;
		case OP_4A_PS_SEL:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fsel);
			break;
		case OP_4A_PS_RES:
			emulated = kvmppc_ps_one_in(vcpu, rcomp, ax_rd,
					ax_rb, fps_fres);
			break;
		case OP_4A_PS_MUL:
			emulated = kvmppc_ps_two_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, SCALAR_NONE, fps_fmuls);
			break;
		case OP_4A_PS_RSQRTE:
			emulated = kvmppc_ps_one_in(vcpu, rcomp, ax_rd,
					ax_rb, fps_frsqrte);
			break;
		case OP_4A_PS_MSUB:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fmsubs);
			break;
		case OP_4A_PS_MADD:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fmadds);
			break;
		case OP_4A_PS_NMSUB:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fnmsubs);
			break;
		case OP_4A_PS_NMADD:
			emulated = kvmppc_ps_three_in(vcpu, rcomp, ax_rd,
					ax_ra, ax_rc, ax_rb, SCALAR_NONE, fps_fnmadds);
			break;
		}
		break;

	/* Real FPU operations */

	case OP_LFS:
	{
		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;

		emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
						   FPU_LS_SINGLE);
		break;
	}
	case OP_LFSU:
	{
		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;

		emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
						   FPU_LS_SINGLE);

		if (emulated == EMULATE_DONE)
			kvmppc_set_gpr(vcpu, ax_ra, addr);
		break;
	}
	case OP_LFD:
	{
		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;

		emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
						   FPU_LS_DOUBLE);
		break;
	}
	case OP_LFDU:
	{
		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;

		emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd, addr,
						   FPU_LS_DOUBLE);

		if (emulated == EMULATE_DONE)
			kvmppc_set_gpr(vcpu, ax_ra, addr);
		break;
	}
	case OP_STFS:
	{
		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;

		emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
						    FPU_LS_SINGLE);
		break;
	}
	case OP_STFSU:
	{
		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;

		emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
						    FPU_LS_SINGLE);

		if (emulated == EMULATE_DONE)
			kvmppc_set_gpr(vcpu, ax_ra, addr);
		break;
	}
	case OP_STFD:
	{
		ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) + full_d;

		emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
						    FPU_LS_DOUBLE);
		break;
	}
	case OP_STFDU:
	{
		ulong addr = kvmppc_get_gpr(vcpu, ax_ra) + full_d;

		emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd, addr,
						    FPU_LS_DOUBLE);

		if (emulated == EMULATE_DONE)
			kvmppc_set_gpr(vcpu, ax_ra, addr);
		break;
	}
	case 31:
		switch (inst_get_field(inst, 21, 30)) {
		case OP_31_LFSX:
		{
			ulong addr = ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0;

			addr += kvmppc_get_gpr(vcpu, ax_rb);
			emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
							   addr, FPU_LS_SINGLE);
			break;
		}
		case OP_31_LFSUX:
		{
			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
							   addr, FPU_LS_SINGLE);

			if (emulated == EMULATE_DONE)
				kvmppc_set_gpr(vcpu, ax_ra, addr);
			break;
		}
		case OP_31_LFDX:
		{
			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
							   addr, FPU_LS_DOUBLE);
			break;
		}
		case OP_31_LFDUX:
		{
			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_load(run, vcpu, ax_rd,
							   addr, FPU_LS_DOUBLE);

			if (emulated == EMULATE_DONE)
				kvmppc_set_gpr(vcpu, ax_ra, addr);
			break;
		}
		case OP_31_STFSX:
		{
			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
							    addr, FPU_LS_SINGLE);
			break;
		}
		case OP_31_STFSUX:
		{
			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
							    addr, FPU_LS_SINGLE);

			if (emulated == EMULATE_DONE)
				kvmppc_set_gpr(vcpu, ax_ra, addr);
			break;
		}
		case OP_31_STFX:
		{
			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
							    addr, FPU_LS_DOUBLE);
			break;
		}
		case OP_31_STFUX:
		{
			ulong addr = kvmppc_get_gpr(vcpu, ax_ra) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
							    addr, FPU_LS_DOUBLE);

			if (emulated == EMULATE_DONE)
				kvmppc_set_gpr(vcpu, ax_ra, addr);
			break;
		}
		case OP_31_STFIWX:
		{
			ulong addr = (ax_ra ? kvmppc_get_gpr(vcpu, ax_ra) : 0) +
				     kvmppc_get_gpr(vcpu, ax_rb);

			emulated = kvmppc_emulate_fpr_store(run, vcpu, ax_rd,
							    addr,
							    FPU_LS_SINGLE_LOW);
			break;
		}
			break;
		}
		break;
	case 59:
		switch (inst_get_field(inst, 21, 30)) {
		case OP_59_FADDS:
			fpd_fadds(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FSUBS:
			fpd_fsubs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FDIVS:
			fpd_fdivs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FRES:
			fpd_fres(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FRSQRTES:
			fpd_frsqrtes(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		}
		switch (inst_get_field(inst, 26, 30)) {
		case OP_59_FMULS:
			fpd_fmuls(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FMSUBS:
			fpd_fmsubs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FMADDS:
			fpd_fmadds(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FNMSUBS:
			fpd_fnmsubs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_59_FNMADDS:
			fpd_fnmadds(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		}
		break;
	case 63:
		switch (inst_get_field(inst, 21, 30)) {
		case OP_63_MTFSB0:
		case OP_63_MTFSB1:
		case OP_63_MCRFS:
		case OP_63_MTFSFI:
			/* XXX need to implement */
			break;
		case OP_63_MFFS:
			/* XXX missing CR */
			*fpr_d = vcpu->arch.fp.fpscr;
			break;
		case OP_63_MTFSF:
			/* XXX missing fm bits */
			/* XXX missing CR */
			vcpu->arch.fp.fpscr = *fpr_b;
			break;
		case OP_63_FCMPU:
		{
			u32 tmp_cr;
			u32 cr0_mask = 0xf0000000;
			u32 cr_shift = inst_get_field(inst, 6, 8) * 4;

			fpd_fcmpu(&vcpu->arch.fp.fpscr, &tmp_cr, fpr_a, fpr_b);
			cr &= ~(cr0_mask >> cr_shift);
			cr |= (cr & cr0_mask) >> cr_shift;
			break;
		}
		case OP_63_FCMPO:
		{
			u32 tmp_cr;
			u32 cr0_mask = 0xf0000000;
			u32 cr_shift = inst_get_field(inst, 6, 8) * 4;

			fpd_fcmpo(&vcpu->arch.fp.fpscr, &tmp_cr, fpr_a, fpr_b);
			cr &= ~(cr0_mask >> cr_shift);
			cr |= (cr & cr0_mask) >> cr_shift;
			break;
		}
		case OP_63_FNEG:
			fpd_fneg(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			break;
		case OP_63_FMR:
			*fpr_d = *fpr_b;
			break;
		case OP_63_FABS:
			fpd_fabs(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			break;
		case OP_63_FCPSGN:
			fpd_fcpsgn(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			break;
		case OP_63_FDIV:
			fpd_fdiv(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			break;
		case OP_63_FADD:
			fpd_fadd(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			break;
		case OP_63_FSUB:
			fpd_fsub(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_b);
			break;
		case OP_63_FCTIW:
			fpd_fctiw(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			break;
		case OP_63_FCTIWZ:
			fpd_fctiwz(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			break;
		case OP_63_FRSP:
			fpd_frsp(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			kvmppc_sync_qpr(vcpu, ax_rd);
			break;
		case OP_63_FRSQRTE:
		{
			double one = 1.0f;

			/* fD = sqrt(fB) */
			fpd_fsqrt(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_b);
			/* fD = 1.0f / fD */
			fpd_fdiv(&vcpu->arch.fp.fpscr, &cr, fpr_d, (u64*)&one, fpr_d);
			break;
		}
		}
		switch (inst_get_field(inst, 26, 30)) {
		case OP_63_FMUL:
			fpd_fmul(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c);
			break;
		case OP_63_FSEL:
			fpd_fsel(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			break;
		case OP_63_FMSUB:
			fpd_fmsub(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			break;
		case OP_63_FMADD:
			fpd_fmadd(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			break;
		case OP_63_FNMSUB:
			fpd_fnmsub(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			break;
		case OP_63_FNMADD:
			fpd_fnmadd(&vcpu->arch.fp.fpscr, &cr, fpr_d, fpr_a, fpr_c, fpr_b);
			break;
		}
		break;
	}

#ifdef DEBUG
	for (i = 0; i < ARRAY_SIZE(vcpu->arch.fp.fpr); i++) {
		u32 f;
		kvm_cvt_df(&VCPU_FPR(vcpu, i), &f);
		dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f);
	}
#endif

	if (rcomp)
		kvmppc_set_cr(vcpu, cr);

	preempt_enable();

	return emulated;
}
Exemple #16
0
asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern struct kernel_param __start___param[], __stop___param[];
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
	lock_kernel();
	boot_cpu_init();
	page_address_init();
	printk(KERN_NOTICE);
	printk(linux_banner);
	setup_arch(&command_line);
	setup_per_cpu_areas();
	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */

	/*
	 * Set up the scheduler prior starting any interrupts (such as the
	 * timer interrupt). Full topology setup happens at smp_init()
	 * time - but meanwhile we still have a functioning scheduler.
	 */
	sched_init();
	/*
	 * Disable preemption - early bootup scheduling is extremely
	 * fragile until we cpu_idle() for the first time.
	 */
	preempt_disable();
	build_all_zonelists();
	page_alloc_init();
	printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);
	parse_early_param();
	parse_args("Booting kernel", command_line, __start___param,
		   __stop___param - __start___param,
		   &unknown_bootoption);
	sort_main_extable();
	trap_init();
	rcu_init();
	init_IRQ();
	pidhash_init();
	init_timers();
	hrtimers_init();
	softirq_init();
	time_init();

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
	console_init();
	if (panic_later)
		panic(panic_later, panic_param);
	profile_init();
	local_irq_enable();
#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start && !initrd_below_start_ok &&
			initrd_start < min_low_pfn << PAGE_SHIFT) {
		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
		    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
		initrd_start = 0;
	}
#endif
	vfs_caches_init_early();
	cpuset_init_early();
	mem_init();
	kmem_cache_init();
	setup_per_cpu_pageset();
	numa_policy_init();
	if (late_time_init)
		late_time_init();
	calibrate_delay();
	pidmap_init();
	pgtable_cache_init();
	prio_tree_init();
	anon_vma_init();
#ifdef CONFIG_X86
	if (efi_enabled)
		efi_enter_virtual_mode();
#endif
	fork_init(num_physpages);
	proc_caches_init();
	buffer_init();
	unnamed_dev_init();
	key_init();
	security_init();
	vfs_caches_init(num_physpages);
	radix_tree_init();
	signals_init();
	/* rootfs populating might need page-writeback */
	page_writeback_init();
#ifdef CONFIG_PROC_FS
	proc_root_init();
#endif
	cpuset_init();

	check_bugs();

	acpi_early_init(); /* before LAPIC and SMP init */

	/* Do the rest non-__init'ed, we're now alive */
	rest_init();
}
Exemple #17
0
asmlinkage int vprintk(const char *fmt, va_list args)
{
    unsigned long flags;
    int printed_len;
    char *p;
    static char printk_buf[1024];
    static int log_level_unknown = 1;

    preempt_disable();
    if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
        /* If a crash is occurring during printk() on this CPU,
         * make sure we can't deadlock */
        zap_locks();

    /* This stops the holder of console_sem just where we want him */
    raw_local_irq_save(flags);
    lockdep_off();
    spin_lock(&logbuf_lock);
    printk_cpu = smp_processor_id();

    /* Emit the output into the temporary buffer */
    printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);

    /*
     * Copy the output into log_buf.  If the caller didn't provide
     * appropriate log level tags, we insert them here
     */
    for (p = printk_buf; *p; p++) {
        if (log_level_unknown) {
            /* log_level_unknown signals the start of a new line */
            if (printk_time) {
                int loglev_char;
                char tbuf[50], *tp;
                unsigned tlen;
                unsigned long long t;
                unsigned long nanosec_rem;

                /*
                 * force the log level token to be
                 * before the time output.
                 */
                if (p[0] == '<' && p[1] >='0' &&
                        p[1] <= '7' && p[2] == '>') {
                    loglev_char = p[1];
                    p += 3;
                    printed_len -= 3;
                } else {
                    loglev_char = default_message_loglevel
                                  + '0';
                }
                t = printk_clock();
                nanosec_rem = do_div(t, 1000000000);
                tlen = sprintf(tbuf,
                               "<%c>[%5lu.%06lu] ",
                               loglev_char,
                               (unsigned long)t,
                               nanosec_rem/1000);

                for (tp = tbuf; tp < tbuf + tlen; tp++)
                    emit_log_char(*tp);
                printed_len += tlen;
            } else {
                if (p[0] != '<' || p[1] < '0' ||
                        p[1] > '7' || p[2] != '>') {
                    emit_log_char('<');
                    emit_log_char(default_message_loglevel
                                  + '0');
                    emit_log_char('>');
                    printed_len += 3;
                }
            }
            log_level_unknown = 0;
            if (!*p)
                break;
        }
        emit_log_char(*p);
        if (*p == '\n')
            log_level_unknown = 1;
    }

    if (!down_trylock(&console_sem)) {
        /*
         * We own the drivers.  We can drop the spinlock and
         * let release_console_sem() print the text, maybe ...
         */
        console_locked = 1;
        printk_cpu = UINT_MAX;
        spin_unlock(&logbuf_lock);

        /*
         * Console drivers may assume that per-cpu resources have
         * been allocated. So unless they're explicitly marked as
         * being able to cope (CON_ANYTIME) don't call them until
         * this CPU is officially up.
         */
        if (cpu_online(smp_processor_id()) || have_callable_console()) {
            console_may_schedule = 0;
            release_console_sem();
        } else {
            /* Release by hand to avoid flushing the buffer. */
            console_locked = 0;
            up(&console_sem);
        }
        lockdep_on();
        raw_local_irq_restore(flags);
    } else {
        /*
         * Someone else owns the drivers.  We drop the spinlock, which
         * allows the semaphore holder to proceed and to call the
         * console drivers with the output which we just produced.
         */
        printk_cpu = UINT_MAX;
        spin_unlock(&logbuf_lock);
        lockdep_on();
        raw_local_irq_restore(flags);
    }

    preempt_enable();
    return printed_len;
}
Exemple #18
0
static inline void __radix__flush_tlb_range(struct mm_struct *mm,
					unsigned long start, unsigned long end,
					bool flush_all_sizes)

{
	unsigned long pid;
	unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift;
	unsigned long page_size = 1UL << page_shift;
	unsigned long nr_pages = (end - start) >> page_shift;
	bool local, full;

	pid = mm->context.id;
	if (unlikely(pid == MMU_NO_CONTEXT))
		return;

	preempt_disable();
	smp_mb(); /* see radix__flush_tlb_mm */
	if (!mm_is_thread_local(mm)) {
		if (unlikely(mm_is_singlethreaded(mm))) {
			if (end != TLB_FLUSH_ALL) {
				exit_flush_lazy_tlbs(mm);
				goto is_local;
			}
		}
		local = false;
		full = (end == TLB_FLUSH_ALL ||
				nr_pages > tlb_single_page_flush_ceiling);
	} else {
is_local:
		local = true;
		full = (end == TLB_FLUSH_ALL ||
				nr_pages > tlb_local_single_page_flush_ceiling);
	}

	if (full) {
		if (local) {
			_tlbiel_pid(pid, RIC_FLUSH_TLB);
		} else {
			if (mm_needs_flush_escalation(mm))
				_tlbie_pid(pid, RIC_FLUSH_ALL);
			else
				_tlbie_pid(pid, RIC_FLUSH_TLB);
		}
	} else {
		bool hflush = flush_all_sizes;
		bool gflush = flush_all_sizes;
		unsigned long hstart, hend;
		unsigned long gstart, gend;

		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
			hflush = true;

		if (hflush) {
			hstart = (start + PMD_SIZE - 1) & PMD_MASK;
			hend = end & PMD_MASK;
			if (hstart == hend)
				hflush = false;
		}

		if (gflush) {
			gstart = (start + PUD_SIZE - 1) & PUD_MASK;
			gend = end & PUD_MASK;
			if (gstart == gend)
				gflush = false;
		}

		asm volatile("ptesync": : :"memory");
		if (local) {
			__tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
			if (hflush)
				__tlbiel_va_range(hstart, hend, pid,
						PMD_SIZE, MMU_PAGE_2M);
			if (gflush)
				__tlbiel_va_range(gstart, gend, pid,
						PUD_SIZE, MMU_PAGE_1G);
			asm volatile("ptesync": : :"memory");
		} else {
			__tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
			if (hflush)
				__tlbie_va_range(hstart, hend, pid,
						PMD_SIZE, MMU_PAGE_2M);
			if (gflush)
				__tlbie_va_range(gstart, gend, pid,
						PUD_SIZE, MMU_PAGE_1G);
			fixup_tlbie();
			asm volatile("eieio; tlbsync; ptesync": : :"memory");
		}
	}
Exemple #19
0
static inline void _stp_ring_buffer_disable_cpu(void)
{
	preempt_disable();
	local_inc(&__get_cpu_var(_stp_cpu_disabled));
}
Exemple #20
0
/*
 * This is the secondary CPU boot entry.  We're using this CPUs
 * idle thread stack, but a set of temporary page tables.
 */
asmlinkage void __cpuinit secondary_start_kernel(void)
{
	struct mm_struct *mm = &init_mm;
	unsigned int cpu = smp_processor_id();
    aee_rr_rec_hoplug(cpu, 1, 0);

	printk("CPU%u: Booted secondary processor\n", cpu);

	/*
	 * All kernel threads share the same mm context; grab a
	 * reference and switch to it.
	 */
	atomic_inc(&mm->mm_count);
	current->active_mm = mm;
	cpumask_set_cpu(cpu, mm_cpumask(mm));
    aee_rr_rec_hoplug(cpu, 2, 0);

	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
    aee_rr_rec_hoplug(cpu, 3, 0);

	/*
	 * TTBR0 is only used for the identity mapping at this stage. Make it
	 * point to zero page to avoid speculatively fetching new entries.
	 */
	cpu_set_reserved_ttbr0();
    aee_rr_rec_hoplug(cpu, 4, 0);
	flush_tlb_all();
    aee_rr_rec_hoplug(cpu, 5, 0);

	preempt_disable();
    aee_rr_rec_hoplug(cpu, 6, 0);
	trace_hardirqs_off();
    aee_rr_rec_hoplug(cpu, 7, 0);

	if (cpu_ops[cpu]->cpu_postboot)
		cpu_ops[cpu]->cpu_postboot();
    aee_rr_rec_hoplug(cpu, 8, 0);

	/*
	 * Log the CPU info before it is marked online and might get read.
	 */
	cpuinfo_store_cpu();

	/*
	 * OK, now it's safe to let the boot CPU continue.  Wait for
	 * the CPU migration code to notice that the CPU is online
	 * before we continue.
	 */
	set_cpu_online(cpu, true);
    aee_rr_rec_hoplug(cpu, 9, 0);
	complete(&cpu_running);
    aee_rr_rec_hoplug(cpu, 10, 0);

	smp_store_cpu_info(cpu);
    aee_rr_rec_hoplug(cpu, 11, 0);

	/*
	 * Enable GIC and timers.
	 */
	notify_cpu_starting(cpu);
    aee_rr_rec_hoplug(cpu, 12, 0);

	local_dbg_enable();
    aee_rr_rec_hoplug(cpu, 13, 0);
	local_irq_enable();
    aee_rr_rec_hoplug(cpu, 14, 0);
	local_fiq_enable();
    aee_rr_rec_hoplug(cpu, 15, 0);

	/*
	 * OK, it's off to the idle thread for us
	 */
	cpu_startup_entry(CPUHP_ONLINE);
    aee_rr_rec_hoplug(cpu, 16, 0);
}
Exemple #21
0
asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern struct kernel_param __start___param[], __stop___param[];

	smp_setup_processor_id();

	/*
	 * Need to run as early as possible, to initialize the
	 * lockdep hash:
	 */
	lockdep_init();
	debug_objects_early_init();

	/*
	 * Set up the the initial canary ASAP:
	 */
	boot_init_stack_canary();

	cgroup_init_early();

	local_irq_disable();
	early_boot_irqs_off();
	early_init_irq_lock_class();

/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
	lock_kernel();
	tick_init();
	boot_cpu_init();
	page_address_init();
	printk(KERN_NOTICE "%s", linux_banner);
	setup_arch(&command_line);
	mm_init_owner(&init_mm, &init_task);
	setup_command_line(command_line);
	setup_nr_cpu_ids();
	setup_per_cpu_areas();
	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */

	build_all_zonelists();
	page_alloc_init();

	printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
	parse_early_param();
	parse_args("Booting kernel", static_command_line, __start___param,
		   __stop___param - __start___param,
		   &unknown_bootoption);
	/*
	 * These use large bootmem allocations and must precede
	 * kmem_cache_init()
	 */
	pidhash_init();
	vfs_caches_init_early();
	sort_main_extable();
	trap_init();
	mm_init();
	/*
	 * Set up the scheduler prior starting any interrupts (such as the
	 * timer interrupt). Full topology setup happens at smp_init()
	 * time - but meanwhile we still have a functioning scheduler.
	 */
	sched_init();
	/*
	 * Disable preemption - early bootup scheduling is extremely
	 * fragile until we cpu_idle() for the first time.
	 */
	preempt_disable();
	if (!irqs_disabled()) {
		printk(KERN_WARNING "start_kernel(): bug: interrupts were "
				"enabled *very* early, fixing it\n");
		local_irq_disable();
	}
	rcu_init();
	/* init some links before init_ISA_irqs() */
	early_irq_init();
	init_IRQ();
	prio_tree_init();
	init_timers();
	hrtimers_init();
	softirq_init();
	timekeeping_init();
	time_init();
	profile_init();
	if (!irqs_disabled())
		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
				 "enabled early\n");
	early_boot_irqs_on();
	local_irq_enable();

	/* Interrupts are enabled now so all GFP allocations are safe. */
	set_gfp_allowed_mask(__GFP_BITS_MASK);

	kmem_cache_init_late();

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
	console_init();
	if (panic_later)
		panic(panic_later, panic_param);

	lockdep_info();

	/*
	 * Need to run this when irqs are enabled, because it wants
	 * to self-test [hard/soft]-irqs on/off lock inversion bugs
	 * too:
	 */
	locking_selftest();

#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start && !initrd_below_start_ok &&
	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
		    "disabling it.\n",
		    page_to_pfn(virt_to_page((void *)initrd_start)),
		    min_low_pfn);
		initrd_start = 0;
	}
#endif
	page_cgroup_init();
	enable_debug_pagealloc();
	kmemtrace_init();
	kmemleak_init();
	debug_objects_mem_init();
	idr_init_cache();
	setup_per_cpu_pageset();
	numa_policy_init();
	if (late_time_init)
		late_time_init();
	sched_clock_init();
	calibrate_delay();
	pidmap_init();
	anon_vma_init();

#ifdef	CONFIG_KDB
	kdb_init();
	if (KDB_FLAG(EARLYKDB)) {
		KDB_ENTER();
	}
#endif	/* CONFIG_KDB */

#ifdef CONFIG_X86
	if (efi_enabled)
		efi_enter_virtual_mode();
#endif
	thread_info_cache_init();
	cred_init();
	fork_init(totalram_pages);
	proc_caches_init();
	buffer_init();
	key_init();
	security_init();
	vfs_caches_init(totalram_pages);
	radix_tree_init();
	signals_init();
	/* rootfs populating might need page-writeback */
	page_writeback_init();
#ifdef CONFIG_PROC_FS
	proc_root_init();
#endif
	cgroup_init();
	cpuset_init();
	taskstats_init_early();
	delayacct_init();

	check_bugs();

	acpi_early_init(); /* before LAPIC and SMP init */
	sfi_init_late();

	ftrace_init();

	/* Do the rest non-__init'ed, we're now alive */
	rest_init();
}
Exemple #22
0
/* Tasklet function for responding to timer interrupts */
void labx_ptp_timer_state_task(unsigned long data) {
  struct ptp_device *ptp = (struct ptp_device*) data;
  unsigned long flags;
  uint32_t newMaster;
  int i;
  int8_t reselect = 0;
  bool localMaster = true;

  uint32_t timerTicks = 0;

  preempt_disable();
  spin_lock_irqsave(&ptp->mutex, flags);
  timerTicks = ptp->timerTicks;
  ptp->timerTicks = 0;
  spin_unlock_irqrestore(&ptp->mutex, flags);
  preempt_enable();

  /* Update port roles whenever any port is flagged for reselect */
  for (i=0; i<ptp->numPorts; i++) {
    reselect |= ptp->ports[i].reselect;
  }
  if (reselect) {
    PortRoleSelection_StateMachine(ptp);
  }

  for (i=0; i<ptp->numPorts; i++) {
    if (ptp->ports[i].selectedRole == PTP_SLAVE) {
      localMaster = false;
      break;
    }
  }

  for (i=0; i<ptp->numPorts; i++) {
    switch(ptp->ports[i].selectedRole) {
    case PTP_MASTER:
      /* Send ANNOUNCE and SYNC messages at their rate for a master port */
      ptp->ports[i].announceCounter += timerTicks;
      if(ptp->ports[i].announceCounter >= ANNOUNCE_INTERVAL_TICKS(ptp, i)) {
        ptp->ports[i].announceCounter = 0;
        ptp->ports[i].newInfo = FALSE;
        transmit_announce(ptp, i);
      }

      ptp->ports[i].syncCounter += timerTicks;
      if(ptp->ports[i].syncCounter >= SYNC_INTERVAL_TICKS(ptp, i)) {
        ptp->ports[i].syncCounter = 0;

        /* If we are the grandmaster send sync messages. If we are not,
           we will forward sync/fup messages when we receive them from the GM. */
        if (localMaster) {
          /* Set the source port ID back to this node when we are the GM */
          memcpy(&ptp->ports[i].syncSourcePortId[0], &ptp->properties.grandmasterIdentity[0], 8);
          ptp->ports[i].syncSourcePortId[8] = (i+1) >> 8;
          ptp->ports[i].syncSourcePortId[9] = (i+1);

          transmit_sync(ptp, i);
          if (ptp->rtcChangesAllowed) {
            /* Periodically update the RTC to get update listeners to
               notice (IE when they are not coasting) */
            set_rtc_increment(ptp, &ptp->nominalIncrement);
          }
        }
      }
      break;

    case PTP_SLAVE:
    {
#ifdef DEBUG_INCREMENT
      uint32_t timeoutTicks = 8;
#endif

      /* Increment and test the announce receipt timeout counter */
      preempt_disable();
      spin_lock_irqsave(&ptp->mutex, flags);
      ptp->ports[i].announceTimeoutCounter += timerTicks;
      ptp->ports[i].syncTimeoutCounter += timerTicks;
      spin_unlock_irqrestore(&ptp->mutex, flags);
      preempt_enable();

#ifdef DEBUG_INCREMENT
      /* Periodically print out the increment we're using */
      if(++ptp->slaveDebugCounter >= timeoutTicks) {
        RtcIncrement increment;
        ptp->slaveDebugCounter = 0;

        get_rtc_increment(ptp, &increment);

        printk("%s: PTP increment: 0x%08X\n", ptp->name, (increment.mantissa << RTC_MANTISSA_SHIFT) | increment.fraction);
      }
#endif

      /* Transmit an ANNOUNCE immediately to speed things along if we've switched our
       * port to the master state.
       */
      if(ptp->ports[i].selectedRole == PTP_MASTER) {
        printk("%s: PTP master (port %d)\n", ptp->name, i);
        for (i=0; i<ptp->numPorts; i++) {
          ptp->ports[i].announceCounter    = 0;
          ptp->ports[i].announceSequenceId = 0x0000;
          transmit_announce(ptp, i);
        }
      } else {
        /* Still a slave; determine whether we are using the end-to-end or peer-to-peer
         * delay mechanism
         */
        if(ptp->properties.delayMechanism == PTP_DELAY_MECHANISM_E2E) {
          /* Increment the delay request counter and see if it's time to
           * send one to the master.
           */
          if(++ptp->ports[i].delayReqCounter >= (DELAY_REQ_INTERVAL / PTP_TIMER_TICK_MS)) {
            ptp->ports[i].delayReqCounter = 0;
            transmit_delay_request(ptp, i);
          }
        }
      } /* if(still a slave) */
    }
    break;

    default:
      /* "Passive"; do nothing */
      break;
    }
  }
Exemple #23
0
static int sys_vperfctr_control(struct vperfctr *perfctr,
				struct perfctr_struct_buf *argp,
				struct task_struct *tsk)
{
	struct vperfctr_control control;
	int err;
	unsigned int next_cstatus;
	unsigned int nrctrs, i;
	cpumask_t cpumask;

	if (!tsk)
		return -ESRCH;	/* attempt to update unlinked perfctr */

	err = perfctr_copy_from_user(&control, argp, &vperfctr_control_sdesc);
	if (err)
		return err;

	/* Step 1: Update the control but keep the counters disabled.
	   PREEMPT note: Preemption is disabled since we're updating
	   an active perfctr. */
	preempt_disable();
	if (IS_RUNNING(perfctr)) {
		if (tsk == current)
			vperfctr_suspend(perfctr);
		perfctr->cpu_state.cstatus = 0;
		vperfctr_clear_iresume_cstatus(perfctr);
	}
	perfctr->cpu_state.control = control.cpu_control;
	/* remote access note: perfctr_cpu_update_control() is ok */
	cpus_setall(cpumask);
#ifdef CONFIG_PERFCTR_CPUS_FORBIDDEN_MASK
	/* make a stopped vperfctr have an unconstrained cpumask */
	perfctr->cpumask = cpumask;
#endif
	err = perfctr_cpu_update_control(&perfctr->cpu_state, &cpumask);
	if (err < 0) {
		next_cstatus = 0;
	} else {
		next_cstatus = perfctr->cpu_state.cstatus;
		perfctr->cpu_state.cstatus = 0;
		perfctr->updater_tgid = current->tgid;
#ifdef CONFIG_PERFCTR_CPUS_FORBIDDEN_MASK
		perfctr->cpumask = cpumask;
#endif
	}
	preempt_enable_no_resched();

	if (!perfctr_cstatus_enabled(next_cstatus))
		return err;

#ifdef CONFIG_PERFCTR_CPUS_FORBIDDEN_MASK
	/* Step 2: Update the task's CPU affinity mask.
	   PREEMPT note: Preemption must be enabled for set_cpus_allowed(). */
	if (control.cpu_control.nractrs || control.cpu_control.nrictrs) {
		cpumask_t old_mask, new_mask;

		old_mask = tsk->cpus_allowed;
		cpus_and(new_mask, old_mask, cpumask);

		if (cpus_empty(new_mask))
			return -EINVAL;
		if (!cpus_equal(new_mask, old_mask))
			set_cpus_allowed(tsk, new_mask);
	}
#endif

	/* Step 3: Enable the counters with the new control and affinity.
	   PREEMPT note: Preemption is disabled since we're updating
	   an active perfctr. */
	preempt_disable();

	/* We had to enable preemption above for set_cpus_allowed() so we may
	   have lost a race with a concurrent update via the remote control
	   interface. If so then we must abort our update of this perfctr. */
	if (perfctr->updater_tgid != current->tgid) {
		printk(KERN_WARNING "perfctr: control update by task %d"
		       " was lost due to race with update by task %d\n",
		       current->tgid, perfctr->updater_tgid);
		err = -EBUSY;
	} else {
		/* XXX: validate si_signo? */
		perfctr->si_signo = control.si_signo;

		perfctr->cpu_state.cstatus = next_cstatus;

		if (!perfctr_cstatus_has_tsc(next_cstatus))
			perfctr->cpu_state.tsc_sum = 0;

		nrctrs = perfctr_cstatus_nrctrs(next_cstatus);
		for(i = 0; i < nrctrs; ++i)
			if (!(control.preserve & (1<<i)))
				perfctr->cpu_state.pmc[i].sum = 0;

		perfctr->flags = control.flags;

		if (tsk == current)
			vperfctr_resume(perfctr);
	}

	preempt_enable();
	return err;
}
int
trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array *tr)
{
	unsigned long save_max = tracing_max_latency;
	unsigned long count;
	int ret;

	/*
                                                          
                                                        
                                                   
                                                      
                                                    
                  
  */
	if (preempt_count()) {
		printk(KERN_CONT "can not test ... force ");
		return 0;
	}

	/*                   */
	ret = tracer_init(trace, tr);
	if (ret) {
		warn_failed_init_tracer(trace, ret);
		goto out_no_start;
	}

	/*                       */
	tracing_max_latency = 0;

	/*                                             */
	preempt_disable();
	local_irq_disable();
	udelay(100);
	preempt_enable();
	/*                                      */
	local_irq_enable();

	/*
                                                 
                                                     
                                                               
                                                        
  */
	trace->stop(tr);
	/*                   */
	tracing_stop();
	/*                          */
	ret = trace_test_buffer(tr, NULL);
	if (ret)
		goto out;

	ret = trace_test_buffer(&max_tr, &count);
	if (ret)
		goto out;

	if (!ret && !count) {
		printk(KERN_CONT ".. no entries found ..");
		ret = -1;
		goto out;
	}

	/*                                                     */
	tracing_max_latency = 0;
	tracing_start();
	trace->start(tr);

	preempt_disable();
	local_irq_disable();
	udelay(100);
	preempt_enable();
	/*                                      */
	local_irq_enable();

	trace->stop(tr);
	/*                   */
	tracing_stop();
	/*                          */
	ret = trace_test_buffer(tr, NULL);
	if (ret)
		goto out;

	ret = trace_test_buffer(&max_tr, &count);

	if (!ret && !count) {
		printk(KERN_CONT ".. no entries found ..");
		ret = -1;
		goto out;
	}

out:
	tracing_start();
out_no_start:
	trace->reset(tr);
	tracing_max_latency = save_max;

	return ret;
}
Exemple #25
0
asmlinkage int vprintk(const char *fmt, va_list args)
{
	unsigned long flags;
	int printed_len;
	char *p;
	static char printk_buf[1024];
	static int log_level_unknown = 1;

	preempt_disable();
	if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
		/* If a crash is occurring during printk() on this CPU,
		 * make sure we can't deadlock */
		zap_locks();

	/* This stops the holder of console_sem just where we want him */
	spin_lock_irqsave(&logbuf_lock, flags);
	printk_cpu = smp_processor_id();

	/* Emit the output into the temporary buffer */
	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);

#ifdef	CONFIG_DEBUG_LL
	printascii(printk_buf);
#endif

	/*
	 * Copy the output into log_buf.  If the caller didn't provide
	 * appropriate log level tags, we insert them here
	 */
	for (p = printk_buf; *p; p++) {
		if (log_level_unknown) {
                        /* log_level_unknown signals the start of a new line */
			if (printk_time) {
				int loglev_char;
				char tbuf[50], *tp;
				unsigned tlen;
				unsigned long long t;
				unsigned long nanosec_rem;

				/*
				 * force the log level token to be
				 * before the time output.
				 */
				if (p[0] == '<' && p[1] >='0' &&
				   p[1] <= '7' && p[2] == '>') {
					loglev_char = p[1];
					p += 3;
					printed_len += 3;
				} else {
					loglev_char = default_message_loglevel
						+ '0';
				}
				t = printk_clock();
				nanosec_rem = do_div(t, 1000000000);
				tlen = sprintf(tbuf,
						"<%c>[%5lu.%06lu] ",
						loglev_char,
						(unsigned long)t,
						nanosec_rem/1000);

				for (tp = tbuf; tp < tbuf + tlen; tp++)
					emit_log_char(*tp);
				printed_len += tlen - 3;
			} else {
				if (p[0] != '<' || p[1] < '0' ||
				   p[1] > '7' || p[2] != '>') {
					emit_log_char('<');
					emit_log_char(default_message_loglevel
						+ '0');
					emit_log_char('>');
				}
				printed_len += 3;
			}
			log_level_unknown = 0;
			if (!*p)
				break;
		}
		emit_log_char(*p);
		if (*p == '\n')
			log_level_unknown = 1;
	}

	if (!cpu_online(smp_processor_id())) {
		/*
		 * Some console drivers may assume that per-cpu resources have
		 * been allocated.  So don't allow them to be called by this
		 * CPU until it is officially up.  We shouldn't be calling into
		 * random console drivers on a CPU which doesn't exist yet..
		 */
		printk_cpu = UINT_MAX;
		spin_unlock_irqrestore(&logbuf_lock, flags);
		goto out;
	}
	if (!down_trylock(&console_sem)) {
		console_locked = 1;
		/*
		 * We own the drivers.  We can drop the spinlock and let
		 * release_console_sem() print the text
		 */
		printk_cpu = UINT_MAX;
		spin_unlock_irqrestore(&logbuf_lock, flags);
		console_may_schedule = 0;
		release_console_sem();
	} else {
		/*
		 * Someone else owns the drivers.  We drop the spinlock, which
		 * allows the semaphore holder to proceed and to call the
		 * console drivers with the output which we just produced.
		 */
		printk_cpu = UINT_MAX;
		spin_unlock_irqrestore(&logbuf_lock, flags);
	}
out:
	preempt_enable();
	return printed_len;
}
Exemple #26
0
int aed_get_process_bt(struct aee_process_bt *bt)
{
    int nr_cpus, err;
    struct bt_sync s;
    struct task_struct *task;
    int timeout_max = 500000;

    if (down_interruptible(&process_bt_sem) < 0) {
        return -ERESTARTSYS;
    }

    err = 0;
    if (bt->pid > 0) {
        task = find_task_by_vpid(bt->pid);
        if (task == NULL) {
            err = -EINVAL;
            goto exit;
        }
    } else {
        err = -EINVAL;
        goto exit;
    }

    err = mutex_lock_killable(&task->signal->cred_guard_mutex);
    if (err)
        goto exit;
    if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
        mutex_unlock(&task->signal->cred_guard_mutex);
        err = -EPERM;
        goto exit;
    }

    get_online_cpus();
    preempt_disable();

    nr_cpus = num_online_cpus();
    atomic_set(&s.cpus_report, nr_cpus - 1);
    atomic_set(&s.cpus_lock, 1);

    smp_call_function(per_cpu_get_bt, &s, 0);

    while (atomic_read(&s.cpus_report) != 0) {
        if (timeout_max-- > 0) {
            udelay(1);
        } else {
            break;
        }
    }

    aed_get_bt(task, bt);

    atomic_set(&s.cpus_report, nr_cpus - 1);
    atomic_set(&s.cpus_lock, 0);
    timeout_max = 500000;
    while (atomic_read(&s.cpus_report) != 0) {
        if (timeout_max-- > 0) {
            udelay(1);
        } else {
            break;
        }
    }

    preempt_enable();
    put_online_cpus();

    mutex_unlock(&task->signal->cred_guard_mutex);

exit:
    up(&process_bt_sem);
    return err;

}
Exemple #27
0
int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
{
	struct address_space *swap_space;
	struct file *swap_storage;
	struct page *from_page;
	struct page *to_page;
	void *from_virtual;
	void *to_virtual;
	int i;
	int ret = -ENOMEM;

	BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
	BUG_ON(ttm->caching_state != tt_cached);

	if (!persistent_swap_storage) {
		swap_storage = shmem_file_setup("ttm swap",
						ttm->num_pages << PAGE_SHIFT,
						0);
		if (unlikely(IS_ERR(swap_storage))) {
			printk(KERN_ERR "Failed allocating swap storage.\n");
			return PTR_ERR(swap_storage);
		}
	} else
		swap_storage = persistent_swap_storage;

	swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;

	for (i = 0; i < ttm->num_pages; ++i) {
		from_page = ttm->pages[i];
		if (unlikely(from_page == NULL))
			continue;
		to_page = shmem_read_mapping_page(swap_space, i);
		if (unlikely(IS_ERR(to_page))) {
			ret = PTR_ERR(to_page);
			goto out_err;
		}
		preempt_disable();
		from_virtual = kmap_atomic(from_page);
		to_virtual = kmap_atomic(to_page);
		memcpy(to_virtual, from_virtual, PAGE_SIZE);
		kunmap_atomic(to_virtual);
		kunmap_atomic(from_virtual);
		preempt_enable();
		set_page_dirty(to_page);
		mark_page_accessed(to_page);
		page_cache_release(to_page);
	}

	ttm->bdev->driver->ttm_tt_unpopulate(ttm);
	ttm->swap_storage = swap_storage;
	ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
	if (persistent_swap_storage)
		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;

	return 0;
out_err:
	if (!persistent_swap_storage)
		fput(swap_storage);

	return ret;
}
Exemple #28
0
static int __kprobes kprobe_handler(struct pt_regs *regs)
{
	struct kprobe *p;
	void *addr = (void *) regs->tpc;
	int ret = 0;
	struct kprobe_ctlblk *kcb;

	/*
	 * We don't want to be preempted for the entire
	 * duration of kprobe processing
	 */
	preempt_disable();
	kcb = get_kprobe_ctlblk();

	if (kprobe_running()) {
		p = get_kprobe(addr);
		if (p) {
			if (kcb->kprobe_status == KPROBE_HIT_SS) {
				regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
					kcb->kprobe_orig_tstate_pil);
				goto no_kprobe;
			}
			/* We have reentered the kprobe_handler(), since
			 * another probe was hit while within the handler.
			 * We here save the original kprobes variables and
			 * just single step on the instruction of the new probe
			 * without calling any user handlers.
			 */
			save_previous_kprobe(kcb);
			set_current_kprobe(p, regs, kcb);
			kprobes_inc_nmissed_count(p);
			kcb->kprobe_status = KPROBE_REENTER;
			prepare_singlestep(p, regs, kcb);
			return 1;
		} else {
			if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
			/* The breakpoint instruction was removed by
			 * another cpu right after we hit, no further
			 * handling of this interrupt is appropriate
			 */
				ret = 1;
				goto no_kprobe;
			}
			p = __get_cpu_var(current_kprobe);
			if (p->break_handler && p->break_handler(p, regs))
				goto ss_probe;
		}
		goto no_kprobe;
	}

	p = get_kprobe(addr);
	if (!p) {
		if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
			/*
			 * The breakpoint instruction was removed right
			 * after we hit it.  Another cpu has removed
			 * either a probepoint or a debugger breakpoint
			 * at this address.  In either case, no further
			 * handling of this interrupt is appropriate.
			 */
			ret = 1;
		}
		/* Not one of ours: let kernel handle it */
		goto no_kprobe;
	}

	set_current_kprobe(p, regs, kcb);
	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
	if (p->pre_handler && p->pre_handler(p, regs))
		return 1;

ss_probe:
	prepare_singlestep(p, regs, kcb);
	kcb->kprobe_status = KPROBE_HIT_SS;
	return 1;

no_kprobe:
	preempt_enable_no_resched();
	return ret;
}
static int mcsdl_download(const UINT8 *pBianry, const UINT16 unLength,
		INT8 IdxNum)
{
	int nRet;

	//---------------------------------
	// Check Binary Size
	//---------------------------------
	if (unLength >= MELFAS_FIRMWARE_MAX_SIZE)
	{

		nRet = MCSDL_RET_PROGRAM_SIZE_IS_WRONG;
		goto MCSDL_DOWNLOAD_FINISH;
	}

#if MELFAS_ENABLE_DBG_PROGRESS_PRINT
	printk(" - Starting download...\n");
#endif

	//---------------------------------
	// Make it ready
	//---------------------------------
#if MELFAS_ENABLE_DBG_PROGRESS_PRINT
	printk(" > Ready\n");
#endif

	mcsdl_set_ready();

	//---------------------------------
	// Erase Flash
	//---------------------------------
#if MELFAS_ENABLE_DBG_PROGRESS_PRINT
	printk(" > Erase\n");
#endif

	preempt_disable();
	nRet = mcsdl_erase_flash(IdxNum);
	preempt_enable();

	if (nRet != MCSDL_RET_SUCCESS)
		goto MCSDL_DOWNLOAD_FINISH;

	//---------------------------------
	// Program Flash
	//---------------------------------
#if MELFAS_ENABLE_DBG_PROGRESS_PRINT
	printk(" > Program   ");
#endif

	preempt_disable();
	nRet = mcsdl_program_flash((UINT8*) pBianry, (UINT16) unLength, IdxNum);
	preempt_enable();
	
	if (nRet != MCSDL_RET_SUCCESS)
		goto MCSDL_DOWNLOAD_FINISH;
	//---------------------------------
	// Verify flash
	//---------------------------------

#if MELFAS_ENABLE_DBG_PROGRESS_PRINT
	printk(" > Verify    ");
#endif

	preempt_disable();
	nRet = mcsdl_verify_flash((UINT8*) pBianry, (UINT16) unLength, IdxNum);
	preempt_enable();

	if (nRet != MCSDL_RET_SUCCESS)
		goto MCSDL_DOWNLOAD_FINISH;

	nRet = MCSDL_RET_SUCCESS;

	MCSDL_DOWNLOAD_FINISH:

#if MELFAS_ENABLE_DBG_PRINT
	mcsdl_print_result( nRet ); // Show result
#endif

#if MELFAS_ENABLE_DBG_PROGRESS_PRINT
	printk(" > Rebooting\n");
	printk(" - Fin.\n\n");
#endif

	mcsdl_reboot_mcs();

	return nRet;
}
Exemple #30
0
void __lockfunc _write_lock_bh(rwlock_t *lock)
{
	local_bh_disable();
	preempt_disable();
	_raw_write_lock(lock);
}