* [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support
@ 2016-08-08 16:51 vijay.kilari
2016-08-08 16:51 ` [Qemu-arm] [RFC PATCH v2 1/2] kernel: Add definitions for GICv3 attributes vijay.kilari
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: vijay.kilari @ 2016-08-08 16:51 UTC (permalink / raw)
To: qemu-arm, peter.maydell, pbonzini
Cc: Prasun.Kapoor, p.fedin, qemu-devel, vijay.kilari, Vijaya Kumar K
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
This series introduces support for GICv3 live migration with
new VGIC implementation in 4.7-rc3 kernel.
In this series, patch 1 of the previous implementation
are ported.
https://lists.nongnu.org/archive/html/qemu-devel/2015-10/msg05284.html
Patch 2, is based on below implementation.
http://patchwork.ozlabs.org/patch/626746/
Kernel patches which implement this functionality are:
http://www.spinics.net/lists/arm-kernel/msg519596.html
This API definition is as per version of VGICv3 specification
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/445611.html
Patch 1 of this series will be synced with KVM patches
in next revision.
Tested Live migration of Idle VM running with 4 VCPUs and 8GB RAM.
Vijaya Kumar K (2):
kernel: Add definitions for GICv3 attributes
hw/intc/arm_gicv3_kvm: Implement get/put functions
hw/intc/arm_gicv3_kvm.c | 474 +++++++++++++++++++++++++++++++++++++++++-
linux-headers/asm-arm64/kvm.h | 17 +-
2 files changed, 478 insertions(+), 13 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-arm] [RFC PATCH v2 1/2] kernel: Add definitions for GICv3 attributes
2016-08-08 16:51 [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support vijay.kilari
@ 2016-08-08 16:51 ` vijay.kilari
2016-08-08 16:51 ` [Qemu-devel] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions vijay.kilari
2016-08-08 16:58 ` [Qemu-arm] [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support no-reply
2 siblings, 0 replies; 6+ messages in thread
From: vijay.kilari @ 2016-08-08 16:51 UTC (permalink / raw)
To: qemu-arm, peter.maydell, pbonzini
Cc: Prasun.Kapoor, p.fedin, qemu-devel, vijay.kilari, Vijaya Kumar K
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
This temporary patch adds kernel API definitions. Use proper header update
procedure after these features are released.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
---
| 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
--git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
index 7d82d1f..396c6f3 100644
--- a/linux-headers/asm-arm64/kvm.h
+++ b/linux-headers/asm-arm64/kvm.h
@@ -180,14 +180,14 @@ struct kvm_arch_memory_slot {
KVM_REG_ARM64_SYSREG_ ## n ## _MASK)
#define __ARM64_SYS_REG(op0,op1,crn,crm,op2) \
- (KVM_REG_ARM64 | KVM_REG_ARM64_SYSREG | \
- ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
+ (ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | \
ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | \
ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | \
ARM64_SYS_REG_SHIFT_MASK(op2, OP2))
-#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
+#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_ARM64 | \
+ KVM_REG_SIZE_U64 | KVM_REG_ARM64_SYSREG)
#define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
@@ -199,10 +199,21 @@ struct kvm_arch_memory_slot {
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define KVM_DEV_ARM_VGIC_V3_CPUID_MASK \
+ (0xffffffffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+#define KVM_DEV_ARM_VGIC_SYSREG_MASK (KVM_REG_ARM64_SYSREG_OP0_MASK | \
+ KVM_REG_ARM64_SYSREG_OP1_MASK | \
+ KVM_REG_ARM64_SYSREG_CRN_MASK | \
+ KVM_REG_ARM64_SYSREG_CRM_MASK | \
+ KVM_REG_ARM64_SYSREG_OP2_MASK)
+#define KVM_DEV_ARM_VGIC_SYSREG(op0,op1,crn,crm,op2) \
+ __ARM64_SYS_REG(op0,op1,crn,crm,op2)
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
+#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
/* Device Control API on vcpu fd */
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions
2016-08-08 16:51 [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support vijay.kilari
2016-08-08 16:51 ` [Qemu-arm] [RFC PATCH v2 1/2] kernel: Add definitions for GICv3 attributes vijay.kilari
@ 2016-08-08 16:51 ` vijay.kilari
2016-08-08 16:57 ` [Qemu-arm] " Peter Maydell
2016-08-08 16:58 ` [Qemu-arm] [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support no-reply
2 siblings, 1 reply; 6+ messages in thread
From: vijay.kilari @ 2016-08-08 16:51 UTC (permalink / raw)
To: qemu-arm, peter.maydell, pbonzini
Cc: Prasun.Kapoor, p.fedin, qemu-devel, vijay.kilari, Vijaya Kumar K
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
This actually implements pre_save and post_load methods for in-kernel
vGICv3.
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
[PMM:
* use decimal, not 0bnnn
* fixed typo in names of ICC_APR0R_EL1 and ICC_AP1R_EL1
* completely rearranged the get and put functions to read and write
the state in a natural order, rather than mixing distributor and
redistributor state together]
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
[Vijay:
* Update macro KVM_VGIC_ATTR
* Use 32 bit access for gicd and gicr
* GICD_IROUTER, GICD_TYPER, GICR_PROPBASER and GICR_PENDBASER reg
access are changed from 64-bit to 32-bit access]
---
hw/intc/arm_gicv3_kvm.c | 474 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 464 insertions(+), 10 deletions(-)
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 711fde3..0f84c86 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -23,8 +23,11 @@
#include "qapi/error.h"
#include "hw/intc/arm_gicv3_common.h"
#include "hw/sysbus.h"
+#include "migration/migration.h"
+#include "qemu/error-report.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
+#include "gicv3_internal.h"
#include "vgic_common.h"
#include "migration/migration.h"
@@ -44,6 +47,23 @@
#define KVM_ARM_GICV3_GET_CLASS(obj) \
OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3)
+#define ICC_PMR_EL1 \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 4, 6, 0)
+#define ICC_BPR0_EL1 \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 8, 3)
+#define ICC_AP0R_EL1(n) \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 8, 4 | n)
+#define ICC_AP1R_EL1(n) \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 9, n)
+#define ICC_BPR1_EL1 \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 3)
+#define ICC_CTLR_EL1 \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 4)
+#define ICC_IGRPEN0_EL1 \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 6)
+#define ICC_IGRPEN1_EL1 \
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 7)
+
typedef struct KVMARMGICv3Class {
ARMGICv3CommonClass parent_class;
DeviceRealize parent_realize;
@@ -57,16 +77,444 @@ static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level)
kvm_arm_gic_set_irq(s->num_irq, irq, level);
}
+#define KVM_VGIC_ATTR(reg, typer) \
+ ((typer & KVM_DEV_ARM_VGIC_V3_CPUID_MASK) | (reg))
+
+static inline void kvm_gicd_access(GICv3State *s, int offset,
+ uint32_t *val, bool write)
+{
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ KVM_VGIC_ATTR(offset, 0),
+ val, write);
+}
+
+static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu,
+ uint32_t *val, bool write)
+{
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(offset, s->cpu[cpu].gicr_typer),
+ val, write);
+}
+
+static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu,
+ uint64_t *val, bool write)
+{
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(reg, s->cpu[cpu].gicr_typer),
+ val, write);
+}
+
+/* Translate from the in-kernel field for an IRQ value to/from the qemu
+ * representation. Note that these are only expected to be used for
+ * SPIs (that is, for interrupts whose state is in the distributor
+ * rather than the redistributor).
+ */
+typedef void (*vgic_translate_fn)(GICv3State *s, int irq,
+ uint32_t *field, bool to_kernel);
+
+static void translate_edge_trigger(GICv3State *s, int irq,
+ uint32_t *field, bool to_kernel)
+{
+ if (to_kernel) { \
+ *field = gicv3_gicd_edge_trigger_test(s, irq); \
+ } else { \
+ gicv3_gicd_edge_trigger_replace(s, irq, *field); \
+ } \
+}
+
+static void translate_priority(GICv3State *s, int irq,
+ uint32_t *field, bool to_kernel)
+{
+ if (to_kernel) {
+ *field = s->gicd_ipriority[irq];
+ } else {
+ s->gicd_ipriority[irq] = *field;
+ }
+}
+
+/* Loop through each distributor IRQ related register; since bits
+ * corresponding to SPIs and PPIs are RAZ/WI when affinity routing
+ * is enabled, we skip those.
+ */
+#define for_each_dist_irq_reg(_irq, _max, _field_width) \
+ for (_irq = GIC_INTERNAL; _irq < _max; _irq += (32 / _field_width))
+
+/* Read a register group from the kernel VGIC */
+static void kvm_dist_get(GICv3State *s, uint32_t offset, int width,
+ vgic_translate_fn translate_fn)
+{
+ uint32_t reg;
+ int j;
+ int irq;
+ uint32_t field;
+ int regsz = 32 / width; /* irqs per kernel register */
+
+ for_each_dist_irq_reg(irq, s->num_irq, width) {
+ kvm_gicd_access(s, offset, ®, false);
+
+ for (j = 0; j < regsz; j++) {
+ field = extract32(reg, j * width, width);
+ translate_fn(s, irq + j, &field, false);
+ }
+ offset += 4;
+ }
+}
+
+/* Write a register group to the kernel VGIC */
+static void kvm_dist_put(GICv3State *s, uint32_t offset, int width,
+ vgic_translate_fn translate_fn)
+{
+ uint32_t reg;
+ int j;
+ int irq;
+ uint32_t field;
+ int regsz = 32 / width; /* irqs per kernel register */
+
+ for_each_dist_irq_reg(irq, s->num_irq, width) {
+ reg = 0;
+ for (j = 0; j < regsz; j++) {
+ translate_fn(s, irq + j, &field, true);
+ reg = deposit32(reg, j * width, width, field);
+ }
+ kvm_gicd_access(s, offset, ®, true);
+ offset += 4;
+ }
+}
+
+/* Read a bitmap register group from the kernel VGIC. */
+static void kvm_dist_getbmp(GICv3State *s, uint32_t offset, uint32_t *bmp)
+{
+ uint32_t reg;
+ int irq;
+
+ for_each_dist_irq_reg(irq, s->num_irq, 1) {
+ kvm_gicd_access(s, offset, ®, false);
+ *gic_bmp_ptr32(bmp, irq) = reg;
+ offset += 4;
+ }
+}
+
+static void kvm_dist_putbmp(GICv3State *s, uint32_t offset,
+ uint32_t clroffset, uint32_t *bmp)
+{
+ uint32_t reg;
+ int irq;
+
+ for_each_dist_irq_reg(irq, s->num_irq, 1) {
+ /* If this bitmap is a set/clear register pair, first write to the
+ * clear-reg to clear all bits before using the set-reg to write
+ * the 1 bits.
+ */
+ if (clroffset != 0) {
+ reg = 0;
+ kvm_gicd_access(s, clroffset, ®, true);
+ }
+ reg = *gic_bmp_ptr32(bmp, irq);
+ kvm_gicd_access(s, offset, ®, true);
+ offset += 4;
+ }
+}
+
+static void kvm_arm_gicv3_check(GICv3State *s)
+{
+ uint32_t reg;
+ uint32_t num_irq;
+
+ /* Sanity checking s->num_irq */
+ kvm_gicd_access(s, GICD_TYPER, ®, false);
+ num_irq = ((reg & 0x1f) + 1) * 32;
+
+ if (num_irq < s->num_irq) {
+ error_report("Model requests %u IRQs, but kernel supports max %u",
+ s->num_irq, num_irq);
+ abort();
+ }
+}
+
static void kvm_arm_gicv3_put(GICv3State *s)
{
- /* TODO */
- DPRINTF("Cannot put kernel gic state, no kernel interface\n");
+ uint32_t regl, regh, reg;
+ uint64_t reg64, redist_typer;
+ int ncpu, i;
+
+ kvm_arm_gicv3_check(s);
+
+ kvm_gicr_access(s, GICR_TYPER, 0, ®l, false);
+ kvm_gicr_access(s, GICR_TYPER + 4, 0, ®h, false);
+ redist_typer = ((uint64_t)regh << 32) | regl;
+
+ reg = s->gicd_ctlr;
+ kvm_gicd_access(s, GICD_CTLR, ®, true);
+
+ if (redist_typer & GICR_TYPER_PLPIS) {
+ /* Set base addresses before LPIs are enabled by GICR_CTLR write */
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ reg64 = c->gicr_propbaser;
+ regl = (uint32_t)reg64;
+ kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true);
+ regh = (uint32_t)(reg64 >> 32);
+ kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, true);
+
+ reg64 = c->gicr_pendbaser;
+ if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
+ /* Setting PTZ is advised if LPIs are disabled, to reduce
+ * GIC initialization time.
+ */
+ reg64 |= GICR_PENDBASER_PTZ;
+ }
+ regl = (uint32_t)reg64;
+ kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, true);
+ regh = (uint32_t)(reg64 >> 32);
+ kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, true);
+ }
+ }
+
+ /* Redistributor state (one per CPU) */
+
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ reg = c->gicr_ctlr;
+ kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true);
+
+ reg = c->gicr_statusr[GICV3_NS];
+ kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, true);
+
+ reg = c->gicr_waker;
+ kvm_gicr_access(s, GICR_WAKER, ncpu, ®, true);
+
+ reg = c->gicr_igroupr0;
+ kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, true);
+
+ reg = ~0;
+ kvm_gicr_access(s, GICR_ICENABLER0, ncpu, ®, true);
+ reg = c->gicr_ienabler0;
+ kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, true);
+
+ /* Restore config before pending so we treat level/edge correctly */
+ reg = half_shuffle32(c->edge_trigger >> 16) << 1;
+ kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, true);
+
+ // TODO: there is no kernel API for reading/writing c->level
+
+ reg = ~0;
+ kvm_gicr_access(s, GICR_ICPENDR0, ncpu, ®, true);
+ reg = c->gicr_ipendr0;
+ kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, true);
+
+ reg = ~0;
+ kvm_gicr_access(s, GICR_ICACTIVER0, ncpu, ®, true);
+ reg = c->gicr_iactiver0;
+ kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, true);
+
+ for (i = 0; i < GIC_INTERNAL; i += 4) {
+ reg = c->gicr_ipriorityr[i] |
+ (c->gicr_ipriorityr[i + 1] << 8) |
+ (c->gicr_ipriorityr[i + 2] << 16) |
+ (c->gicr_ipriorityr[i + 3] << 24);
+ kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, true);
+ }
+ }
+
+ /* Distributor state (shared between all CPUs */
+ reg = s->gicd_statusr[GICV3_NS];
+ kvm_gicd_access(s, GICD_STATUSR, ®, true);
+
+ /* s->enable bitmap -> GICD_ISENABLERn */
+ kvm_dist_putbmp(s, GICD_ISENABLER, GICD_ICENABLER, s->enabled);
+
+ /* s->group bitmap -> GICD_IGROUPRn */
+ kvm_dist_putbmp(s, GICD_IGROUPR, 0, s->group);
+
+ /* Restore targets before pending to ensure the pending state is set on
+ * the appropriate CPU interfaces in the kernel
+ */
+
+ /* s->gicd_irouter[irq] -> GICD_IROUTERn
+ * We can't use kvm_dist_put() here because the registers are 64-bit
+ */
+ for (i = GIC_INTERNAL; i < s->num_irq; i++) {
+ uint32_t offset;
+
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i);
+ reg = (uint32_t)s->gicd_irouter[i];
+ kvm_gicd_access(s, offset, ®, true);
+
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i) + 4;
+ reg = (uint32_t)(s->gicd_irouter[i] >> 32);
+ kvm_gicd_access(s, offset, ®, true);
+ }
+
+ /* s->trigger bitmap -> GICD_ICFGRn
+ * (restore configuration registers before pending IRQs so we treat
+ * level/edge correctly)
+ */
+ kvm_dist_put(s, GICD_ICFGR, 2, translate_edge_trigger);
+
+ // TODO: there is no kernel API for reading/writing s->level
+
+ /* s->pending bitmap -> GICD_ISPENDRn */
+ kvm_dist_putbmp(s, GICD_ISPENDR, GICD_ICPENDR, s->pending);
+
+ /* s->active bitmap -> GICD_ISACTIVERn */
+ kvm_dist_putbmp(s, GICD_ISACTIVER, GICD_ICACTIVER, s->active);
+
+ /* s->gicd_ipriority[] -> GICD_IPRIORITYRn */
+ kvm_dist_put(s, GICD_IPRIORITYR, 8, translate_priority);
+
+ /* CPU Interface state (one per CPU) */
+
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
+ &c->icc_ctlr_el1[GICV3_NS], true);
+ kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu,
+ &c->icc_igrpen[GICV3_G0], true);
+ kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu,
+ &c->icc_igrpen[GICV3_G1NS], true);
+ kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, true);
+ kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], true);
+ kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], true);
+
+ for (i = 0; i < 4; i++) {
+ reg64 = c->icc_apr[GICV3_G0][i];
+ kvm_gicc_access(s, ICC_AP0R_EL1(i), ncpu, ®64, true);
+ }
+
+ for (i = 0; i < 4; i++) {
+ reg64 = c->icc_apr[GICV3_G1NS][i];
+ kvm_gicc_access(s, ICC_AP1R_EL1(i), ncpu, ®64, true);
+ }
+ }
}
static void kvm_arm_gicv3_get(GICv3State *s)
{
- /* TODO */
- DPRINTF("Cannot get kernel gic state, no kernel interface\n");
+ uint32_t regl, regh, reg;
+ uint64_t reg64, redist_typer;
+ int ncpu, i;
+
+ kvm_arm_gicv3_check(s);
+
+ kvm_gicr_access(s, GICR_TYPER, 0, ®l, false);
+ kvm_gicr_access(s, GICR_TYPER + 4, 0, ®h, false);
+ redist_typer = ((uint64_t)regh << 32) | regl;
+
+ kvm_gicd_access(s, GICD_CTLR, ®, false);
+ s->gicd_ctlr = reg;
+
+ /* Redistributor state (one per CPU) */
+
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false);
+ c->gicr_ctlr = reg;
+
+ kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, false);
+ c->gicr_statusr[GICV3_NS] = reg;
+
+ kvm_gicr_access(s, GICR_WAKER, ncpu, ®, false);
+ c->gicr_waker = reg;
+
+ kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, false);
+ c->gicr_igroupr0 = reg;
+ kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, false);
+ c->gicr_ienabler0 = reg;
+ kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, false);
+ c->edge_trigger = half_unshuffle32(reg >> 1) << 16;
+ kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, false);
+ c->gicr_ipendr0 = reg;
+ kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, false);
+ c->gicr_iactiver0 = reg;
+
+ for (i = 0; i < GIC_INTERNAL; i += 4) {
+ kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, false);
+ c->gicr_ipriorityr[i] = extract32(reg, 0, 8);
+ c->gicr_ipriorityr[i + 1] = extract32(reg, 8, 8);
+ c->gicr_ipriorityr[i + 2] = extract32(reg, 16, 8);
+ c->gicr_ipriorityr[i + 3] = extract32(reg, 24, 8);
+ }
+ }
+
+ if (redist_typer & GICR_TYPER_PLPIS) {
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false);
+ kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, false);
+ c->gicr_propbaser = ((uint64_t)regh << 32) | regl;
+
+ kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, false);
+ kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, false);
+ c->gicr_pendbaser = ((uint64_t)regh << 32) | regl;
+ }
+ }
+
+ /* Distributor state (shared between all CPUs */
+
+ kvm_gicd_access(s, GICD_STATUSR, ®, false);
+ s->gicd_statusr[GICV3_NS] = reg;
+
+ /* GICD_IGROUPRn -> s->group bitmap */
+ kvm_dist_getbmp(s, GICD_IGROUPR, s->group);
+
+ /* GICD_ISENABLERn -> s->enabled bitmap */
+ kvm_dist_getbmp(s, GICD_ISENABLER, s->enabled);
+
+ /* GICD_ISPENDRn -> s->pending bitmap */
+ kvm_dist_getbmp(s, GICD_ISPENDR, s->pending);
+
+ /* GICD_ISACTIVERn -> s->active bitmap */
+ kvm_dist_getbmp(s, GICD_ISACTIVER, s->active);
+
+ /* GICD_ICFGRn -> s->trigger bitmap */
+ kvm_dist_get(s, GICD_ICFGR, 2, translate_edge_trigger);
+
+ /* GICD_IPRIORITYRn -> s->gicd_ipriority[] */
+ kvm_dist_get(s, GICD_IPRIORITYR, 8, translate_priority);
+
+ /* GICD_IROUTERn -> s->gicd_irouter[irq] */
+ for (i = GIC_INTERNAL; i < s->num_irq; i++) {
+ uint32_t offset;
+
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i);
+ kvm_gicd_access(s, offset, ®l, false);
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i) + 4;
+ kvm_gicd_access(s, offset, ®h, false);
+ s->gicd_irouter[i] = ((uint64_t)regh << 32) | regl;
+ }
+
+ /*****************************************************************
+ * CPU Interface(s) State
+ */
+
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
+ &c->icc_ctlr_el1[GICV3_NS], false);
+ kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu,
+ &c->icc_igrpen[GICV3_G0], false);
+ kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu,
+ &c->icc_igrpen[GICV3_G1NS], false);
+ kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false);
+ kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], false);
+ kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], false);
+
+ for (i = 0; i < 4; i++) {
+ kvm_gicc_access(s, ICC_AP0R_EL1(i), ncpu, ®64, false);
+ c->icc_apr[0][i] = reg64;
+ }
+
+ for (i = 0; i < 4; i++) {
+ kvm_gicc_access(s, ICC_AP1R_EL1(i), ncpu, ®64, false);
+ c->icc_apr[1][i] = reg64;
+ }
+ }
}
static void kvm_arm_gicv3_reset(DeviceState *dev)
@@ -77,6 +525,12 @@ static void kvm_arm_gicv3_reset(DeviceState *dev)
DPRINTF("Reset\n");
kgc->parent_reset(dev);
+
+ if (s->migration_blocker) {
+ DPRINTF("Cannot put kernel gic state, no kernel interface\n");
+ return;
+ }
+
kvm_arm_gicv3_put(s);
}
@@ -121,12 +575,12 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
- /* Block migration of a KVM GICv3 device: the API for saving and restoring
- * the state in the kernel is not yet finalised in the kernel or
- * implemented in QEMU.
- */
- error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
- migrate_add_blocker(s->migration_blocker);
+ if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ GICD_CTLR)) {
+ error_setg(&s->migration_blocker, "This operating system kernel does "
+ "not support vGICv3 migration");
+ migrate_add_blocker(s->migration_blocker);
+ }
}
static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-arm] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions
2016-08-08 16:51 ` [Qemu-devel] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions vijay.kilari
@ 2016-08-08 16:57 ` Peter Maydell
2016-08-09 6:52 ` Vijay Kilari
0 siblings, 1 reply; 6+ messages in thread
From: Peter Maydell @ 2016-08-08 16:57 UTC (permalink / raw)
To: Vijay Kilari
Cc: prasun.kapoor, Pavel Fedin, QEMU Developers, Vijaya Kumar K,
qemu-arm, Paolo Bonzini
On 8 August 2016 at 17:51, <vijay.kilari@gmail.com> wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>
> This actually implements pre_save and post_load methods for in-kernel
> vGICv3.
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> [PMM:
> * use decimal, not 0bnnn
> * fixed typo in names of ICC_APR0R_EL1 and ICC_AP1R_EL1
> * completely rearranged the get and put functions to read and write
> the state in a natural order, rather than mixing distributor and
> redistributor state together]
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> [Vijay:
> * Update macro KVM_VGIC_ATTR
> * Use 32 bit access for gicd and gicr
> * GICD_IROUTER, GICD_TYPER, GICR_PROPBASER and GICR_PENDBASER reg
> access are changed from 64-bit to 32-bit access]
> ---
> + // TODO: there is no kernel API for reading/writing c->level
We have now defined this API so this code should use it.
> + // TODO: there is no kernel API for reading/writing s->level
Also here (and similarly in the _get function).
thanks
-- PMM
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-arm] [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support
2016-08-08 16:51 [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support vijay.kilari
2016-08-08 16:51 ` [Qemu-arm] [RFC PATCH v2 1/2] kernel: Add definitions for GICv3 attributes vijay.kilari
2016-08-08 16:51 ` [Qemu-devel] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions vijay.kilari
@ 2016-08-08 16:58 ` no-reply
2 siblings, 0 replies; 6+ messages in thread
From: no-reply @ 2016-08-08 16:58 UTC (permalink / raw)
To: vijay.kilari
Cc: peter.maydell, famz, vijay.kilari, Prasun.Kapoor, p.fedin,
qemu-devel, Vijaya.Kumar, qemu-arm, pbonzini
Hi,
Your series seems to have some coding style problems. See output below for
more information:
Message-id: 1470675071-23677-1-git-send-email-vijay.kilari@gmail.com
Type: series
Subject: [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done
exit $failed
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
* [new tag] patchew/1470675071-23677-1-git-send-email-vijay.kilari@gmail.com -> patchew/1470675071-23677-1-git-send-email-vijay.kilari@gmail.com
Switched to a new branch 'test'
52635e4 hw/intc/arm_gicv3_kvm: Implement get/put functions
15053e8 kernel: Add definitions for GICv3 attributes
=== OUTPUT BEGIN ===
Checking PATCH 1/2: kernel: Add definitions for GICv3 attributes...
ERROR: code indent should never use tabs
#22: FILE: linux-headers/asm-arm64/kvm.h:183:
+^I(ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \$
ERROR: space required after that ',' (ctx:VxV)
#47: FILE: linux-headers/asm-arm64/kvm.h:211:
+#define KVM_DEV_ARM_VGIC_SYSREG(op0,op1,crn,crm,op2) \
^
ERROR: space required after that ',' (ctx:VxV)
#47: FILE: linux-headers/asm-arm64/kvm.h:211:
+#define KVM_DEV_ARM_VGIC_SYSREG(op0,op1,crn,crm,op2) \
^
ERROR: space required after that ',' (ctx:VxV)
#47: FILE: linux-headers/asm-arm64/kvm.h:211:
+#define KVM_DEV_ARM_VGIC_SYSREG(op0,op1,crn,crm,op2) \
^
ERROR: space required after that ',' (ctx:VxV)
#47: FILE: linux-headers/asm-arm64/kvm.h:211:
+#define KVM_DEV_ARM_VGIC_SYSREG(op0,op1,crn,crm,op2) \
^
ERROR: space required after that ',' (ctx:VxV)
#48: FILE: linux-headers/asm-arm64/kvm.h:212:
+ __ARM64_SYS_REG(op0,op1,crn,crm,op2)
^
ERROR: space required after that ',' (ctx:VxV)
#48: FILE: linux-headers/asm-arm64/kvm.h:212:
+ __ARM64_SYS_REG(op0,op1,crn,crm,op2)
^
ERROR: space required after that ',' (ctx:VxV)
#48: FILE: linux-headers/asm-arm64/kvm.h:212:
+ __ARM64_SYS_REG(op0,op1,crn,crm,op2)
^
ERROR: space required after that ',' (ctx:VxV)
#48: FILE: linux-headers/asm-arm64/kvm.h:212:
+ __ARM64_SYS_REG(op0,op1,crn,crm,op2)
^
total: 9 errors, 0 warnings, 38 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 2/2: hw/intc/arm_gicv3_kvm: Implement get/put functions...
ERROR: do not use C99 // comments
#291: FILE: hw/intc/arm_gicv3_kvm.c:300:
+ // TODO: there is no kernel API for reading/writing c->level
ERROR: do not use C99 // comments
#347: FILE: hw/intc/arm_gicv3_kvm.c:356:
+ // TODO: there is no kernel API for reading/writing s->level
total: 2 errors, 0 warnings, 512 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-arm] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions
2016-08-08 16:57 ` [Qemu-arm] " Peter Maydell
@ 2016-08-09 6:52 ` Vijay Kilari
0 siblings, 0 replies; 6+ messages in thread
From: Vijay Kilari @ 2016-08-09 6:52 UTC (permalink / raw)
To: Peter Maydell
Cc: prasun.kapoor, Pavel Fedin, QEMU Developers, Vijaya Kumar K,
qemu-arm, Paolo Bonzini
On Mon, Aug 8, 2016 at 10:27 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 8 August 2016 at 17:51, <vijay.kilari@gmail.com> wrote:
>> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>>
>> This actually implements pre_save and post_load methods for in-kernel
>> vGICv3.
>>
>> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>> [PMM:
>> * use decimal, not 0bnnn
>> * fixed typo in names of ICC_APR0R_EL1 and ICC_AP1R_EL1
>> * completely rearranged the get and put functions to read and write
>> the state in a natural order, rather than mixing distributor and
>> redistributor state together]
>> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>> [Vijay:
>> * Update macro KVM_VGIC_ATTR
>> * Use 32 bit access for gicd and gicr
>> * GICD_IROUTER, GICD_TYPER, GICR_PROPBASER and GICR_PENDBASER reg
>> access are changed from 64-bit to 32-bit access]
>> ---
>
>> + // TODO: there is no kernel API for reading/writing c->level
>
> We have now defined this API so this code should use it.
You mean storing and restoring of irq->line_level of kernel?.
I don't see any API defined in new vgic to read line level.
The irq pending information is updated when line_level is changed in
kernel. Hence pending (ispendr) holds information of pending status
of interrupt. Do you see line level is still required to save & restore?
>
>> + // TODO: there is no kernel API for reading/writing s->level
>
> Also here (and similarly in the _get function).
>
> thanks
> -- PMM
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-08-09 7:00 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-08 16:51 [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support vijay.kilari
2016-08-08 16:51 ` [Qemu-arm] [RFC PATCH v2 1/2] kernel: Add definitions for GICv3 attributes vijay.kilari
2016-08-08 16:51 ` [Qemu-devel] [RFC PATCH v2 2/2] hw/intc/arm_gicv3_kvm: Implement get/put functions vijay.kilari
2016-08-08 16:57 ` [Qemu-arm] " Peter Maydell
2016-08-09 6:52 ` Vijay Kilari
2016-08-08 16:58 ` [Qemu-arm] [Qemu-devel] [RFC PATCH v2 0/2] GICv3 live migration support no-reply
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).