示例#1
0
void
ia32_load_state (struct task_struct *t)
{
	unsigned long eflag, fsr, fcr, fir, fdr, tssd;
	struct pt_regs *regs = task_pt_regs(t);

	eflag = t->thread.eflag;
	fsr = t->thread.fsr;
	fcr = t->thread.fcr;
	fir = t->thread.fir;
	fdr = t->thread.fdr;
	tssd = load_desc(_TSS);					/* TSSD */

	ia64_setreg(_IA64_REG_AR_EFLAG, eflag);
	ia64_setreg(_IA64_REG_AR_FSR, fsr);
	ia64_setreg(_IA64_REG_AR_FCR, fcr);
	ia64_setreg(_IA64_REG_AR_FIR, fir);
	ia64_setreg(_IA64_REG_AR_FDR, fdr);
	current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
	current->thread.old_k1 = ia64_get_kr(IA64_KR_TSSD);
	ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
	ia64_set_kr(IA64_KR_TSSD, tssd);

	regs->r17 = (_TSS << 48) | (_LDT << 32) | (__u32) regs->r17;
	regs->r30 = load_desc(_LDT);				/* LDTD */
	load_TLS(&t->thread, smp_processor_id());
}
示例#2
0
void
ia32_save_state (struct task_struct *t)
{
	t->thread.eflag = ia64_getreg(_IA64_REG_AR_EFLAG);
	t->thread.fsr   = ia64_getreg(_IA64_REG_AR_FSR);
	t->thread.fcr   = ia64_getreg(_IA64_REG_AR_FCR);
	t->thread.fir   = ia64_getreg(_IA64_REG_AR_FIR);
	t->thread.fdr   = ia64_getreg(_IA64_REG_AR_FDR);
	ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob);
	ia64_set_kr(IA64_KR_TSSD, t->thread.old_k1);
}
示例#3
0
static void __init
io_port_init (void)
{
	extern unsigned long ia64_iobase;
	unsigned long phys_iobase;

	/*
	 *  Set `iobase' to the appropriate address in region 6 (uncached access range).
	 *
	 *  The EFI memory map is the "preferred" location to get the I/O port space base,
	 *  rather the relying on AR.KR0. This should become more clear in future SAL
	 *  specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is
	 *  found in the memory map.
	 */
	phys_iobase = efi_get_iobase();
	if (phys_iobase)
		/* set AR.KR0 since this is all we use it for anyway */
		ia64_set_kr(IA64_KR_IO_BASE, phys_iobase);
	else {
		phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
		printk(KERN_INFO "No I/O port range found in EFI memory map, falling back "
		       "to AR.KR0\n");
		printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase);
	}
	ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);

	/* setup legacy IO port space */
	io_space[0].mmio_base = ia64_iobase;
	io_space[0].sparse = 1;
	num_io_spaces = 1;
}
示例#4
0
static void __init
io_port_init (void)
{
	unsigned long phys_iobase;

	/*
	 * Set `iobase' based on the EFI memory map or, failing that, the
	 * value firmware left in ar.k0.
	 *
	 * Note that in ia32 mode, IN/OUT instructions use ar.k0 to compute
	 * the port's virtual address, so ia32_load_state() loads it with a
	 * user virtual address.  But in ia64 mode, glibc uses the
	 * *physical* address in ar.k0 to mmap the appropriate area from
	 * /dev/mem, and the inX()/outX() interfaces use MMIO.  In both
	 * cases, user-mode can only use the legacy 0-64K I/O port space.
	 *
	 * ar.k0 is not involved in kernel I/O port accesses, which can use
	 * any of the I/O port spaces and are done via MMIO using the
	 * virtual mmio_base from the appropriate io_space[].
	 */
	phys_iobase = efi_get_iobase();
	if (!phys_iobase) {
		phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
		printk(KERN_INFO "No I/O port range found in EFI memory map, "
			"falling back to AR.KR0 (0x%lx)\n", phys_iobase);
	}
	ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));

	/* setup legacy IO port space */
	io_space[0].mmio_base = ia64_iobase;
	io_space[0].sparse = 1;
	num_io_spaces = 1;
}
示例#5
0
static void __init
smp_callin (void)
{
	int cpuid, phys_id;
	extern void ia64_init_itm(void);

#ifdef CONFIG_PERFMON
	extern void pfm_init_percpu(void);
#endif

	cpuid = smp_processor_id();
	phys_id = hard_smp_processor_id();

	if (test_and_set_bit(cpuid, &cpu_online_map)) {
		printk("huh, phys CPU#0x%x, CPU#0x%x already present??\n", phys_id, cpuid);
		BUG();
	}

	smp_setup_percpu_timer();

	/*
	 * Synchronize the ITC with the BP
	 */
	Dprintk("Going to syncup ITC with BP.\n");

	ia64_sync_itc(0);
	/*
	 * Get our bogomips.
	 */
	ia64_init_itm();

	/*
	 * Set I/O port base per CPU
	 */
	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));

