Skip to content

Commit

Permalink
Merge tag 'kvm-arm-for-3.17' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/kvmarm/kvmarm into kvm

KVM/ARM New features for 3.17 include:
 - Fixes and code refactoring for stage2 kvm MMU unmap_range
 - Support unmapping IPAs on deleting memslots for arm and arm64
 - Support MMIO mappings in stage2 faults
 - KVM VGIC v2 emulation on GICv3 hardware
 - Big-Endian support for arm/arm64 (guest and host)
 - Debug Architecture support for arm64 (arm32 is on Christoffer's todo list)

Conflicts:
	virt/kvm/arm/vgic.c [last minute cherry-pick from 3.17 to 3.16]
  • Loading branch information
bonzini committed Aug 5, 2014
2 parents 5167d09 + dedf97e commit 5d57686
Show file tree
Hide file tree
Showing 39 changed files with 2,858 additions and 576 deletions.
8 changes: 8 additions & 0 deletions Documentation/arm64/booting.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ Before jumping into the kernel, the following conditions must be met:
the kernel image will be entered must be initialised by software at a
higher exception level to prevent execution in an UNKNOWN state.

For systems with a GICv3 interrupt controller:
- If EL3 is present:
ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1.
ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1.
- If the kernel is entered at EL1:
ICC.SRE_EL2.Enable (bit 3) must be initialised to 0b1
ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b1.

The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must
enter the kernel in the same exception level.
Expand Down
79 changes: 79 additions & 0 deletions Documentation/devicetree/bindings/arm/gic-v3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
* ARM Generic Interrupt Controller, version 3

AArch64 SMP cores are often associated with a GICv3, providing Private
Peripheral Interrupts (PPI), Shared Peripheral Interrupts (SPI),
Software Generated Interrupts (SGI), and Locality-specific Peripheral
Interrupts (LPI).

Main node required properties:

- compatible : should at least contain "arm,gic-v3".
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. Must be a single cell with a value of at least 3.

The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
interrupts. Other values are reserved for future use.

The 2nd cell contains the interrupt number for the interrupt type.
SPI interrupts are in the range [0-987]. PPI interrupts are in the
range [0-15].

The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
1 = edge triggered
4 = level triggered

Cells 4 and beyond are reserved for future use. When the 1st cell
has a value of 0 or 1, cells 4 and beyond act as padding, and may be
ignored. It is recommended that padding cells have a value of 0.

- reg : Specifies base physical address(s) and size of the GIC
registers, in the following order:
- GIC Distributor interface (GICD)
- GIC Redistributors (GICR), one range per redistributor region
- GIC CPU interface (GICC)
- GIC Hypervisor interface (GICH)
- GIC Virtual CPU interface (GICV)

GICC, GICH and GICV are optional.

- interrupts : Interrupt source of the VGIC maintenance interrupt.

Optional

- redistributor-stride : If using padding pages, specifies the stride
of consecutive redistributors. Must be a multiple of 64kB.

- #redistributor-regions: The number of independent contiguous regions
occupied by the redistributors. Required if more than one such
region is present.

Examples:

gic: interrupt-controller@2cf00000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
interrupt-controller;
reg = <0x0 0x2f000000 0 0x10000>, // GICD
<0x0 0x2f100000 0 0x200000>, // GICR
<0x0 0x2c000000 0 0x2000>, // GICC
<0x0 0x2c010000 0 0x2000>, // GICH
<0x0 0x2c020000 0 0x2000>; // GICV
interrupts = <1 9 4>;
};

gic: interrupt-controller@2c010000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
interrupt-controller;
redistributor-stride = <0x0 0x40000>; // 256kB stride
#redistributor-regions = <2>;
reg = <0x0 0x2c010000 0 0x10000>, // GICD
<0x0 0x2d000000 0 0x800000>, // GICR 1: CPUs 0-31
<0x0 0x2e000000 0 0x800000>; // GICR 2: CPUs 32-63
<0x0 0x2c040000 0 0x2000>, // GICC
<0x0 0x2c060000 0 0x2000>, // GICH
<0x0 0x2c080000 0 0x2000>; // GICV
interrupts = <1 9 4>;
};
18 changes: 18 additions & 0 deletions arch/arm/include/asm/kvm_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@
#define ARM_EXCEPTION_FIQ 6
#define ARM_EXCEPTION_HVC 7

/*
* The rr_lo_hi macro swaps a pair of registers depending on
* current endianness. It is used in conjunction with ldrd and strd
* instructions that load/store a 64-bit value from/to memory to/from
* a pair of registers which are used with the mrrc and mcrr instructions.
* If used with the ldrd/strd instructions, the a1 parameter is the first
* source/destination register and the a2 parameter is the second
* source/destination register. Note that the ldrd/strd instructions
* already swap the bytes within the words correctly according to the
* endianness setting, but the order of the registers need to be effectively
* swapped when used with the mrrc/mcrr instructions.
*/
#ifdef CONFIG_CPU_ENDIAN_BE8
#define rr_lo_hi(a1, a2) a2, a1
#else
#define rr_lo_hi(a1, a2) a1, a2
#endif

