Commit 1b374e4d authored by Suresh Siddha's avatar Suresh Siddha Committed by Ingo Molnar
Browse files

x64, x2apic/intr-remap: basic apic ops support



Introduce basic apic operations which handle the apic programming. This
will be used later to introduce another specific operations for x2apic.

For the perfomance critial accesses like IPI's, EOI etc, we use the
native operations as they are already referenced by different
indirections like genapic, irq_chip etc.

64bit Paravirt ops can also define their apic operations accordingly.

Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Cc: akpm@linux-foundation.org
Cc: arjan@linux.intel.com
Cc: andi@firstfloor.org
Cc: ebiederm@xmission.com
Cc: jbarnes@virtuousgeek.org
Cc: steiner@sgi.com
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 2d7a66d0
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -145,6 +145,12 @@ static int modern_apic(void)
	return lapic_get_version() >= 0x14;
	return lapic_get_version() >= 0x14;
}
}


void apic_icr_write(u32 low, u32 id)
{
	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id));
	apic_write_around(APIC_ICR, low);
}

void apic_wait_icr_idle(void)
void apic_wait_icr_idle(void)
{
{
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
+32 −2
Original line number Original line Diff line number Diff line
@@ -119,13 +119,13 @@ static int modern_apic(void)
	return lapic_get_version() >= 0x14;
	return lapic_get_version() >= 0x14;
}
}


void apic_wait_icr_idle(void)
void xapic_wait_icr_idle(void)
{
{
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
	while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
		cpu_relax();
		cpu_relax();
}
}


u32 safe_apic_wait_icr_idle(void)
u32 safe_xapic_wait_icr_idle(void)
{
{
	u32 send_status;
	u32 send_status;
	int timeout;
	int timeout;
@@ -141,6 +141,36 @@ u32 safe_apic_wait_icr_idle(void)
	return send_status;
	return send_status;
}
}


void xapic_icr_write(u32 low, u32 id)
{
	apic_write(APIC_ICR2, id << 24);
	apic_write(APIC_ICR, low);
}

u64 xapic_icr_read(void)
{
	u32 icr1, icr2;

	icr2 = apic_read(APIC_ICR2);
	icr1 = apic_read(APIC_ICR);

	return (icr1 | ((u64)icr2 << 32));
}

static struct apic_ops xapic_ops = {
	.read = native_apic_mem_read,
	.write = native_apic_mem_write,
	.write_atomic = native_apic_mem_write_atomic,
	.icr_read = xapic_icr_read,
	.icr_write = xapic_icr_write,
	.wait_icr_idle = xapic_wait_icr_idle,
	.safe_wait_icr_idle = safe_xapic_wait_icr_idle,
};

struct apic_ops __read_mostly *apic_ops = &xapic_ops;

EXPORT_SYMBOL_GPL(apic_ops);

/**
/**
 * enable_NMI_through_LVT0 - enable NMI through local vector table 0
 * enable_NMI_through_LVT0 - enable NMI through local vector table 0
 */
 */
