summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-10-21 06:39:40 +0000
committerkmacy <kmacy@FreeBSD.org>2008-10-21 06:39:40 +0000
commit48c93950a2e011e3403cff8595a5c84ca10c40fd (patch)
tree0bd49e2523b1f807610364194cb73a261b8d6e26
parent84e725f1e7c12b4a710346250c985a5864f4f87f (diff)
downloadFreeBSD-src-48c93950a2e011e3403cff8595a5c84ca10c40fd.zip
FreeBSD-src-48c93950a2e011e3403cff8595a5c84ca10c40fd.tar.gz
Implement infrastructure for gluing i386 ipi functions in to xen's infrastructure
-rw-r--r--sys/i386/xen/exception.s2
-rw-r--r--sys/i386/xen/mp_machdep.c178
2 files changed, 151 insertions, 29 deletions
diff --git a/sys/i386/xen/exception.s b/sys/i386/xen/exception.s
index ef32be9..cc31884 100644
--- a/sys/i386/xen/exception.s
+++ b/sys/i386/xen/exception.s
@@ -184,14 +184,12 @@ call_evtchn_upcall:
hypervisor_callback_pending:
DISABLE_INTERRUPTS(%esi) /* cli */
jmp 10b
-
/*
* alltraps entry point. Interrupts are enabled if this was a trap
* gate (TGT), else disabled if this was an interrupt gate (IGT).
* Note that int0x80_syscall is a trap gate. Only page faults
* use an interrupt gate.
*/
-
SUPERALIGN_TEXT
.globl alltraps
.type alltraps,@function
diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c
index 945ae69..10862b5 100644
--- a/sys/i386/xen/mp_machdep.c
+++ b/sys/i386/xen/mp_machdep.c
@@ -86,14 +86,10 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/xen-os.h>
#include <machine/xen/evtchn.h>
+#include <machine/xen/xen_intr.h>
#include <machine/xen/hypervisor.h>
#include <xen/interface/vcpu.h>
-
-#define WARMBOOT_TARGET 0
-#define WARMBOOT_OFF (KERNBASE + 0x0467)
-#define WARMBOOT_SEG (KERNBASE + 0x0469)
-
#define stop_cpus_with_nmi 0
@@ -105,6 +101,10 @@ extern struct pcpu __pcpu[];
static int bootAP;
static union descriptor *bootAPgdt;
+static DEFINE_PER_CPU(int, resched_irq);
+static DEFINE_PER_CPU(int, callfunc_irq);
+static char resched_name[NR_CPUS][15];
+static char callfunc_name[NR_CPUS][15];
/* Free these after use */
void *bootstacks[MAXCPU];
@@ -119,6 +119,8 @@ vm_offset_t smp_tlb_addr1;
vm_offset_t smp_tlb_addr2;
volatile int smp_tlb_wait;
+typedef void call_data_func_t(uintptr_t , uintptr_t);
+
static u_int logical_cpus;
/* used to hold the AP's until we are ready to release them */
@@ -141,8 +143,6 @@ int cpu_apic_ids[MAXCPU];
/* Holds pending bitmap based IPIs per CPU */
static volatile u_int cpu_ipi_pending[MAXCPU];
-static u_int boot_address;
-
static void assign_cpu_ids(void);
static void set_interrupt_apic_ids(void);
int start_all_aps(void);
@@ -300,6 +300,105 @@ cpu_mp_start(void)
}
+static void
+iv_rendezvous(uintptr_t a, uintptr_t b)
+{
+
+}
+
+static void
+iv_invltlb(uintptr_t a, uintptr_t b)
+{
+
+}
+
+static void
+iv_invlpg(uintptr_t a, uintptr_t b)
+{
+
+}
+
+static void
+iv_invlrng(uintptr_t a, uintptr_t b)
+{
+
+}
+
+static void
+iv_invlcache(uintptr_t a, uintptr_t b)
+{
+
+}
+
+static void
+iv_lazypmap(uintptr_t a, uintptr_t b)
+{
+
+}
+
+static void
+iv_bitmap_vector(uintptr_t a, uintptr_t b)
+{
+
+}
+
+
+static call_data_func_t *ipi_vectors[IPI_BITMAP_VECTOR + 1] =
+{ iv_rendezvous,
+ iv_invltlb,
+ iv_invlpg,
+ iv_invlrng,
+ iv_invlcache,
+ iv_lazypmap,
+ iv_bitmap_vector
+};
+
+/*
+ * Reschedule call back. Nothing to do,
+ * all the work is done automatically when
+ * we return from the interrupt.
+ */
+static void
+smp_reschedule_interrupt(void *unused)
+{
+}
+
+struct _call_data {
+ call_data_func_t *func;
+ uintptr_t arg1;
+ uintptr_t arg2;
+ atomic_t started;
+ atomic_t finished;
+ int wait;
+};
+
+static struct _call_data *call_data;
+
+static void
+smp_call_function_interrupt(void *unused)
+{
+ call_data_func_t *func = call_data->func;
+ uintptr_t arg1 = call_data->arg1;
+ uintptr_t arg2 = call_data->arg2;
+ int wait = call_data->wait;
+
+ /*
+ * Notify initiating CPU that I've grabbed the data and am
+ * about to execute the function
+ */
+ mb();
+ atomic_inc(&call_data->started);
+ /*
+ * At this point the info structure may be out of scope unless wait==1
+ */
+ (*func)(arg1, arg2);
+
+ if (wait) {
+ mb();
+ atomic_inc(&call_data->finished);
+ }
+}
+
/*
* Print various information about the SMP system hardware and setup.
*/
@@ -323,6 +422,46 @@ cpu_mp_announce(void)
}
}
+
+static int
+xen_smp_intr_init(unsigned int cpu)
+{
+ int rc;
+
+ per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
+
+ sprintf(resched_name[cpu], "resched%u", cpu);
+ rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
+ cpu,
+ resched_name[cpu],
+ smp_reschedule_interrupt,
+ INTR_FAST);
+
+ per_cpu(resched_irq, cpu) = rc;
+
+ sprintf(callfunc_name[cpu], "callfunc%u", cpu);
+ rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
+ cpu,
+ callfunc_name[cpu],
+ smp_call_function_interrupt,
+ INTR_FAST);
+ if (rc < 0)
+ goto fail;
+ per_cpu(callfunc_irq, cpu) = rc;
+
+ if ((cpu != 0) && ((rc = ap_cpu_initclocks(cpu)) != 0))
+ goto fail;
+
+ return 0;
+
+ fail:
+ if (per_cpu(resched_irq, cpu) >= 0)
+ unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ if (per_cpu(callfunc_irq, cpu) >= 0)
+ unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+ return rc;
+}
+
#define MTOPSIZE (1<<(14 + PAGE_SHIFT))
/*
@@ -336,8 +475,6 @@ init_secondary(void)
/* bootAP is set in start_ap() to our ID. */
-
-
PCPU_SET(currentldt, _default_ldt);
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
#if 0
@@ -434,6 +571,7 @@ init_secondary(void)
smp_active = 1; /* historic */
}
+ xen_smp_intr_init(bootAP);
mtx_unlock_spin(&ap_boot_mtx);
/* wait until all the AP's are up */
@@ -533,15 +671,11 @@ assign_cpu_ids(void)
int
start_all_aps(void)
{
- u_int32_t mpbioswarmvec;
int x,apic_id, cpu;
struct pcpu *pc;
mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
- /* save the current value of the warm-start vector */
- mpbioswarmvec = *((u_int32_t *) WARMBOOT_OFF);
-
/* set up temporary P==V mapping for AP boot */
/* XXX this is a hack, we should boot the AP on its own stack/PTD */
@@ -550,10 +684,6 @@ start_all_aps(void)
apic_id = cpu_apic_ids[cpu];
- /* setup a vector to our boot code */
- *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
- *((volatile u_short *) WARMBOOT_SEG) = (boot_address >> 4);
-
bootAP = cpu;
bootAPgdt = gdt + (512*cpu);
@@ -600,9 +730,6 @@ start_all_aps(void)
/* build our map of 'other' CPUs */
PCPU_SET(other_cpus, all_cpus & ~PCPU_GET(cpumask));
- /* restore the warmstart vector */
- *(u_int32_t *) WARMBOOT_OFF = mpbioswarmvec;
-
pmap_invalidate_range(kernel_pmap, 0, NKPT * NBPDR - 1);
/* number of APs actually started */
@@ -624,11 +751,8 @@ smp_trap_init(trap_info_t *trap_ctxt)
}
}
-void
-cpu_initialize_context(unsigned int cpu);
extern int nkpt;
-
-void
+static void
cpu_initialize_context(unsigned int cpu)
{
/* vcpu_guest_context_t is too large to allocate on the stack.
@@ -645,7 +769,6 @@ cpu_initialize_context(unsigned int cpu)
* Page 0,[0-3] PTD
* Page 1, [4] boot stack
* Page [5] PDPT
-
*
*/
for (i = 0; i < NPGPTD + 2; i++) {
@@ -796,8 +919,9 @@ smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2)
if (!(read_eflags() & PSL_I))
panic("%s: interrupts disabled", __func__);
mtx_lock_spin(&smp_ipi_mtx);
- smp_tlb_addr1 = addr1;
- smp_tlb_addr2 = addr2;
+ call_data->func = ipi_vectors[vector];
+ call_data->arg1 = addr1;
+ call_data->arg2 = addr2;
atomic_store_rel_int(&smp_tlb_wait, 0);
ipi_all_but_self(vector);
while (smp_tlb_wait < ncpu)
OpenPOWER on IntegriCloud