#ifdef CONFIG_IA64_MCA
	ia64_mca_cmc_vector_setup();	/* Setup vector on AP & enable */
	ia64_mca_check_errors();	/* For post-failure MCA error logging */
#endif

#ifdef CONFIG_PERFMON
	pfm_init_percpu();
#endif

	local_irq_enable();
	calibrate_delay();
	local_cpu_data->loops_per_jiffy = loops_per_jiffy;
	/*
	 * Allow the master to continue.
	 */
	set_bit(cpuid, &cpu_callin_map);
	Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid);
}
示例#6
0
/*
 * Activate a secondary processor.  head.S calls this.
 */
int __devinit
start_secondary (void *unused)
{
	/* Early console may use I/O ports */
	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
	Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
	efi_map_pal_code();
	cpu_init();
	smp_callin();

	cpu_idle();
	return 0;
}
/*
 * Activate a secondary processor.  head.S calls this.
 */
int __cpuinit
start_secondary (void *unused)
{
	/* Early console may use I/O ports */
	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
#ifndef CONFIG_PRINTK_TIME
	Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
#endif
	efi_map_pal_code();
	cpu_init();
	preempt_disable();
	smp_callin();

	cpu_idle();
	return 0;
}
示例#8
0
文件: smpboot.c 项目: amodj/Utopia
/*
 * Activate a secondary processor.  head.S calls this.
 */
int __devinit
start_secondary (void *unused)
{
	/* Early console may use I/O ports */
	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
#ifndef XEN
	Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
	efi_map_pal_code();
#endif
	cpu_init();
	smp_callin();

#ifdef XEN
	if (vmx_enabled)
		vmx_init_env(0, 0);

	startup_cpu_idle_loop();
#else
	cpu_idle();
#endif
	return 0;
}
示例#9
0
/*
 * cpu_init() initializes state that is per-CPU.  This function acts
 * as a 'CPU state barrier', nothing should get across.
 */
void
cpu_init (void)
{
	extern void __devinit ia64_mmu_init (void *);
	unsigned long num_phys_stacked;
	pal_vm_info_2_u_t vmi;
	unsigned int max_ctx;
	struct cpuinfo_ia64 *cpu_info;
	void *cpu_data;

	cpu_data = per_cpu_init();

	get_max_cacheline_size();

	/*
	 * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
	 * ia64_mmu_init() yet.  And we can't call ia64_mmu_init() first because it
	 * depends on the data returned by identify_cpu().  We break the dependency by
	 * accessing cpu_data() through the canonical per-CPU address.
	 */
	cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(cpu_info) - __per_cpu_start);
	identify_cpu(cpu_info);

#ifdef CONFIG_MCKINLEY
	{
#		define FEATURE_SET 16
		struct ia64_pal_retval iprv;

		if (cpu_info->family == 0x1f) {
			PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, FEATURE_SET, 0);
			if ((iprv.status == 0) && (iprv.v0 & 0x80) && (iprv.v2 & 0x80))
				PAL_CALL_PHYS(iprv, PAL_PROC_SET_FEATURES,
				              (iprv.v1 | 0x80), FEATURE_SET, 0);
		}
	}
#endif

	/* Clear the stack memory reserved for pt_regs: */
	memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));

	ia64_set_kr(IA64_KR_FPU_OWNER, 0);

	/*
	 * Initialize default control register to defer all speculative faults.  The
	 * kernel MUST NOT depend on a particular setting of these bits (in other words,
	 * the kernel must have recovery code for all speculative accesses).  Turn on
	 * dcr.lc as per recommendation by the architecture team.  Most IA-32 apps
	 * shouldn't be affected by this (moral: keep your ia32 locks aligned and you'll
	 * be fine).
	 */
	ia64_setreg(_IA64_REG_CR_DCR,  (  IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
					| IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC));
	atomic_inc(&init_mm.mm_count);
	current->active_mm = &init_mm;
	if (current->mm)
		BUG();

	ia64_mmu_init(ia64_imva(cpu_data));

#ifdef CONFIG_IA32_SUPPORT
	ia32_cpu_init();
#endif

	/* Clear ITC to eliminiate sched_clock() overflows in human time.  */
	ia64_set_itc(0);

	/* disable all local interrupt sources: */
	ia64_set_itv(1 << 16);
	ia64_set_lrr0(1 << 16);
	ia64_set_lrr1(1 << 16);
	ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
	ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);

	/* clear TPR & XTP to enable all interrupt classes: */
	ia64_setreg(_IA64_REG_CR_TPR, 0);