#ifndef __ASSEMBLY__
struct kvm;
struct kvm_vcpu;
Expand Down
22 changes: 18 additions & 4 deletions arch/arm/include/asm/kvm_emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,16 @@ static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
default:
return be32_to_cpu(data);
}
} else {
switch (len) {
case 1:
return data & 0xff;
case 2:
return le16_to_cpu(data & 0xffff);
default:
return le32_to_cpu(data);
}
}

return data; /* Leave LE untouched */
}

static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
Expand All @@ -203,9 +210,16 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
default:
return cpu_to_be32(data);
}
} else {
switch (len) {
case 1:
return data & 0xff;
case 2:
return cpu_to_le16(data & 0xffff);
default:
return cpu_to_le32(data);
}
}

return data; /* Leave LE untouched */
}

#endif /* __ARM_KVM_EMULATE_H__ */
8 changes: 5 additions & 3 deletions arch/arm/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,12 @@ static inline int kvm_arch_dev_ioctl_check_extension(long ext)
return 0;
}

static inline void vgic_arch_setup(const struct vgic_params *vgic)
{
BUG_ON(vgic->type != VGIC_V2);
}

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__ */
12 changes: 12 additions & 0 deletions arch/arm/include/asm/kvm_mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})

static inline bool kvm_page_empty(void *ptr)
{
struct page *ptr_page = virt_to_page(ptr);
return page_count(ptr_page) == 1;
}


#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep)
#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
#define kvm_pud_table_empty(pudp) (0)


struct kvm;

#define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l))
Expand Down
14 changes: 7 additions & 7 deletions arch/arm/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,13 @@ int main(void)
DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
#ifdef CONFIG_KVM_ARM_VGIC
DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu));
DEFINE(VGIC_CPU_HCR, offsetof(struct vgic_cpu, vgic_hcr));
DEFINE(VGIC_CPU_VMCR, offsetof(struct vgic_cpu, vgic_vmcr));
DEFINE(VGIC_CPU_MISR, offsetof(struct vgic_cpu, vgic_misr));
DEFINE(VGIC_CPU_EISR, offsetof(struct vgic_cpu, vgic_eisr));
DEFINE(VGIC_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_elrsr));
DEFINE(VGIC_CPU_APR, offsetof(struct vgic_cpu, vgic_apr));
DEFINE(VGIC_CPU_LR, offsetof(struct vgic_cpu, vgic_lr));
DEFINE(VGIC_V2_CPU_HCR, offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
DEFINE(VGIC_V2_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
DEFINE(VGIC_V2_CPU_MISR, offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
DEFINE(VGIC_V2_CPU_EISR, offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
DEFINE(VGIC_V2_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
DEFINE(VGIC_V2_CPU_APR, offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
DEFINE(VGIC_V2_CPU_LR, offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr));
#ifdef CONFIG_KVM_ARM_TIMER
DEFINE(VCPU_TIMER_CNTV_CTL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
Expand Down
4 changes: 1 addition & 3 deletions arch/arm/kernel/hyp-stub.S
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,7 @@ ENTRY(__hyp_stub_install_secondary)
mcr p15, 4, r7, c1, c1, 3 @ HSTR

THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE
#ifdef CONFIG_CPU_BIG_ENDIAN
orr r7, #(1 << 9) @ HSCTLR.EE
#endif
ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE
mcr p15, 4, r7, c1, c0, 0 @ HSCTLR

mrc p15, 4, r7, c1, c1, 1 @ HDCR
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ config KVM
select HAVE_KVM_CPU_RELAX_INTERCEPT
select KVM_MMIO
select KVM_ARM_HOST
depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN
depends on ARM_VIRT_EXT && ARM_LPAE
---help---
Support hosting virtualized guest machines. You will also
need to select one or more of the processor modules below.
Expand Down
1 change: 1 addition & 0 deletions arch/arm/kvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ obj-y += kvm-arm.o init.o interrupts.o
obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
37 changes: 0 additions & 37 deletions arch/arm/kvm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,6 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
}

void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
struct kvm_memory_slot *dont)
{
}

int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
unsigned long npages)
{
return 0;
}

/**
* kvm_arch_destroy_vm - destroy the VM data structure
Expand Down Expand Up @@ -225,33 +215,6 @@ long kvm_arch_dev_ioctl(struct file *filp,
return -EINVAL;
}

void kvm_arch_memslots_updated(struct kvm *kvm)
{
}

int kvm_arch_prepare_memory_region(struct kvm *kvm,
struct kvm_memory_slot *memslot,
struct kvm_userspace_memory_region *mem,
enum kvm_mr_change change)
{
return 0;
}

void kvm_arch_commit_memory_region(struct kvm *kvm,
struct kvm_userspace_memory_region *mem,
const struct kvm_memory_slot *old,
enum kvm_mr_change change)
{
}

void kvm_arch_flush_shadow_all(struct kvm *kvm)
{
}

void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
struct kvm_memory_slot *slot)
{
}

struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
Expand Down
Loading

0 comments on commit 5d57686

Please sign in to comment.