Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60dd133a authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge tag 'vgic-migrate-for-marc' of...

Merge tag 'vgic-migrate-for-marc' of git://git.linaro.org/people/christoffer.dall/linux-kvm-arm into kvm-arm64/next

VGIC and timer migration pull
parents 989c6b34 fa20f5ae
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2391,7 +2391,8 @@ struct kvm_reg_list {
This ioctl returns the guest registers that are supported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.

4.85 KVM_ARM_SET_DEVICE_ADDR

4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated)

Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
Architectures: arm, arm64
@@ -2429,6 +2430,10 @@ must be called after calling KVM_CREATE_IRQCHIP, but before calling
KVM_RUN on any of the VCPUs.  Calling this ioctl twice for any of the
base addresses will return -EEXIST.

Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
should be used instead.


4.86 KVM_PPC_RTAS_DEFINE_TOKEN

Capability: KVM_CAP_PPC_RTAS
+73 −0
Original line number Diff line number Diff line
ARM Virtual Generic Interrupt Controller (VGIC)
===============================================

Device types supported:
  KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0

Only one VGIC instance may be instantiated through either this API or the
legacy KVM_CREATE_IRQCHIP api.  The created VGIC will act as the VM interrupt
controller, requiring emulated user-space devices to inject interrupts to the
VGIC instead of directly to CPUs.

Groups:
  KVM_DEV_ARM_VGIC_GRP_ADDR
  Attributes:
    KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
      Base address in the guest physical address space of the GIC distributor
      register mappings.

    KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
      Base address in the guest physical address space of the GIC virtual cpu
      interface register mappings.

  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
  Attributes:
    The attr field of kvm_device_attr encodes two values:
    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
    values:   |    reserved   |   cpu id   |      offset     |

    All distributor regs are (rw, 32-bit)

    The offset is relative to the "Distributor base address" as defined in the
    GICv2 specs.  Getting or setting such a register has the same effect as
    reading or writing the register on the actual hardware from the cpu
    specified with cpu id field.  Note that most distributor fields are not
    banked, but return the same value regardless of the cpu id used to access
    the register.
  Limitations:
    - Priorities are not implemented, and registers are RAZ/WI
  Errors:
    -ENODEV: Getting or setting this register is not yet supported
    -EBUSY: One or more VCPUs are running

  KVM_DEV_ARM_VGIC_GRP_CPU_REGS
  Attributes:
    The attr field of kvm_device_attr encodes two values:
    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
    values:   |    reserved   |   cpu id   |      offset     |

    All CPU interface regs are (rw, 32-bit)

    The offset specifies the offset from the "CPU interface base address" as
    defined in the GICv2 specs.  Getting or setting such a register has the
    same effect as reading or writing the register on the actual hardware.

    The Active Priorities Registers APRn are implementation defined, so we set a
    fixed format for our implementation that fits with the model of a "GICv2
    implementation without the security extensions" which we present to the
    guest.  This interface always exposes four register APR[0-3] describing the
    maximum possible 128 preemption levels.  The semantics of the register
    indicate if any interrupts in a given preemption level are in the active
    state by setting the corresponding bit.

    Thus, preemption level X has one or more active interrupts if and only if:

      APRn[X mod 32] == 0b1,  where n = X / 32

    Bits for undefined preemption levels are RAZ/WI.

  Limitations:
    - Priorities are not implemented, and registers are RAZ/WI
  Errors:
    -ENODEV: Getting or setting this register is not yet supported
    -EBUSY: One or more VCPUs are running
+3 −0
Original line number Diff line number Diff line
@@ -225,4 +225,7 @@ static inline int kvm_arch_dev_ioctl_check_extension(long ext)
int kvm_perf_init(void);
int kvm_perf_teardown(void);

u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);

#endif /* __ARM_KVM_HOST_H__ */
+28 −0
Original line number Diff line number Diff line
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
#define KVM_REG_ARM_32_CRN_MASK		0x0000000000007800
#define KVM_REG_ARM_32_CRN_SHIFT	11

#define ARM_CP15_REG_SHIFT_MASK(x,n) \
	(((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK)

#define __ARM_CP15_REG(op1,crn,crm,op2) \
	(KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT) | \
	ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
	ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
	ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
	ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))

#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)

#define __ARM_CP15_REG64(op1,crm) \
	(__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)

#define KVM_REG_ARM_TIMER_CTL		ARM_CP15_REG32(0, 14, 3, 1)
#define KVM_REG_ARM_TIMER_CNT		ARM_CP15_REG64(1, 14) 
#define KVM_REG_ARM_TIMER_CVAL		ARM_CP15_REG64(3, 14) 

/* Normal registers are mapped as coprocessor 16. */
#define KVM_REG_ARM_CORE		(0x0010 << KVM_REG_ARM_COPROC_SHIFT)
#define KVM_REG_ARM_CORE_REG(name)	(offsetof(struct kvm_regs, name) / 4)
@@ -143,6 +163,14 @@ struct kvm_arch_memory_slot {
#define KVM_REG_ARM_VFP_FPINST		0x1009
#define KVM_REG_ARM_VFP_FPINST2		0x100A

/* Device Control API: ARM VGIC */
#define KVM_DEV_ARM_VGIC_GRP_ADDR	0
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
#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_OFFSET_SHIFT	0
#define   KVM_DEV_ARM_VGIC_OFFSET_MASK	(0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)

/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_TYPE_SHIFT		24
+15 −4
Original line number Diff line number Diff line
@@ -137,6 +137,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
	if (ret)
		goto out_free_stage2_pgd;

	kvm_timer_init(kvm);

	/* Mark the initial VMID generation invalid */
	kvm->arch.vmid_gen = 0;

@@ -188,6 +190,7 @@ int kvm_dev_ioctl_check_extension(long ext)
	case KVM_CAP_IRQCHIP:
		r = vgic_present;
		break;
	case KVM_CAP_DEVICE_CTRL:
	case KVM_CAP_USER_MEMORY:
	case KVM_CAP_SYNC_MMU:
	case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
@@ -339,6 +342,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)

void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
	/*
	 * The arch-generic KVM code expects the cpu field of a vcpu to be -1
	 * if the vcpu is no longer assigned to a cpu.  This is used for the
	 * optimized make_all_cpus_request path.
	 */
	vcpu->cpu = -1;

	kvm_arm_set_running_vcpu(NULL);
}

@@ -462,6 +472,8 @@ static void update_vttbr(struct kvm *kvm)

static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
{
	int ret;

	if (likely(vcpu->arch.has_run_once))
		return 0;

@@ -471,9 +483,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
	 * Initialize the VGIC before running a vcpu the first time on
	 * this VM.
	 */
	if (irqchip_in_kernel(vcpu->kvm) &&
	    unlikely(!vgic_initialized(vcpu->kvm))) {
		int ret = kvm_vgic_init(vcpu->kvm);
	if (unlikely(!vgic_initialized(vcpu->kvm))) {
		ret = kvm_vgic_init(vcpu->kvm);
		if (ret)
			return ret;
	}
@@ -772,7 +783,7 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
	case KVM_ARM_DEVICE_VGIC_V2:
		if (!vgic_present)
			return -ENXIO;
		return kvm_vgic_set_addr(kvm, type, dev_addr->addr);
		return kvm_vgic_addr(kvm, type, &dev_addr->addr, true);
	default:
		return -ENODEV;
	}
Loading