#ifdef CONFIG_SMP
	normal_xtp();
#endif

	/* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */
	if (ia64_pal_vm_summary(NULL, &vmi) == 0)
		max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1;
	else {
		printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n");
		max_ctx = (1U << 15) - 1;	/* use architected minimum */
	}
	while (max_ctx < ia64_ctx.max_ctx) {
		unsigned int old = ia64_ctx.max_ctx;
		if (cmpxchg(&ia64_ctx.max_ctx, old, max_ctx) == old)
			break;
	}

	if (ia64_pal_rse_info(&num_phys_stacked, NULL) != 0) {
		printk(KERN_WARNING "cpu_init: PAL RSE info failed; assuming 96 physical "
		       "stacked regs\n");
		num_phys_stacked = 96;
	}
	/* size of physical stacked register partition plus 8 bytes: */
	__get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8;
	platform_cpu_init();
}
示例#10
0
文件: setup.c 项目: sarnobat/knoppix
void __init
setup_arch (char **cmdline_p)
{
	extern unsigned long ia64_iobase;
	unsigned long phys_iobase;

	unw_init();

	ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);

	*cmdline_p = __va(ia64_boot_param->command_line);
	strlcpy(saved_command_line, *cmdline_p, sizeof(saved_command_line));

	efi_init();

#ifdef CONFIG_ACPI_BOOT
	/* Initialize the ACPI boot-time table parser */
	acpi_table_init();
# ifdef CONFIG_ACPI_NUMA
	acpi_numa_init();
# endif
#else
# ifdef CONFIG_SMP
	smp_build_cpu_map();	/* happens, e.g., with the Ski simulator */
# endif
#endif /* CONFIG_APCI_BOOT */

	find_memory();

	/* process SAL system table: */
	ia64_sal_init(efi.sal_systab);

#ifdef CONFIG_IA64_GENERIC
	machvec_init(acpi_get_sysname());
#endif

	/*
	 *  Set `iobase' to the appropriate address in region 6 (uncached access range).
	 *
	 *  The EFI memory map is the "preferred" location to get the I/O port space base,
	 *  rather the relying on AR.KR0. This should become more clear in future SAL
	 *  specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is
	 *  found in the memory map.
	 */
	phys_iobase = efi_get_iobase();
	if (phys_iobase)
		/* set AR.KR0 since this is all we use it for anyway */
		ia64_set_kr(IA64_KR_IO_BASE, phys_iobase);
	else {
		phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
		printk(KERN_INFO "No I/O port range found in EFI memory map, falling back "
		       "to AR.KR0\n");
		printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase);
	}
	ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);

	/* setup legacy IO port space */
	io_space[0].mmio_base = ia64_iobase;
	io_space[0].sparse = 1;
	num_io_spaces = 1;

#ifdef CONFIG_SMP
	cpu_physical_id(0) = hard_smp_processor_id();
#endif

	cpu_init();	/* initialize the bootstrap CPU */

#ifdef CONFIG_ACPI_BOOT
	acpi_boot_init();
#endif
#ifdef CONFIG_SERIAL_8250_HCDP
	if (efi.hcdp) {
		void setup_serial_hcdp(void *);
		setup_serial_hcdp(efi.hcdp);
	}
#endif
#ifdef CONFIG_SERIAL_8250_CONSOLE
	/*
	 * Without HCDP, we won't discover any serial ports until the serial driver looks
	 * in the ACPI namespace.  If ACPI claims there are some legacy devices, register
	 * the legacy COM ports so serial console works earlier.  This is slightly dangerous
	 * because we don't *really* know whether there's anything there, but we hope that
	 * all new boxes will implement HCDP.
	 */
	{
		extern unsigned char acpi_legacy_devices;
		if (!efi.hcdp && acpi_legacy_devices)
			setup_serial_legacy();
	}
#endif

#ifdef CONFIG_VT
# if defined(CONFIG_DUMMY_CONSOLE)
	conswitchp = &dummy_con;
# endif
# if defined(CONFIG_VGA_CONSOLE)
	/*
	 * Non-legacy systems may route legacy VGA MMIO range to system
	 * memory.  vga_con probes the MMIO hole, so memory looks like
	 * a VGA device to it.  The EFI memory map can tell us if it's
	 * memory so we can avoid this problem.
	 */
	if (efi_mem_type(0xA0000) != EFI_CONVENTIONAL_MEMORY)
		conswitchp = &vga_con;
# endif
#endif

#ifdef CONFIG_IA64_MCA
	/* enable IA-64 Machine Check Abort Handling */
	ia64_mca_init();
#endif

	platform_setup(cmdline_p);
	paging_init();
}