diff options
author | Dietmar Eggemann <dietmar.eggemann@arm.com> | 2012-03-15 14:59:41 +0000 |
---|---|---|
committer | Dietmar Eggemann <dietmar.eggemann@arm.com> | 2012-05-22 10:43:46 +0100 |
commit | 4112d8f52fcdc6b76bf82a44be48a66fce1fbada (patch) | |
tree | 3a0254579818160b825040f2c5bf188ecd879dc1 | |
parent | 0b0dfb1c222362944bce728357551a88c99997d6 (diff) |
Virqmig: Complete interoperability with hotplug.
Signed-off-by: Achin Gupta <achin.gupta@arm.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
-rwxr-xr-x | big-little/common/pagetable_setup.c | 8 | ||||
-rw-r--r-- | big-little/common/vgic_handle.c | 4 | ||||
-rw-r--r-- | big-little/common/vgiclib.c | 18 | ||||
-rw-r--r-- | big-little/virtualisor/vgic_trap_handler.c | 11 | ||||
-rw-r--r-- | big-little/virtualisor/virt_setup.c | 18 |
5 files changed, 33 insertions, 26 deletions
diff --git a/big-little/common/pagetable_setup.c b/big-little/common/pagetable_setup.c index 4a25a8f..431e047 100755 --- a/big-little/common/pagetable_setup.c +++ b/big-little/common/pagetable_setup.c @@ -379,6 +379,14 @@ void Create2ndStagePageTables(void) l3_desc.pt_addr = stage2_l3_cpuif_pt; Add4KMapping(&l3_desc); + /* 4KB Mapping for trapping GIC Distributor accesses */ + l3_desc.va = GIC_ID_PHY_BASE; + l3_desc.pa = GIC_ID_PHY_BASE; + l3_desc.attrs = ACCESS_FLAG | SHAREABILITY(0x3) | ACCESS_PERM(0x3) | + MEM_ATTR(0x1); + l3_desc.pt_addr = stage2_l3_cpuif_pt; + Add4KMapping(&l3_desc); + /* * Create a mapping for a device page to be used * for Locks, Events & anything that is shared when both diff --git a/big-little/common/vgic_handle.c b/big-little/common/vgic_handle.c index 0e20dcf..960f97d 100644 --- a/big-little/common/vgic_handle.c +++ b/big-little/common/vgic_handle.c @@ -160,7 +160,9 @@ vm_context *handle_interrupt(vm_context * context) break; case IPI_MIGRATE_VIRQS: - complete_virq_migration(src_cpu); + /* Refer to comments in vgic_trap_handler.c */ + if (FALSE == async_switchover) + complete_virq_migration(src_cpu); return ret_ctx; default: diff --git a/big-little/common/vgiclib.c b/big-little/common/vgiclib.c index 5f5735b..ffe1be9 100644 --- a/big-little/common/vgiclib.c +++ b/big-little/common/vgiclib.c @@ -25,11 +25,13 @@ #include "virt_helpers.h" #include "int_master.h" #include "ipi.h" +#include "events.h" + +extern unsigned get_cpuinfo(unsigned); /* * Manage overflowints somehow.. static pool with recycling allocators. */ - #define MAXOVERFLOWINTS 200 static struct overflowint *freeoverflows[NUM_CPUS]; @@ -170,6 +172,7 @@ unsigned start_virq_migration(unsigned orig, unsigned curr, unsigned icdiptr_off */ if (virq_mig_mask) { send_hyp_ipi(virq_mig_mask, IPI_MIGRATE_VIRQS); + wait_for_events(VIRQ_MIG_DONE, get_cpu_mask(virq_mig_mask)); return 1; } @@ -183,16 +186,19 @@ void complete_virq_migration(unsigned src_cpuid) { unsigned ctr, cpu_id = read_cpuid(); unsigned cluster_id = read_clusterid(); - unsigned dest_cpuif = get_cpuif(cluster_id, cpu_id); + unsigned dest_cpuid = 0; for (ctr = 0; ctr < MAX_MIG_IRQS; ctr++) { - if (migrated_irqs[src_cpuid][ctr].desc && - migrated_irqs[src_cpuid][ctr].dest_cpuif == dest_cpuif) { + /* + * Compare the cpu id instead of the cpu interface id in case + * a switch took place before the virq migration ipi was recieved. + */ + dest_cpuid = get_cpuinfo(migrated_irqs[src_cpuid][ctr].dest_cpuif) & 0xf; + if (migrated_irqs[src_cpuid][ctr].desc && dest_cpuid == cpu_id) enqueue_interrupt(migrated_irqs[src_cpuid][ctr].desc, cpu_id); - } } -// set_event(VIRQ_MIG_DONE, src_cpuid); + set_event(VIRQ_MIG_DONE, src_cpuid); return; } diff --git a/big-little/virtualisor/vgic_trap_handler.c b/big-little/virtualisor/vgic_trap_handler.c index 5e64eea..cd06578 100644 --- a/big-little/virtualisor/vgic_trap_handler.c +++ b/big-little/virtualisor/vgic_trap_handler.c @@ -25,6 +25,7 @@ #include "misc.h" #include "virt_helpers.h" #include "vgiclib.h" +#include "int_master.h" /* * Whether A15 or A7, the distributor accesses are virtualised in @@ -51,7 +52,15 @@ void handle_vgic_distif_abort(unsigned pa, unsigned *data, unsigned write) write32(pa, value); icdiptr_curr = value; - start_virq_migration(icdiptr_orig, icdiptr_curr, reg_offset - GICD_CPUS); + /* + * Virtual irq migration needs communication with another cpu in + * HYP mode. A cluster switch while doing this can cause a deadlock + * and there is no easy way around this. So the assumption is that + * the OS will prevent a switch while an irq migration operation is + * in progress. + */ + if (FALSE == async_switchover) + start_virq_migration(icdiptr_orig, icdiptr_curr, reg_offset - GICD_CPUS); } else { value = read32(pa); diff --git a/big-little/virtualisor/virt_setup.c b/big-little/virtualisor/virt_setup.c index d35adc6..4403ae2 100644 --- a/big-little/virtualisor/virt_setup.c +++ b/big-little/virtualisor/virt_setup.c @@ -130,24 +130,6 @@ void SetupVirtualisor(unsigned first_cpu) } - /* - * Irrespective of what cpu types are present in the - * dual cluster system, the host cluster has to trap - * accesses to the vgic distributor when switching. - */ - if (switcher && cluster_id == host_cluster) { - if (cpu_id == first_cpu) { - rc = mem_trap_setup(GIC_ID_PHY_BASE, - &svgic_distif_trap); - if (rc) { - printf - ("%s: svgic distif trap setup failed \n", - __FUNCTION__); - goto out; - } - } - } - /* * If the two clusters have different cpu types, then the * target saves its midr and the host uses the value to |