+4 −4
Original line number Original line Diff line number Diff line
@@ -1157,6 +1157,7 @@ static __apicdebuginit void print_APIC_bitfield (int base)
void __apicdebuginit print_local_APIC(void * dummy)
void __apicdebuginit print_local_APIC(void * dummy)
{
{
	unsigned int v, ver, maxlvt;
	unsigned int v, ver, maxlvt;
	unsigned long icr;


	if (apic_verbosity == APIC_QUIET)
	if (apic_verbosity == APIC_QUIET)
		return;
		return;
@@ -1200,10 +1201,9 @@ void __apicdebuginit print_local_APIC(void * dummy)
	v = apic_read(APIC_ESR);
	v = apic_read(APIC_ESR);
	printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
	printk(KERN_DEBUG "... APIC ESR: %08x\n", v);


	v = apic_read(APIC_ICR);
	icr = apic_icr_read();
	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
	printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
	v = apic_read(APIC_ICR2);
	printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);


	v = apic_read(APIC_LVTT);
	v = apic_read(APIC_LVTT);
	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
+5 −3
Original line number Original line Diff line number Diff line
@@ -360,9 +360,11 @@ struct pv_cpu_ops pv_cpu_ops = {


struct pv_apic_ops pv_apic_ops = {
struct pv_apic_ops pv_apic_ops = {
#ifdef CONFIG_X86_LOCAL_APIC
#ifdef CONFIG_X86_LOCAL_APIC
	.apic_write = native_apic_write,
#ifnded CONFIG_X86_64
	.apic_write_atomic = native_apic_write_atomic,
	.apic_write = native_apic_mem_write,
	.apic_read = native_apic_read,
	.apic_write_atomic = native_apic_mem_write_atomic,
	.apic_read = native_apic_mem_read,
#endif
	.setup_boot_clock = setup_boot_APIC_clock,
	.setup_boot_clock = setup_boot_APIC_clock,
	.setup_secondary_clock = setup_secondary_APIC_clock,
	.setup_secondary_clock = setup_secondary_APIC_clock,
	.startup_ipi_hook = paravirt_nop,
	.startup_ipi_hook = paravirt_nop,
+11 −17
Original line number Original line Diff line number Diff line
@@ -123,7 +123,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);


static atomic_t init_deasserted;
static atomic_t init_deasserted;


static int boot_cpu_logical_apicid;


/* representing cpus for which sibling maps can be computed */
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
static cpumask_t cpu_sibling_setup_map;
@@ -165,6 +164,8 @@ static void unmap_cpu_to_node(int cpu)
#endif
#endif


#ifdef CONFIG_X86_32
#ifdef CONFIG_X86_32
static int boot_cpu_logical_apicid;

u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
					{ [0 ... NR_CPUS-1] = BAD_APICID };
					{ [0 ... NR_CPUS-1] = BAD_APICID };


@@ -546,8 +547,7 @@ static inline void __inquire_remote_apic(int apicid)
			printk(KERN_CONT
			printk(KERN_CONT
			       "a previous APIC delivery may have failed\n");
			       "a previous APIC delivery may have failed\n");


		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
		apic_icr_write(APIC_DM_REMRD | regs[i], apicid);
		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);


		timeout = 0;
		timeout = 0;
		do {
		do {
@@ -579,11 +579,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
	int maxlvt;
	int maxlvt;


	/* Target chip */
	/* Target chip */
	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));

	/* Boot on the stack */
	/* Boot on the stack */
	/* Kick the second */
	/* Kick the second */
	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
	apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid);


	Dprintk("Waiting for send to finish...\n");
	Dprintk("Waiting for send to finish...\n");
	send_status = safe_apic_wait_icr_idle();
	send_status = safe_apic_wait_icr_idle();
@@ -639,13 +637,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
	/*
	/*
	 * Turn INIT on target chip
	 * Turn INIT on target chip
	 */
	 */
	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));

	/*
	/*
	 * Send IPI
	 * Send IPI
	 */
	 */
	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
	apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
				| APIC_DM_INIT);
		       phys_apicid);


	Dprintk("Waiting for send to finish...\n");
	Dprintk("Waiting for send to finish...\n");
	send_status = safe_apic_wait_icr_idle();
	send_status = safe_apic_wait_icr_idle();
@@ -655,10 +651,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
	Dprintk("Deasserting INIT.\n");
	Dprintk("Deasserting INIT.\n");


	/* Target chip */
	/* Target chip */
	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));

	/* Send IPI */
	/* Send IPI */
	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
	apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);


	Dprintk("Waiting for send to finish...\n");
	Dprintk("Waiting for send to finish...\n");
	send_status = safe_apic_wait_icr_idle();
	send_status = safe_apic_wait_icr_idle();
@@ -703,12 +697,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
		 */
		 */


		/* Target chip */
		/* Target chip */
		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));

		/* Boot on the stack */
		/* Boot on the stack */
		/* Kick the second */
		/* Kick the second */
		apic_write_around(APIC_ICR, APIC_DM_STARTUP
		apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12),
					| (start_eip >> 12));
			       phys_apicid);


		/*
		/*
		 * Give the other CPU some time to accept the IPI.
		 * Give the other CPU some time to accept the IPI.
@@ -1147,7 +1139,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
	 * Setup boot CPU information
	 * Setup boot CPU information
	 */
	 */
	smp_store_cpu_info(0); /* Final full version of the data */
	smp_store_cpu_info(0); /* Final full version of the data */
#ifdef CONFIG_X86_32
	boot_cpu_logical_apicid = logical_smp_processor_id();
	boot_cpu_logical_apicid = logical_smp_processor_id();
#endif
	current_thread_info()->cpu = 0;  /* needed? */
	current_thread_info()->cpu = 0;  /* needed? */
	set_cpu_sibling_map(0);
	set_cpu_sibling_map(0);


Loading