diff options
-rw-r--r-- | kernel-arm64.patch | 2435 | ||||
-rw-r--r-- | kernel.spec | 5 |
2 files changed, 78 insertions, 2362 deletions
diff --git a/kernel-arm64.patch b/kernel-arm64.patch index 6fb01f64c..0a8b9ea91 100644 --- a/kernel-arm64.patch +++ b/kernel-arm64.patch @@ -1,107 +1,49 @@ -diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt -index 85af34d..f3c05b5 100644 ---- a/Documentation/arm64/booting.txt -+++ b/Documentation/arm64/booting.txt -@@ -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. -diff --git a/Documentation/devicetree/bindings/arm/gic-v3.txt b/Documentation/devicetree/bindings/arm/gic-v3.txt -new file mode 100644 -index 0000000..33cd05e ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/gic-v3.txt -@@ -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>; -+ }; + .../devicetree/bindings/net/apm-xgene-enet.txt | 72 ++ + .../devicetree/bindings/pci/xgene-pci.txt | 52 ++ + MAINTAINERS | 15 + + arch/arm64/Kconfig | 19 +- + arch/arm64/boot/dts/apm-mustang.dts | 12 + + arch/arm64/boot/dts/apm-storm.dtsi | 208 ++++- + arch/arm64/include/asm/Kbuild | 1 + + arch/arm64/include/asm/elf.h | 3 +- + arch/arm64/include/asm/io.h | 3 +- + arch/arm64/include/asm/kvm_mmu.h | 12 +- + arch/arm64/include/asm/pci.h | 49 ++ + arch/arm64/kernel/Makefile | 1 + + arch/arm64/kernel/efi-stub.c | 16 +- + arch/arm64/kernel/efi.c | 11 + + arch/arm64/kernel/head.S | 6 +- + arch/arm64/kernel/pci.c | 38 + + arch/arm64/kernel/process.c | 6 + + arch/arm64/kernel/smp_spin_table.c | 21 +- + drivers/ata/ahci_xgene.c | 3 +- + drivers/irqchip/irq-gic.c | 32 +- + drivers/net/ethernet/Kconfig | 1 + + drivers/net/ethernet/Makefile | 1 + + drivers/net/ethernet/apm/Kconfig | 1 + + drivers/net/ethernet/apm/Makefile | 5 + + drivers/net/ethernet/apm/xgene/Kconfig | 9 + + drivers/net/ethernet/apm/xgene/Makefile | 6 + + .../net/ethernet/apm/xgene/xgene_enet_ethtool.c | 125 +++ + drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 747 ++++++++++++++++ + drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 375 ++++++++ + drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 962 +++++++++++++++++++++ + drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 107 +++ + drivers/of/address.c | 108 +++ + drivers/of/of_pci.c | 136 +++ + drivers/pci/host-bridge.c | 18 +- + drivers/pci/host/Kconfig | 10 + + drivers/pci/host/Makefile | 1 + + drivers/pci/host/pci-xgene.c | 725 ++++++++++++++++ + drivers/pci/pci.c | 37 + + drivers/pci/probe.c | 68 +- + include/asm-generic/io.h | 2 +- + include/linux/of_address.h | 14 +- + include/linux/of_pci.h | 10 + + include/linux/pci.h | 15 + + tools/perf/arch/arm64/include/perf_regs.h | 2 + + 44 files changed, 3992 insertions(+), 73 deletions(-) + diff --git a/Documentation/devicetree/bindings/net/apm-xgene-enet.txt b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt new file mode 100644 index 0000000..3e2a295 @@ -239,10 +181,10 @@ index 0000000..e19fdb8 + status = "ok"; + }; diff --git a/MAINTAINERS b/MAINTAINERS -index 0f066dd..5a10717 100644 +index 7e2eb4c..7bf051dd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -701,6 +701,14 @@ S: Maintained +@@ -719,6 +719,14 @@ S: Maintained F: drivers/net/appletalk/ F: net/appletalk/ @@ -257,7 +199,7 @@ index 0f066dd..5a10717 100644 APTINA CAMERA SENSOR PLL M: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> L: linux-media@vger.kernel.org -@@ -6861,6 +6869,13 @@ S: Maintained +@@ -6880,6 +6888,13 @@ S: Maintained F: Documentation/devicetree/bindings/pci/host-generic-pci.txt F: drivers/pci/host/pci-host-generic.c @@ -268,123 +210,14 @@ index 0f066dd..5a10717 100644 +S: Maintained +F: drivers/pci/host/pci-xgene.c + - PCMCIA SUBSYSTEM - P: Linux PCMCIA Team - L: linux-pcmcia@lists.infradead.org -diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h -index 193ceaf..d6d5227 100644 ---- a/arch/arm/include/asm/kvm_host.h -+++ b/arch/arm/include/asm/kvm_host.h -@@ -225,6 +225,11 @@ 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); - -diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c -index 85598b5..713e807 100644 ---- a/arch/arm/kernel/asm-offsets.c -+++ b/arch/arm/kernel/asm-offsets.c -@@ -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)); -diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile -index 789bca9..f7057ed 100644 ---- a/arch/arm/kvm/Makefile -+++ b/arch/arm/kvm/Makefile -@@ -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 -diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S -index 76af9302..e4eaf30 100644 ---- a/arch/arm/kvm/interrupts_head.S -+++ b/arch/arm/kvm/interrupts_head.S -@@ -421,14 +421,14 @@ vcpu .req r0 @ vcpu pointer always in r0 - ldr r9, [r2, #GICH_ELRSR1] - ldr r10, [r2, #GICH_APR] - -- str r3, [r11, #VGIC_CPU_HCR] -- str r4, [r11, #VGIC_CPU_VMCR] -- str r5, [r11, #VGIC_CPU_MISR] -- str r6, [r11, #VGIC_CPU_EISR] -- str r7, [r11, #(VGIC_CPU_EISR + 4)] -- str r8, [r11, #VGIC_CPU_ELRSR] -- str r9, [r11, #(VGIC_CPU_ELRSR + 4)] -- str r10, [r11, #VGIC_CPU_APR] -+ str r3, [r11, #VGIC_V2_CPU_HCR] -+ str r4, [r11, #VGIC_V2_CPU_VMCR] -+ str r5, [r11, #VGIC_V2_CPU_MISR] -+ str r6, [r11, #VGIC_V2_CPU_EISR] -+ str r7, [r11, #(VGIC_V2_CPU_EISR + 4)] -+ str r8, [r11, #VGIC_V2_CPU_ELRSR] -+ str r9, [r11, #(VGIC_V2_CPU_ELRSR + 4)] -+ str r10, [r11, #VGIC_V2_CPU_APR] - - /* Clear GICH_HCR */ - mov r5, #0 -@@ -436,7 +436,7 @@ vcpu .req r0 @ vcpu pointer always in r0 - - /* Save list registers */ - add r2, r2, #GICH_LR0 -- add r3, r11, #VGIC_CPU_LR -+ add r3, r11, #VGIC_V2_CPU_LR - ldr r4, [r11, #VGIC_CPU_NR_LR] - 1: ldr r6, [r2], #4 - str r6, [r3], #4 -@@ -463,9 +463,9 @@ vcpu .req r0 @ vcpu pointer always in r0 - add r11, vcpu, #VCPU_VGIC_CPU - - /* We only restore a minimal set of registers */ -- ldr r3, [r11, #VGIC_CPU_HCR] -- ldr r4, [r11, #VGIC_CPU_VMCR] -- ldr r8, [r11, #VGIC_CPU_APR] -+ ldr r3, [r11, #VGIC_V2_CPU_HCR] -+ ldr r4, [r11, #VGIC_V2_CPU_VMCR] -+ ldr r8, [r11, #VGIC_V2_CPU_APR] - - str r3, [r2, #GICH_HCR] - str r4, [r2, #GICH_VMCR] -@@ -473,7 +473,7 @@ vcpu .req r0 @ vcpu pointer always in r0 - - /* Restore list registers */ - add r2, r2, #GICH_LR0 -- add r3, r11, #VGIC_CPU_LR -+ add r3, r11, #VGIC_V2_CPU_LR - ldr r4, [r11, #VGIC_CPU_NR_LR] - 1: ldr r6, [r3], #4 - str r6, [r2], #4 + PCIE DRIVER FOR ST SPEAR13XX + M: Mohit Kumar <mohit.kumar@st.com> + L: linux-pci@vger.kernel.org diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index b0f9c9d..be54ce2 100644 +index fd4e81a..e8559bb 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -80,7 +80,7 @@ config MMU +@@ -81,7 +81,7 @@ config MMU def_bool y config NO_IOPORT_MAP @@ -393,7 +226,7 @@ index b0f9c9d..be54ce2 100644 config STACKTRACE_SUPPORT def_bool y -@@ -155,6 +155,23 @@ menu "Bus support" +@@ -156,6 +156,23 @@ menu "Bus support" config ARM_AMBA bool @@ -777,99 +610,8 @@ index e0ecdcf..dc34039 100644 #define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_32M)) static inline u8 inb(unsigned long addr) -diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h -index 3d69030..cc83520 100644 ---- a/arch/arm64/include/asm/kvm_arm.h -+++ b/arch/arm64/include/asm/kvm_arm.h -@@ -76,9 +76,10 @@ - */ - #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ - HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \ -- HCR_AMO | HCR_IMO | HCR_FMO | \ -- HCR_SWIO | HCR_TIDCP | HCR_RW) -+ HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW) - #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) -+#define HCR_INT_OVERRIDE (HCR_FMO | HCR_IMO) -+ - - /* Hyp System Control Register (SCTLR_EL2) bits */ - #define SCTLR_EL2_EE (1 << 25) -diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h -index 9fcd54b..a28c35b 100644 ---- a/arch/arm64/include/asm/kvm_asm.h -+++ b/arch/arm64/include/asm/kvm_asm.h -@@ -18,6 +18,8 @@ - #ifndef __ARM_KVM_ASM_H__ - #define __ARM_KVM_ASM_H__ - -+#include <asm/virt.h> -+ - /* - * 0 is reserved as an invalid value. - * Order *must* be kept in sync with the hyp switch code. -@@ -96,13 +98,21 @@ extern char __kvm_hyp_init_end[]; - - extern char __kvm_hyp_vector[]; - --extern char __kvm_hyp_code_start[]; --extern char __kvm_hyp_code_end[]; -+#define __kvm_hyp_code_start __hyp_text_start -+#define __kvm_hyp_code_end __hyp_text_end - - extern void __kvm_flush_vm_context(void); - extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa); - - extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); -+ -+extern u64 __vgic_v3_get_ich_vtr_el2(void); -+ -+extern char __save_vgic_v2_state[]; -+extern char __restore_vgic_v2_state[]; -+extern char __save_vgic_v3_state[]; -+extern char __restore_vgic_v3_state[]; -+ - #endif - - #endif /* __ARM_KVM_ASM_H__ */ -diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h -index 92242ce..4ae9213 100644 ---- a/arch/arm64/include/asm/kvm_host.h -+++ b/arch/arm64/include/asm/kvm_host.h -@@ -200,4 +200,32 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr, - hyp_stack_ptr, vector_ptr); - } - -+struct vgic_sr_vectors { -+ void *save_vgic; -+ void *restore_vgic; -+}; -+ -+static inline void vgic_arch_setup(const struct vgic_params *vgic) -+{ -+ extern struct vgic_sr_vectors __vgic_sr_vectors; -+ -+ switch(vgic->type) -+ { -+ case VGIC_V2: -+ __vgic_sr_vectors.save_vgic = __save_vgic_v2_state; -+ __vgic_sr_vectors.restore_vgic = __restore_vgic_v2_state; -+ break; -+ -+#ifdef CONFIG_ARM_GIC_V3 -+ case VGIC_V3: -+ __vgic_sr_vectors.save_vgic = __save_vgic_v3_state; -+ __vgic_sr_vectors.restore_vgic = __restore_vgic_v3_state; -+ break; -+#endif -+ -+ default: -+ BUG(); -+ } -+} -+ - #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h -index 7d29847..d7f77ff 100644 +index 8e138c7..f8c9385 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -122,8 +122,16 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) @@ -889,8 +631,8 @@ index 7d29847..d7f77ff 100644 + (__boundary - 1 < (end) - 1)? __boundary: (end); \ +}) - struct kvm; - + static inline bool kvm_page_empty(void *ptr) + { diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h new file mode 100644 index 0000000..3f7856e @@ -946,21 +688,6 @@ index 0000000..3f7856e + +#endif /* __KERNEL__ */ +#endif /* __ASM_PCI_H */ -diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h -index 215ad46..7a5df52 100644 ---- a/arch/arm64/include/asm/virt.h -+++ b/arch/arm64/include/asm/virt.h -@@ -50,6 +50,10 @@ static inline bool is_hyp_mode_mismatched(void) - return __boot_cpu_mode[0] != __boot_cpu_mode[1]; - } - -+/* The section containing the hypervisor text */ -+extern char __hyp_text_start[]; -+extern char __hyp_text_end[]; -+ - #endif /* __ASSEMBLY__ */ - - #endif /* ! __ASM__VIRT_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index df7ef87..1ed5a06 100644 --- a/arch/arm64/kernel/Makefile @@ -973,42 +700,6 @@ index df7ef87..1ed5a06 100644 obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) -diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c -index 646f888..e74654c 100644 ---- a/arch/arm64/kernel/asm-offsets.c -+++ b/arch/arm64/kernel/asm-offsets.c -@@ -129,13 +129,24 @@ int main(void) - DEFINE(KVM_TIMER_ENABLED, offsetof(struct kvm, arch.timer.enabled)); - DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm)); - 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_SAVE_FN, offsetof(struct vgic_sr_vectors, save_vgic)); -+ DEFINE(VGIC_RESTORE_FN, offsetof(struct vgic_sr_vectors, restore_vgic)); -+ DEFINE(VGIC_SR_VECTOR_SZ, sizeof(struct vgic_sr_vectors)); -+ 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_V3_CPU_HCR, offsetof(struct vgic_cpu, vgic_v3.vgic_hcr)); -+ DEFINE(VGIC_V3_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr)); -+ DEFINE(VGIC_V3_CPU_MISR, offsetof(struct vgic_cpu, vgic_v3.vgic_misr)); -+ DEFINE(VGIC_V3_CPU_EISR, offsetof(struct vgic_cpu, vgic_v3.vgic_eisr)); -+ DEFINE(VGIC_V3_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v3.vgic_elrsr)); -+ DEFINE(VGIC_V3_CPU_AP0R, offsetof(struct vgic_cpu, vgic_v3.vgic_ap0r)); -+ DEFINE(VGIC_V3_CPU_AP1R, offsetof(struct vgic_cpu, vgic_v3.vgic_ap1r)); -+ DEFINE(VGIC_V3_CPU_LR, offsetof(struct vgic_cpu, vgic_v3.vgic_lr)); - DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr)); - DEFINE(KVM_VTTBR, offsetof(struct kvm, arch.vttbr)); - DEFINE(KVM_VGIC_VCTRL, offsetof(struct kvm, arch.vgic.vctrl_base)); diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c index 1317fef..d27dd98 100644 --- a/arch/arm64/kernel/efi-stub.c @@ -1214,635 +905,6 @@ index 0347d38..70181c1 100644 return 0; } -diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile -index 72a9fd5..32a0961 100644 ---- a/arch/arm64/kvm/Makefile -+++ b/arch/arm64/kvm/Makefile -@@ -20,4 +20,8 @@ kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o - kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o - - kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o -+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o -+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o -+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o -+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o - kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o -diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S -index b0d1512..5945f3b 100644 ---- a/arch/arm64/kvm/hyp.S -+++ b/arch/arm64/kvm/hyp.S -@@ -16,7 +16,6 @@ - */ - - #include <linux/linkage.h> --#include <linux/irqchip/arm-gic.h> - - #include <asm/assembler.h> - #include <asm/memory.h> -@@ -36,9 +35,6 @@ - .pushsection .hyp.text, "ax" - .align PAGE_SHIFT - --__kvm_hyp_code_start: -- .globl __kvm_hyp_code_start -- - .macro save_common_regs - // x2: base address for cpu context - // x3: tmp register -@@ -339,11 +335,8 @@ __kvm_hyp_code_start: - .endm - - .macro activate_traps -- ldr x2, [x0, #VCPU_IRQ_LINES] -- ldr x1, [x0, #VCPU_HCR_EL2] -- orr x2, x2, x1 -- msr hcr_el2, x2 -- -+ ldr x2, [x0, #VCPU_HCR_EL2] -+ msr hcr_el2, x2 - ldr x2, =(CPTR_EL2_TTA) - msr cptr_el2, x2 - -@@ -379,100 +372,33 @@ __kvm_hyp_code_start: - .endm - - /* -- * Save the VGIC CPU state into memory -- * x0: Register pointing to VCPU struct -- * Do not corrupt x1!!! -+ * Call into the vgic backend for state saving - */ - .macro save_vgic_state -- /* Get VGIC VCTRL base into x2 */ -- ldr x2, [x0, #VCPU_KVM] -- kern_hyp_va x2 -- ldr x2, [x2, #KVM_VGIC_VCTRL] -- kern_hyp_va x2 -- cbz x2, 2f // disabled -- -- /* Compute the address of struct vgic_cpu */ -- add x3, x0, #VCPU_VGIC_CPU -- -- /* Save all interesting registers */ -- ldr w4, [x2, #GICH_HCR] -- ldr w5, [x2, #GICH_VMCR] -- ldr w6, [x2, #GICH_MISR] -- ldr w7, [x2, #GICH_EISR0] -- ldr w8, [x2, #GICH_EISR1] -- ldr w9, [x2, #GICH_ELRSR0] -- ldr w10, [x2, #GICH_ELRSR1] -- ldr w11, [x2, #GICH_APR] --CPU_BE( rev w4, w4 ) --CPU_BE( rev w5, w5 ) --CPU_BE( rev w6, w6 ) --CPU_BE( rev w7, w7 ) --CPU_BE( rev w8, w8 ) --CPU_BE( rev w9, w9 ) --CPU_BE( rev w10, w10 ) --CPU_BE( rev w11, w11 ) -- -- str w4, [x3, #VGIC_CPU_HCR] -- str w5, [x3, #VGIC_CPU_VMCR] -- str w6, [x3, #VGIC_CPU_MISR] -- str w7, [x3, #VGIC_CPU_EISR] -- str w8, [x3, #(VGIC_CPU_EISR + 4)] -- str w9, [x3, #VGIC_CPU_ELRSR] -- str w10, [x3, #(VGIC_CPU_ELRSR + 4)] -- str w11, [x3, #VGIC_CPU_APR] -- -- /* Clear GICH_HCR */ -- str wzr, [x2, #GICH_HCR] -- -- /* Save list registers */ -- add x2, x2, #GICH_LR0 -- ldr w4, [x3, #VGIC_CPU_NR_LR] -- add x3, x3, #VGIC_CPU_LR --1: ldr w5, [x2], #4 --CPU_BE( rev w5, w5 ) -- str w5, [x3], #4 -- sub w4, w4, #1 -- cbnz w4, 1b --2: -+ adr x24, __vgic_sr_vectors -+ ldr x24, [x24, VGIC_SAVE_FN] -+ kern_hyp_va x24 -+ blr x24 -+ mrs x24, hcr_el2 -+ mov x25, #HCR_INT_OVERRIDE -+ neg x25, x25 -+ and x24, x24, x25 -+ msr hcr_el2, x24 - .endm - - /* -- * Restore the VGIC CPU state from memory -- * x0: Register pointing to VCPU struct -+ * Call into the vgic backend for state restoring - */ - .macro restore_vgic_state -- /* Get VGIC VCTRL base into x2 */ -- ldr x2, [x0, #VCPU_KVM] -- kern_hyp_va x2 -- ldr x2, [x2, #KVM_VGIC_VCTRL] -- kern_hyp_va x2 -- cbz x2, 2f // disabled -- -- /* Compute the address of struct vgic_cpu */ -- add x3, x0, #VCPU_VGIC_CPU -- -- /* We only restore a minimal set of registers */ -- ldr w4, [x3, #VGIC_CPU_HCR] -- ldr w5, [x3, #VGIC_CPU_VMCR] -- ldr w6, [x3, #VGIC_CPU_APR] --CPU_BE( rev w4, w4 ) --CPU_BE( rev w5, w5 ) --CPU_BE( rev w6, w6 ) -- -- str w4, [x2, #GICH_HCR] -- str w5, [x2, #GICH_VMCR] -- str w6, [x2, #GICH_APR] -- -- /* Restore list registers */ -- add x2, x2, #GICH_LR0 -- ldr w4, [x3, #VGIC_CPU_NR_LR] -- add x3, x3, #VGIC_CPU_LR --1: ldr w5, [x3], #4 --CPU_BE( rev w5, w5 ) -- str w5, [x2], #4 -- sub w4, w4, #1 -- cbnz w4, 1b --2: -+ mrs x24, hcr_el2 -+ ldr x25, [x0, #VCPU_IRQ_LINES] -+ orr x24, x24, #HCR_INT_OVERRIDE -+ orr x24, x24, x25 -+ msr hcr_el2, x24 -+ adr x24, __vgic_sr_vectors -+ ldr x24, [x24, #VGIC_RESTORE_FN] -+ kern_hyp_va x24 -+ blr x24 - .endm - - .macro save_timer_state -@@ -653,6 +579,12 @@ ENTRY(__kvm_flush_vm_context) - ret - ENDPROC(__kvm_flush_vm_context) - -+ // struct vgic_sr_vectors __vgi_sr_vectors; -+ .align 3 -+ENTRY(__vgic_sr_vectors) -+ .skip VGIC_SR_VECTOR_SZ -+ENDPROC(__vgic_sr_vectors) -+ - __kvm_hyp_panic: - // Guess the context by looking at VTTBR: - // If zero, then we're already a host. -@@ -880,7 +812,4 @@ ENTRY(__kvm_hyp_vector) - ventry el1_error_invalid // Error 32-bit EL1 - ENDPROC(__kvm_hyp_vector) - --__kvm_hyp_code_end: -- .globl __kvm_hyp_code_end -- - .popsection -diff --git a/arch/arm64/kvm/vgic-v2-switch.S b/arch/arm64/kvm/vgic-v2-switch.S -new file mode 100644 -index 0000000..ae21177 ---- /dev/null -+++ b/arch/arm64/kvm/vgic-v2-switch.S -@@ -0,0 +1,133 @@ -+/* -+ * Copyright (C) 2012,2013 - ARM Ltd -+ * Author: Marc Zyngier <marc.zyngier@arm.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see <http://www.gnu.org/licenses/>. -+ */ -+ -+#include <linux/linkage.h> -+#include <linux/irqchip/arm-gic.h> -+ -+#include <asm/assembler.h> -+#include <asm/memory.h> -+#include <asm/asm-offsets.h> -+#include <asm/kvm.h> -+#include <asm/kvm_asm.h> -+#include <asm/kvm_arm.h> -+#include <asm/kvm_mmu.h> -+ -+ .text -+ .pushsection .hyp.text, "ax" -+ -+/* -+ * Save the VGIC CPU state into memory -+ * x0: Register pointing to VCPU struct -+ * Do not corrupt x1!!! -+ */ -+ENTRY(__save_vgic_v2_state) -+__save_vgic_v2_state: -+ /* Get VGIC VCTRL base into x2 */ -+ ldr x2, [x0, #VCPU_KVM] -+ kern_hyp_va x2 -+ ldr x2, [x2, #KVM_VGIC_VCTRL] -+ kern_hyp_va x2 -+ cbz x2, 2f // disabled -+ -+ /* Compute the address of struct vgic_cpu */ -+ add x3, x0, #VCPU_VGIC_CPU -+ -+ /* Save all interesting registers */ -+ ldr w4, [x2, #GICH_HCR] -+ ldr w5, [x2, #GICH_VMCR] -+ ldr w6, [x2, #GICH_MISR] -+ ldr w7, [x2, #GICH_EISR0] -+ ldr w8, [x2, #GICH_EISR1] -+ ldr w9, [x2, #GICH_ELRSR0] -+ ldr w10, [x2, #GICH_ELRSR1] -+ ldr w11, [x2, #GICH_APR] -+CPU_BE( rev w4, w4 ) -+CPU_BE( rev w5, w5 ) -+CPU_BE( rev w6, w6 ) -+CPU_BE( rev w7, w7 ) -+CPU_BE( rev w8, w8 ) -+CPU_BE( rev w9, w9 ) -+CPU_BE( rev w10, w10 ) -+CPU_BE( rev w11, w11 ) -+ -+ str w4, [x3, #VGIC_V2_CPU_HCR] -+ str w5, [x3, #VGIC_V2_CPU_VMCR] -+ str w6, [x3, #VGIC_V2_CPU_MISR] -+ str w7, [x3, #VGIC_V2_CPU_EISR] -+ str w8, [x3, #(VGIC_V2_CPU_EISR + 4)] -+ str w9, [x3, #VGIC_V2_CPU_ELRSR] -+ str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)] -+ str w11, [x3, #VGIC_V2_CPU_APR] -+ -+ /* Clear GICH_HCR */ -+ str wzr, [x2, #GICH_HCR] -+ -+ /* Save list registers */ -+ add x2, x2, #GICH_LR0 -+ ldr w4, [x3, #VGIC_CPU_NR_LR] -+ add x3, x3, #VGIC_V2_CPU_LR -+1: ldr w5, [x2], #4 -+CPU_BE( rev w5, w5 ) -+ str w5, [x3], #4 -+ sub w4, w4, #1 -+ cbnz w4, 1b -+2: -+ ret -+ENDPROC(__save_vgic_v2_state) -+ -+/* -+ * Restore the VGIC CPU state from memory -+ * x0: Register pointing to VCPU struct -+ */ -+ENTRY(__restore_vgic_v2_state) -+__restore_vgic_v2_state: -+ /* Get VGIC VCTRL base into x2 */ -+ ldr x2, [x0, #VCPU_KVM] -+ kern_hyp_va x2 -+ ldr x2, [x2, #KVM_VGIC_VCTRL] -+ kern_hyp_va x2 -+ cbz x2, 2f // disabled -+ -+ /* Compute the address of struct vgic_cpu */ -+ add x3, x0, #VCPU_VGIC_CPU -+ -+ /* We only restore a minimal set of registers */ -+ ldr w4, [x3, #VGIC_V2_CPU_HCR] -+ ldr w5, [x3, #VGIC_V2_CPU_VMCR] -+ ldr w6, [x3, #VGIC_V2_CPU_APR] -+CPU_BE( rev w4, w4 ) -+CPU_BE( rev w5, w5 ) -+CPU_BE( rev w6, w6 ) -+ -+ str w4, [x2, #GICH_HCR] -+ str w5, [x2, #GICH_VMCR] -+ str w6, [x2, #GICH_APR] -+ -+ /* Restore list registers */ -+ add x2, x2, #GICH_LR0 -+ ldr w4, [x3, #VGIC_CPU_NR_LR] -+ add x3, x3, #VGIC_V2_CPU_LR -+1: ldr w5, [x3], #4 -+CPU_BE( rev w5, w5 ) -+ str w5, [x2], #4 -+ sub w4, w4, #1 -+ cbnz w4, 1b -+2: -+ ret -+ENDPROC(__restore_vgic_v2_state) -+ -+ .popsection -diff --git a/arch/arm64/kvm/vgic-v3-switch.S b/arch/arm64/kvm/vgic-v3-switch.S -new file mode 100644 -index 0000000..d160469 ---- /dev/null -+++ b/arch/arm64/kvm/vgic-v3-switch.S -@@ -0,0 +1,267 @@ -+/* -+ * Copyright (C) 2012,2013 - ARM Ltd -+ * Author: Marc Zyngier <marc.zyngier@arm.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see <http://www.gnu.org/licenses/>. -+ */ -+ -+#include <linux/linkage.h> -+#include <linux/irqchip/arm-gic-v3.h> -+ -+#include <asm/assembler.h> -+#include <asm/memory.h> -+#include <asm/asm-offsets.h> -+#include <asm/kvm.h> -+#include <asm/kvm_asm.h> -+#include <asm/kvm_arm.h> -+ -+ .text -+ .pushsection .hyp.text, "ax" -+ -+/* -+ * We store LRs in reverse order to let the CPU deal with streaming -+ * access. Use this macro to make it look saner... -+ */ -+#define LR_OFFSET(n) (VGIC_V3_CPU_LR + (15 - n) * 8) -+ -+/* -+ * Save the VGIC CPU state into memory -+ * x0: Register pointing to VCPU struct -+ * Do not corrupt x1!!! -+ */ -+.macro save_vgic_v3_state -+ // Compute the address of struct vgic_cpu -+ add x3, x0, #VCPU_VGIC_CPU -+ -+ // Make sure stores to the GIC via the memory mapped interface -+ // are now visible to the system register interface -+ dsb st -+ -+ // Save all interesting registers -+ mrs_s x4, ICH_HCR_EL2 -+ mrs_s x5, ICH_VMCR_EL2 -+ mrs_s x6, ICH_MISR_EL2 -+ mrs_s x7, ICH_EISR_EL2 -+ mrs_s x8, ICH_ELSR_EL2 -+ -+ str w4, [x3, #VGIC_V3_CPU_HCR] -+ str w5, [x3, #VGIC_V3_CPU_VMCR] -+ str w6, [x3, #VGIC_V3_CPU_MISR] -+ str w7, [x3, #VGIC_V3_CPU_EISR] -+ str w8, [x3, #VGIC_V3_CPU_ELRSR] -+ -+ msr_s ICH_HCR_EL2, xzr -+ -+ mrs_s x21, ICH_VTR_EL2 -+ mvn w22, w21 -+ ubfiz w23, w22, 2, 4 // w23 = (15 - ListRegs) * 4 -+ -+ adr x24, 1f -+ add x24, x24, x23 -+ br x24 -+ -+1: -+ mrs_s x20, ICH_LR15_EL2 -+ mrs_s x19, ICH_LR14_EL2 -+ mrs_s x18, ICH_LR13_EL2 -+ mrs_s x17, ICH_LR12_EL2 -+ mrs_s x16, ICH_LR11_EL2 -+ mrs_s x15, ICH_LR10_EL2 -+ mrs_s x14, ICH_LR9_EL2 -+ mrs_s x13, ICH_LR8_EL2 -+ mrs_s x12, ICH_LR7_EL2 -+ mrs_s x11, ICH_LR6_EL2 -+ mrs_s x10, ICH_LR5_EL2 -+ mrs_s x9, ICH_LR4_EL2 -+ mrs_s x8, ICH_LR3_EL2 -+ mrs_s x7, ICH_LR2_EL2 -+ mrs_s x6, ICH_LR1_EL2 -+ mrs_s x5, ICH_LR0_EL2 -+ -+ adr x24, 1f -+ add x24, x24, x23 -+ br x24 -+ -+1: -+ str x20, [x3, #LR_OFFSET(15)] -+ str x19, [x3, #LR_OFFSET(14)] -+ str x18, [x3, #LR_OFFSET(13)] -+ str x17, [x3, #LR_OFFSET(12)] -+ str x16, [x3, #LR_OFFSET(11)] -+ str x15, [x3, #LR_OFFSET(10)] -+ str x14, [x3, #LR_OFFSET(9)] -+ str x13, [x3, #LR_OFFSET(8)] -+ str x12, [x3, #LR_OFFSET(7)] -+ str x11, [x3, #LR_OFFSET(6)] -+ str x10, [x3, #LR_OFFSET(5)] -+ str x9, [x3, #LR_OFFSET(4)] -+ str x8, [x3, #LR_OFFSET(3)] -+ str x7, [x3, #LR_OFFSET(2)] -+ str x6, [x3, #LR_OFFSET(1)] -+ str x5, [x3, #LR_OFFSET(0)] -+ -+ tbnz w21, #29, 6f // 6 bits -+ tbz w21, #30, 5f // 5 bits -+ // 7 bits -+ mrs_s x20, ICH_AP0R3_EL2 -+ str w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)] -+ mrs_s x19, ICH_AP0R2_EL2 -+ str w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)] -+6: mrs_s x18, ICH_AP0R1_EL2 -+ str w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)] -+5: mrs_s x17, ICH_AP0R0_EL2 -+ str w17, [x3, #VGIC_V3_CPU_AP0R] -+ -+ tbnz w21, #29, 6f // 6 bits -+ tbz w21, #30, 5f // 5 bits -+ // 7 bits -+ mrs_s x20, ICH_AP1R3_EL2 -+ str w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)] -+ mrs_s x19, ICH_AP1R2_EL2 -+ str w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)] -+6: mrs_s x18, ICH_AP1R1_EL2 -+ str w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)] -+5: mrs_s x17, ICH_AP1R0_EL2 -+ str w17, [x3, #VGIC_V3_CPU_AP1R] -+ -+ // Restore SRE_EL1 access and re-enable SRE at EL1. -+ mrs_s x5, ICC_SRE_EL2 -+ orr x5, x5, #ICC_SRE_EL2_ENABLE -+ msr_s ICC_SRE_EL2, x5 -+ isb -+ mov x5, #1 -+ msr_s ICC_SRE_EL1, x5 -+.endm -+ -+/* -+ * Restore the VGIC CPU state from memory -+ * x0: Register pointing to VCPU struct -+ */ -+.macro restore_vgic_v3_state -+ // Disable SRE_EL1 access. Necessary, otherwise -+ // ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens... -+ msr_s ICC_SRE_EL1, xzr -+ isb -+ -+ // Compute the address of struct vgic_cpu -+ add x3, x0, #VCPU_VGIC_CPU -+ -+ // Restore all interesting registers -+ ldr w4, [x3, #VGIC_V3_CPU_HCR] -+ ldr w5, [x3, #VGIC_V3_CPU_VMCR] -+ -+ msr_s ICH_HCR_EL2, x4 -+ msr_s ICH_VMCR_EL2, x5 -+ -+ mrs_s x21, ICH_VTR_EL2 -+ -+ tbnz w21, #29, 6f // 6 bits -+ tbz w21, #30, 5f // 5 bits -+ // 7 bits -+ ldr w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)] -+ msr_s ICH_AP1R3_EL2, x20 -+ ldr w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)] -+ msr_s ICH_AP1R2_EL2, x19 -+6: ldr w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)] -+ msr_s ICH_AP1R1_EL2, x18 -+5: ldr w17, [x3, #VGIC_V3_CPU_AP1R] -+ msr_s ICH_AP1R0_EL2, x17 -+ -+ tbnz w21, #29, 6f // 6 bits -+ tbz w21, #30, 5f // 5 bits -+ // 7 bits -+ ldr w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)] -+ msr_s ICH_AP0R3_EL2, x20 -+ ldr w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)] -+ msr_s ICH_AP0R2_EL2, x19 -+6: ldr w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)] -+ msr_s ICH_AP0R1_EL2, x18 -+5: ldr w17, [x3, #VGIC_V3_CPU_AP0R] -+ msr_s ICH_AP0R0_EL2, x17 -+ -+ and w22, w21, #0xf -+ mvn w22, w21 -+ ubfiz w23, w22, 2, 4 // w23 = (15 - ListRegs) * 4 -+ -+ adr x24, 1f -+ add x24, x24, x23 -+ br x24 -+ -+1: -+ ldr x20, [x3, #LR_OFFSET(15)] -+ ldr x19, [x3, #LR_OFFSET(14)] -+ ldr x18, [x3, #LR_OFFSET(13)] -+ ldr x17, [x3, #LR_OFFSET(12)] -+ ldr x16, [x3, #LR_OFFSET(11)] -+ ldr x15, [x3, #LR_OFFSET(10)] -+ ldr x14, [x3, #LR_OFFSET(9)] -+ ldr x13, [x3, #LR_OFFSET(8)] -+ ldr x12, [x3, #LR_OFFSET(7)] -+ ldr x11, [x3, #LR_OFFSET(6)] -+ ldr x10, [x3, #LR_OFFSET(5)] -+ ldr x9, [x3, #LR_OFFSET(4)] -+ ldr x8, [x3, #LR_OFFSET(3)] -+ ldr x7, [x3, #LR_OFFSET(2)] -+ ldr x6, [x3, #LR_OFFSET(1)] -+ ldr x5, [x3, #LR_OFFSET(0)] -+ -+ adr x24, 1f -+ add x24, x24, x23 -+ br x24 -+ -+1: -+ msr_s ICH_LR15_EL2, x20 -+ msr_s ICH_LR14_EL2, x19 -+ msr_s ICH_LR13_EL2, x18 -+ msr_s ICH_LR12_EL2, x17 -+ msr_s ICH_LR11_EL2, x16 -+ msr_s ICH_LR10_EL2, x15 -+ msr_s ICH_LR9_EL2, x14 -+ msr_s ICH_LR8_EL2, x13 -+ msr_s ICH_LR7_EL2, x12 -+ msr_s ICH_LR6_EL2, x11 -+ msr_s ICH_LR5_EL2, x10 -+ msr_s ICH_LR4_EL2, x9 -+ msr_s ICH_LR3_EL2, x8 -+ msr_s ICH_LR2_EL2, x7 -+ msr_s ICH_LR1_EL2, x6 -+ msr_s ICH_LR0_EL2, x5 -+ -+ // Ensure that the above will have reached the -+ // (re)distributors. This ensure the guest will read -+ // the correct values from the memory-mapped interface. -+ isb -+ dsb sy -+ -+ // Prevent the guest from touching the GIC system registers -+ mrs_s x5, ICC_SRE_EL2 -+ and x5, x5, #~ICC_SRE_EL2_ENABLE -+ msr_s ICC_SRE_EL2, x5 -+.endm -+ -+ENTRY(__save_vgic_v3_state) -+ save_vgic_v3_state -+ ret -+ENDPROC(__save_vgic_v3_state) -+ -+ENTRY(__restore_vgic_v3_state) -+ restore_vgic_v3_state -+ ret -+ENDPROC(__restore_vgic_v3_state) -+ -+ENTRY(__vgic_v3_get_ich_vtr_el2) -+ mrs_s x0, ICH_VTR_EL2 -+ ret -+ENDPROC(__vgic_v3_get_ich_vtr_el2) -+ -+ .popsection -diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c -index 71c52bc..a149c67 100644 ---- a/arch/ia64/kernel/time.c -+++ b/arch/ia64/kernel/time.c -@@ -384,21 +384,6 @@ static struct irqaction timer_irqaction = { - .name = "timer" - }; - --static struct platform_device rtc_efi_dev = { -- .name = "rtc-efi", -- .id = -1, --}; -- --static int __init rtc_init(void) --{ -- if (platform_device_register(&rtc_efi_dev) < 0) -- printk(KERN_ERR "unable to register rtc device...\n"); -- -- /* not necessarily an error */ -- return 0; --} --module_init(rtc_init); -- - void read_persistent_clock(struct timespec *ts) - { - efi_gettimeofday(ts); diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index bc28111..00e5a0c 100644 --- a/drivers/ata/ahci_xgene.c @@ -1858,10 +920,10 @@ index bc28111..00e5a0c 100644 rc = ahci_qc_issue(qc); diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c -index 9c1f883..1ddfdde 100644 +index 4b959e6..c36c7ab55 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c -@@ -383,6 +383,7 @@ static void gic_cpu_init(struct gic_chip_data *gic) +@@ -381,6 +381,7 @@ static void gic_cpu_init(struct gic_chip_data *gic) void __iomem *dist_base = gic_data_dist_base(gic); void __iomem *base = gic_data_cpu_base(gic); unsigned int cpu_mask, cpu = smp_processor_id(); @@ -1869,7 +931,7 @@ index 9c1f883..1ddfdde 100644 int i; /* -@@ -403,13 +404,29 @@ static void gic_cpu_init(struct gic_chip_data *gic) +@@ -401,13 +402,29 @@ static void gic_cpu_init(struct gic_chip_data *gic) gic_cpu_config(dist_base, NULL); writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); @@ -1901,7 +963,7 @@ index 9c1f883..1ddfdde 100644 } #ifdef CONFIG_CPU_PM -@@ -520,6 +537,7 @@ static void gic_cpu_restore(unsigned int gic_nr) +@@ -518,6 +535,7 @@ static void gic_cpu_restore(unsigned int gic_nr) { int i; u32 *ptr; @@ -1909,7 +971,7 @@ index 9c1f883..1ddfdde 100644 void __iomem *dist_base; void __iomem *cpu_base; -@@ -544,7 +562,15 @@ static void gic_cpu_restore(unsigned int gic_nr) +@@ -542,7 +560,15 @@ static void gic_cpu_restore(unsigned int gic_nr) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); @@ -4342,7 +3404,7 @@ index 0000000..f4f7e4a + +#endif /* __XGENE_ENET_MAIN_H__ */ diff --git a/drivers/of/address.c b/drivers/of/address.c -index 5edfcb0..cbbaed2 100644 +index e371825..5eaadae 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -5,6 +5,7 @@ @@ -4426,7 +3488,7 @@ index 5edfcb0..cbbaed2 100644 } static int __of_address_to_resource(struct device_node *dev, -@@ -811,3 +872,50 @@ bool of_dma_is_coherent(struct device_node *np) +@@ -847,3 +908,50 @@ bool of_dma_is_coherent(struct device_node *np) return false; } EXPORT_SYMBOL_GPL(of_dma_is_coherent); @@ -4670,10 +3732,10 @@ index 0e5f3c9..54ceafd 100644 + return 0; +} diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig -index 21df477..3b988a2 100644 +index 2d8a4d0..76daa18 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig -@@ -46,4 +46,14 @@ config PCI_HOST_GENERIC +@@ -46,6 +46,16 @@ config PCI_HOST_GENERIC Say Y here if you want to support a simple generic PCI host controller, such as the one emulated by kvmtool. @@ -4687,16 +3749,19 @@ index 21df477..3b988a2 100644 + There are 5 internal PCIe ports available. Each port is GEN3 capable + and have varied lanes from x1 to x8. + - endmenu + config PCIE_SPEAR13XX + tristate "STMicroelectronics SPEAr PCIe controller" + depends on ARCH_SPEAR13XX diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile -index 611ba4b..0801606 100644 +index 0daec79..6990412 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile -@@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o +@@ -6,4 +6,5 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o +obj-$(CONFIG_PCI_XGENE) += pci-xgene.o + obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c new file mode 100644 index 0000000..7bf4ac7 @@ -5622,71 +4687,6 @@ index e3cf8a2..abf5e82 100644 } int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max) -diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig -index 0754f5c..4478a59 100644 ---- a/drivers/rtc/Kconfig -+++ b/drivers/rtc/Kconfig -@@ -789,7 +789,7 @@ config RTC_DRV_DA9063 - - config RTC_DRV_EFI - tristate "EFI RTC" -- depends on IA64 -+ depends on EFI - help - If you say yes here you will get support for the EFI - Real Time Clock. -diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile -index 70347d0..f1dfc36 100644 ---- a/drivers/rtc/Makefile -+++ b/drivers/rtc/Makefile -@@ -10,6 +10,10 @@ obj-$(CONFIG_RTC_SYSTOHC) += systohc.o - obj-$(CONFIG_RTC_CLASS) += rtc-core.o - rtc-core-y := class.o interface.o - -+ifdef CONFIG_RTC_DRV_EFI -+rtc-core-y += rtc-efi-platform.o -+endif -+ - rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o - rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o - rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o -diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c -new file mode 100644 -index 0000000..b40fbe3 ---- /dev/null -+++ b/drivers/rtc/rtc-efi-platform.c -@@ -0,0 +1,31 @@ -+/* -+ * Moved from arch/ia64/kernel/time.c -+ * -+ * Copyright (C) 1998-2003 Hewlett-Packard Co -+ * Stephane Eranian <eranian@hpl.hp.com> -+ * David Mosberger <davidm@hpl.hp.com> -+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> -+ * Copyright (C) 1999-2000 VA Linux Systems -+ * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com> -+ */ -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/efi.h> -+#include <linux/platform_device.h> -+ -+static struct platform_device rtc_efi_dev = { -+ .name = "rtc-efi", -+ .id = -1, -+}; -+ -+static int __init rtc_init(void) -+{ -+ if (efi_enabled(EFI_RUNTIME_SERVICES)) -+ if (platform_device_register(&rtc_efi_dev) < 0) -+ pr_err("unable to register rtc device...\n"); -+ -+ /* not necessarily an error */ -+ return 0; -+} -+module_init(rtc_init); diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 975e1cc..2e2161b 100644 --- a/include/asm-generic/io.h @@ -5700,184 +4700,8 @@ index 975e1cc..2e2161b 100644 } static inline void ioport_unmap(void __iomem *p) -diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h -index f27000f..35b0c12 100644 ---- a/include/kvm/arm_vgic.h -+++ b/include/kvm/arm_vgic.h -@@ -24,7 +24,6 @@ - #include <linux/irqreturn.h> - #include <linux/spinlock.h> - #include <linux/types.h> --#include <linux/irqchip/arm-gic.h> - - #define VGIC_NR_IRQS 256 - #define VGIC_NR_SGIS 16 -@@ -32,7 +31,9 @@ - #define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS) - #define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS) - #define VGIC_MAX_CPUS KVM_MAX_VCPUS --#define VGIC_MAX_LRS (1 << 6) -+ -+#define VGIC_V2_MAX_LRS (1 << 6) -+#define VGIC_V3_MAX_LRS 16 - - /* Sanity checks... */ - #if (VGIC_MAX_CPUS > 8) -@@ -68,9 +69,62 @@ struct vgic_bytemap { - u32 shared[VGIC_NR_SHARED_IRQS / 4]; - }; - -+struct kvm_vcpu; -+ -+enum vgic_type { -+ VGIC_V2, /* Good ol' GICv2 */ -+ VGIC_V3, /* New fancy GICv3 */ -+}; -+ -+#define LR_STATE_PENDING (1 << 0) -+#define LR_STATE_ACTIVE (1 << 1) -+#define LR_STATE_MASK (3 << 0) -+#define LR_EOI_INT (1 << 2) -+ -+struct vgic_lr { -+ u16 irq; -+ u8 source; -+ u8 state; -+}; -+ -+struct vgic_vmcr { -+ u32 ctlr; -+ u32 abpr; -+ u32 bpr; -+ u32 pmr; -+}; -+ -+struct vgic_ops { -+ struct vgic_lr (*get_lr)(const struct kvm_vcpu *, int); -+ void (*set_lr)(struct kvm_vcpu *, int, struct vgic_lr); -+ void (*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr); -+ u64 (*get_elrsr)(const struct kvm_vcpu *vcpu); -+ u64 (*get_eisr)(const struct kvm_vcpu *vcpu); -+ u32 (*get_interrupt_status)(const struct kvm_vcpu *vcpu); -+ void (*enable_underflow)(struct kvm_vcpu *vcpu); -+ void (*disable_underflow)(struct kvm_vcpu *vcpu); -+ void (*get_vmcr)(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); -+ void (*set_vmcr)(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); -+ void (*enable)(struct kvm_vcpu *vcpu); -+}; -+ -+struct vgic_params { -+ /* vgic type */ -+ enum vgic_type type; -+ /* Physical address of vgic virtual cpu interface */ -+ phys_addr_t vcpu_base; -+ /* Number of list registers */ -+ u32 nr_lr; -+ /* Interrupt number */ -+ unsigned int maint_irq; -+ /* Virtual control interface base address */ -+ void __iomem *vctrl_base; -+}; -+ - struct vgic_dist { - #ifdef CONFIG_KVM_ARM_VGIC - spinlock_t lock; -+ bool in_kernel; - bool ready; - - /* Virtual control interface mapping */ -@@ -110,6 +164,29 @@ struct vgic_dist { - #endif - }; - -+struct vgic_v2_cpu_if { -+ u32 vgic_hcr; -+ u32 vgic_vmcr; -+ u32 vgic_misr; /* Saved only */ -+ u32 vgic_eisr[2]; /* Saved only */ -+ u32 vgic_elrsr[2]; /* Saved only */ -+ u32 vgic_apr; -+ u32 vgic_lr[VGIC_V2_MAX_LRS]; -+}; -+ -+struct vgic_v3_cpu_if { -+#ifdef CONFIG_ARM_GIC_V3 -+ u32 vgic_hcr; -+ u32 vgic_vmcr; -+ u32 vgic_misr; /* Saved only */ -+ u32 vgic_eisr; /* Saved only */ -+ u32 vgic_elrsr; /* Saved only */ -+ u32 vgic_ap0r[4]; -+ u32 vgic_ap1r[4]; -+ u64 vgic_lr[VGIC_V3_MAX_LRS]; -+#endif -+}; -+ - struct vgic_cpu { - #ifdef CONFIG_KVM_ARM_VGIC - /* per IRQ to LR mapping */ -@@ -120,24 +197,24 @@ struct vgic_cpu { - DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS); - - /* Bitmap of used/free list registers */ -- DECLARE_BITMAP( lr_used, VGIC_MAX_LRS); -+ DECLARE_BITMAP( lr_used, VGIC_V2_MAX_LRS); - - /* Number of list registers on this CPU */ - int nr_lr; - - /* CPU vif control registers for world switch */ -- u32 vgic_hcr; -- u32 vgic_vmcr; -- u32 vgic_misr; /* Saved only */ -- u32 vgic_eisr[2]; /* Saved only */ -- u32 vgic_elrsr[2]; /* Saved only */ -- u32 vgic_apr; -- u32 vgic_lr[VGIC_MAX_LRS]; -+ union { -+ struct vgic_v2_cpu_if vgic_v2; -+ struct vgic_v3_cpu_if vgic_v3; -+ }; - #endif - }; - - #define LR_EMPTY 0xff - -+#define INT_STATUS_EOI (1 << 0) -+#define INT_STATUS_UNDERFLOW (1 << 1) -+ - struct kvm; - struct kvm_vcpu; - struct kvm_run; -@@ -157,9 +234,25 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu); - bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, - struct kvm_exit_mmio *mmio); - --#define irqchip_in_kernel(k) (!!((k)->arch.vgic.vctrl_base)) -+#define irqchip_in_kernel(k) (!!((k)->arch.vgic.in_kernel)) - #define vgic_initialized(k) ((k)->arch.vgic.ready) - -+int vgic_v2_probe(struct device_node *vgic_node, -+ const struct vgic_ops **ops, -+ const struct vgic_params **params); -+#ifdef CONFIG_ARM_GIC_V3 -+int vgic_v3_probe(struct device_node *vgic_node, -+ const struct vgic_ops **ops, -+ const struct vgic_params **params); -+#else -+static inline int vgic_v3_probe(struct device_node *vgic_node, -+ const struct vgic_ops **ops, -+ const struct vgic_params **params) -+{ -+ return -ENODEV; -+} -+#endif -+ - #else - static inline int kvm_vgic_hyp_init(void) - { diff --git a/include/linux/of_address.h b/include/linux/of_address.h -index c13b878..33c0420 100644 +index fb7b722..cb9479e4 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -23,17 +23,8 @@ struct of_pci_range { @@ -5998,1114 +4822,3 @@ index e9441b9..1d3f39c 100644 #define PERF_REG_IP PERF_REG_ARM64_PC #define PERF_REG_SP PERF_REG_ARM64_SP -diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c -new file mode 100644 -index 0000000..ff597d8 ---- /dev/null -+++ b/virt/kvm/arm/vgic-v2.c -@@ -0,0 +1,259 @@ -+/* -+ * Copyright (C) 2012,2013 ARM Limited, All Rights Reserved. -+ * Author: Marc Zyngier <marc.zyngier@arm.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see <http://www.gnu.org/licenses/>. -+ */ -+ -+#include <linux/cpu.h> -+#include <linux/kvm.h> -+#include <linux/kvm_host.h> -+#include <linux/interrupt.h> -+#include <linux/io.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/of_irq.h> -+ -+#include <linux/irqchip/arm-gic.h> -+ -+#include <asm/kvm_emulate.h> -+#include <asm/kvm_arm.h> -+#include <asm/kvm_mmu.h> -+ -+static struct vgic_lr vgic_v2_get_lr(const struct kvm_vcpu *vcpu, int lr) -+{ -+ struct vgic_lr lr_desc; -+ u32 val = vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr]; -+ -+ lr_desc.irq = val & GICH_LR_VIRTUALID; -+ if (lr_desc.irq <= 15) -+ lr_desc.source = (val >> GICH_LR_PHYSID_CPUID_SHIFT) & 0x7; -+ else -+ lr_desc.source = 0; -+ lr_desc.state = 0; -+ -+ if (val & GICH_LR_PENDING_BIT) -+ lr_desc.state |= LR_STATE_PENDING; -+ if (val & GICH_LR_ACTIVE_BIT) -+ lr_desc.state |= LR_STATE_ACTIVE; -+ if (val & GICH_LR_EOI) -+ lr_desc.state |= LR_EOI_INT; -+ -+ return lr_desc; -+} -+ -+static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, -+ struct vgic_lr lr_desc) -+{ -+ u32 lr_val = (lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | lr_desc.irq; -+ -+ if (lr_desc.state & LR_STATE_PENDING) -+ lr_val |= GICH_LR_PENDING_BIT; -+ if (lr_desc.state & LR_STATE_ACTIVE) -+ lr_val |= GICH_LR_ACTIVE_BIT; -+ if (lr_desc.state & LR_EOI_INT) -+ lr_val |= GICH_LR_EOI; -+ -+ vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val; -+} -+ -+static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, -+ struct vgic_lr lr_desc) -+{ -+ if (!(lr_desc.state & LR_STATE_MASK)) -+ set_bit(lr, (unsigned long *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr); -+} -+ -+static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu) -+{ -+ u64 val; -+ -+ val = vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[1]; -+ val <<= 32; -+ val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[0]; -+ -+ return val; -+} -+ -+static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu) -+{ -+ u64 val; -+ -+ val = vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[1]; -+ val <<= 32; -+ val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr[0]; -+ -+ return val; -+} -+ -+static u32 vgic_v2_get_interrupt_status(const struct kvm_vcpu *vcpu) -+{ -+ u32 misr = vcpu->arch.vgic_cpu.vgic_v2.vgic_misr; -+ u32 ret = 0; -+ -+ if (misr & GICH_MISR_EOI) -+ ret |= INT_STATUS_EOI; -+ if (misr & GICH_MISR_U) -+ ret |= INT_STATUS_UNDERFLOW; -+ -+ return ret; -+} -+ -+static void vgic_v2_enable_underflow(struct kvm_vcpu *vcpu) -+{ -+ vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr |= GICH_HCR_UIE; -+} -+ -+static void vgic_v2_disable_underflow(struct kvm_vcpu *vcpu) -+{ -+ vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr &= ~GICH_HCR_UIE; -+} -+ -+static void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) -+{ -+ u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr; -+ -+ vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >> GICH_VMCR_CTRL_SHIFT; -+ vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >> GICH_VMCR_ALIAS_BINPOINT_SHIFT; -+ vmcrp->bpr = (vmcr & GICH_VMCR_BINPOINT_MASK) >> GICH_VMCR_BINPOINT_SHIFT; -+ vmcrp->pmr = (vmcr & GICH_VMCR_PRIMASK_MASK) >> GICH_VMCR_PRIMASK_SHIFT; -+} -+ -+static void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) -+{ -+ u32 vmcr; -+ -+ vmcr = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK; -+ vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) & GICH_VMCR_ALIAS_BINPOINT_MASK; -+ vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) & GICH_VMCR_BINPOINT_MASK; -+ vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) & GICH_VMCR_PRIMASK_MASK; -+ -+ vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr; -+} -+ -+static void vgic_v2_enable(struct kvm_vcpu *vcpu) -+{ -+ /* -+ * By forcing VMCR to zero, the GIC will restore the binary -+ * points to their reset values. Anything else resets to zero -+ * anyway. -+ */ -+ vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0; -+ -+ /* Get the show on the road... */ -+ vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN; -+} -+ -+static const struct vgic_ops vgic_v2_ops = { -+ .get_lr = vgic_v2_get_lr, -+ .set_lr = vgic_v2_set_lr, -+ .sync_lr_elrsr = vgic_v2_sync_lr_elrsr, -+ .get_elrsr = vgic_v2_get_elrsr, -+ .get_eisr = vgic_v2_get_eisr, -+ .get_interrupt_status = vgic_v2_get_interrupt_status, -+ .enable_underflow = vgic_v2_enable_underflow, -+ .disable_underflow = vgic_v2_disable_underflow, -+ .get_vmcr = vgic_v2_get_vmcr, -+ .set_vmcr = vgic_v2_set_vmcr, -+ .enable = vgic_v2_enable, -+}; -+ -+static struct vgic_params vgic_v2_params; -+ -+/** -+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT -+ * @node: pointer to the DT node -+ * @ops: address of a pointer to the GICv2 operations -+ * @params: address of a pointer to HW-specific parameters -+ * -+ * Returns 0 if a GICv2 has been found, with the low level operations -+ * in *ops and the HW parameters in *params. Returns an error code -+ * otherwise. -+ */ -+int vgic_v2_probe(struct device_node *vgic_node, -+ const struct vgic_ops **ops, -+ const struct vgic_params **params) -+{ -+ int ret; -+ struct resource vctrl_res; -+ struct resource vcpu_res; -+ struct vgic_params *vgic = &vgic_v2_params; -+ -+ vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0); -+ if (!vgic->maint_irq) { -+ kvm_err("error getting vgic maintenance irq from DT\n"); -+ ret = -ENXIO; -+ goto out; -+ } -+ -+ ret = of_address_to_resource(vgic_node, 2, &vctrl_res); -+ if (ret) { -+ kvm_err("Cannot obtain GICH resource\n"); -+ goto out; -+ } -+ -+ vgic->vctrl_base = of_iomap(vgic_node, 2); -+ if (!vgic->vctrl_base) { -+ kvm_err("Cannot ioremap GICH\n"); -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ vgic->nr_lr = readl_relaxed(vgic->vctrl_base + GICH_VTR); -+ vgic->nr_lr = (vgic->nr_lr & 0x3f) + 1; -+ -+ ret = create_hyp_io_mappings(vgic->vctrl_base, -+ vgic->vctrl_base + resource_size(&vctrl_res), -+ vctrl_res.start); -+ if (ret) { -+ kvm_err("Cannot map VCTRL into hyp\n"); -+ goto out_unmap; -+ } -+ -+ if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { -+ kvm_err("Cannot obtain GICV resource\n"); -+ ret = -ENXIO; -+ goto out_unmap; -+ } -+ -+ if (!PAGE_ALIGNED(vcpu_res.start)) { -+ kvm_err("GICV physical address 0x%llx not page aligned\n", -+ (unsigned long long)vcpu_res.start); -+ ret = -ENXIO; -+ goto out_unmap; -+ } -+ -+ if (!PAGE_ALIGNED(resource_size(&vcpu_res))) { -+ kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n", -+ (unsigned long long)resource_size(&vcpu_res), -+ PAGE_SIZE); -+ ret = -ENXIO; -+ goto out_unmap; -+ } -+ -+ vgic->vcpu_base = vcpu_res.start; -+ -+ kvm_info("%s@%llx IRQ%d\n", vgic_node->name, -+ vgic->vctrl_base, vgic->maint_irq); -+ -+ vgic->type = VGIC_V2; -+ *ops = &vgic_v2_ops; -+ *params = vgic; -+ goto out; -+ -+out_unmap: -+ iounmap(vgic->vctrl_base); -+out: -+ of_node_put(vgic_node); -+ return ret; -+} -diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c -new file mode 100644 -index 0000000..f01d446 ---- /dev/null -+++ b/virt/kvm/arm/vgic-v3.c -@@ -0,0 +1,231 @@ -+/* -+ * Copyright (C) 2013 ARM Limited, All Rights Reserved. -+ * Author: Marc Zyngier <marc.zyngier@arm.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see <http://www.gnu.org/licenses/>. -+ */ -+ -+#include <linux/cpu.h> -+#include <linux/kvm.h> -+#include <linux/kvm_host.h> -+#include <linux/interrupt.h> -+#include <linux/io.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/of_irq.h> -+ -+#include <linux/irqchip/arm-gic-v3.h> -+ -+#include <asm/kvm_emulate.h> -+#include <asm/kvm_arm.h> -+#include <asm/kvm_mmu.h> -+ -+/* These are for GICv2 emulation only */ -+#define GICH_LR_VIRTUALID (0x3ffUL << 0) -+#define GICH_LR_PHYSID_CPUID_SHIFT (10) -+#define GICH_LR_PHYSID_CPUID (7UL << GICH_LR_PHYSID_CPUID_SHIFT) -+ -+/* -+ * LRs are stored in reverse order in memory. make sure we index them -+ * correctly. -+ */ -+#define LR_INDEX(lr) (VGIC_V3_MAX_LRS - 1 - lr) -+ -+static u32 ich_vtr_el2; -+ -+static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr) -+{ -+ struct vgic_lr lr_desc; -+ u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)]; -+ -+ lr_desc.irq = val & GICH_LR_VIRTUALID; -+ if (lr_desc.irq <= 15) -+ lr_desc.source = (val >> GICH_LR_PHYSID_CPUID_SHIFT) & 0x7; -+ else -+ lr_desc.source = 0; -+ lr_desc.state = 0; -+ -+ if (val & ICH_LR_PENDING_BIT) -+ lr_desc.state |= LR_STATE_PENDING; -+ if (val & ICH_LR_ACTIVE_BIT) -+ lr_desc.state |= LR_STATE_ACTIVE; -+ if (val & ICH_LR_EOI) -+ lr_desc.state |= LR_EOI_INT; -+ -+ return lr_desc; -+} -+ -+static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr, -+ struct vgic_lr lr_desc) -+{ -+ u64 lr_val = (((u32)lr_desc.source << GICH_LR_PHYSID_CPUID_SHIFT) | -+ lr_desc.irq); -+ -+ if (lr_desc.state & LR_STATE_PENDING) -+ lr_val |= ICH_LR_PENDING_BIT; -+ if (lr_desc.state & LR_STATE_ACTIVE) -+ lr_val |= ICH_LR_ACTIVE_BIT; -+ if (lr_desc.state & LR_EOI_INT) -+ lr_val |= ICH_LR_EOI; -+ -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val; -+} -+ -+static void vgic_v3_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, -+ struct vgic_lr lr_desc) -+{ -+ if (!(lr_desc.state & LR_STATE_MASK)) -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr); -+} -+ -+static u64 vgic_v3_get_elrsr(const struct kvm_vcpu *vcpu) -+{ -+ return vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr; -+} -+ -+static u64 vgic_v3_get_eisr(const struct kvm_vcpu *vcpu) -+{ -+ return vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr; -+} -+ -+static u32 vgic_v3_get_interrupt_status(const struct kvm_vcpu *vcpu) -+{ -+ u32 misr = vcpu->arch.vgic_cpu.vgic_v3.vgic_misr; -+ u32 ret = 0; -+ -+ if (misr & ICH_MISR_EOI) -+ ret |= INT_STATUS_EOI; -+ if (misr & ICH_MISR_U) -+ ret |= INT_STATUS_UNDERFLOW; -+ -+ return ret; -+} -+ -+static void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) -+{ -+ u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr; -+ -+ vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT; -+ vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT; -+ vmcrp->bpr = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT; -+ vmcrp->pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT; -+} -+ -+static void vgic_v3_enable_underflow(struct kvm_vcpu *vcpu) -+{ -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr |= ICH_HCR_UIE; -+} -+ -+static void vgic_v3_disable_underflow(struct kvm_vcpu *vcpu) -+{ -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr &= ~ICH_HCR_UIE; -+} -+ -+static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) -+{ -+ u32 vmcr; -+ -+ vmcr = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK; -+ vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK; -+ vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK; -+ vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK; -+ -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr; -+} -+ -+static void vgic_v3_enable(struct kvm_vcpu *vcpu) -+{ -+ /* -+ * By forcing VMCR to zero, the GIC will restore the binary -+ * points to their reset values. Anything else resets to zero -+ * anyway. -+ */ -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = 0; -+ -+ /* Get the show on the road... */ -+ vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr = ICH_HCR_EN; -+} -+ -+static const struct vgic_ops vgic_v3_ops = { -+ .get_lr = vgic_v3_get_lr, -+ .set_lr = vgic_v3_set_lr, -+ .sync_lr_elrsr = vgic_v3_sync_lr_elrsr, -+ .get_elrsr = vgic_v3_get_elrsr, -+ .get_eisr = vgic_v3_get_eisr, -+ .get_interrupt_status = vgic_v3_get_interrupt_status, -+ .enable_underflow = vgic_v3_enable_underflow, -+ .disable_underflow = vgic_v3_disable_underflow, -+ .get_vmcr = vgic_v3_get_vmcr, -+ .set_vmcr = vgic_v3_set_vmcr, -+ .enable = vgic_v3_enable, -+}; -+ -+static struct vgic_params vgic_v3_params; -+ -+/** -+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT -+ * @node: pointer to the DT node -+ * @ops: address of a pointer to the GICv3 operations -+ * @params: address of a pointer to HW-specific parameters -+ * -+ * Returns 0 if a GICv3 has been found, with the low level operations -+ * in *ops and the HW parameters in *params. Returns an error code -+ * otherwise. -+ */ -+int vgic_v3_probe(struct device_node *vgic_node, -+ const struct vgic_ops **ops, -+ const struct vgic_params **params) -+{ -+ int ret = 0; -+ u32 gicv_idx; -+ struct resource vcpu_res; -+ struct vgic_params *vgic = &vgic_v3_params; -+ -+ vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0); -+ if (!vgic->maint_irq) { -+ kvm_err("error getting vgic maintenance irq from DT\n"); -+ ret = -ENXIO; -+ goto out; -+ } -+ -+ ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2); -+ -+ /* -+ * The ListRegs field is 5 bits, but there is a architectural -+ * maximum of 16 list registers. Just ignore bit 4... -+ */ -+ vgic->nr_lr = (ich_vtr_el2 & 0xf) + 1; -+ -+ if (of_property_read_u32(vgic_node, "#redistributor-regions", &gicv_idx)) -+ gicv_idx = 1; -+ -+ gicv_idx += 3; /* Also skip GICD, GICC, GICH */ -+ if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) { -+ kvm_err("Cannot obtain GICV region\n"); -+ ret = -ENXIO; -+ goto out; -+ } -+ vgic->vcpu_base = vcpu_res.start; -+ vgic->vctrl_base = NULL; -+ vgic->type = VGIC_V3; -+ -+ kvm_info("%s@%llx IRQ%d\n", vgic_node->name, -+ vcpu_res.start, vgic->maint_irq); -+ -+ *ops = &vgic_v3_ops; -+ *params = vgic; -+ -+out: -+ of_node_put(vgic_node); -+ return ret; -+} -diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c -index 476d3bf..795ab48 100644 ---- a/virt/kvm/arm/vgic.c -+++ b/virt/kvm/arm/vgic.c -@@ -76,14 +76,6 @@ - #define IMPLEMENTER_ARM 0x43b - #define GICC_ARCH_VERSION_V2 0x2 - --/* Physical address of vgic virtual cpu interface */ --static phys_addr_t vgic_vcpu_base; -- --/* Virtual control interface base address */ --static void __iomem *vgic_vctrl_base; -- --static struct device_node *vgic_node; -- - #define ACCESS_READ_VALUE (1 << 0) - #define ACCESS_READ_RAZ (0 << 0) - #define ACCESS_READ_MASK(x) ((x) & (1 << 0)) -@@ -94,12 +86,17 @@ static struct device_node *vgic_node; - #define ACCESS_WRITE_MASK(x) ((x) & (3 << 1)) - - static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu); -+static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu); - static void vgic_update_state(struct kvm *kvm); - static void vgic_kick_vcpus(struct kvm *kvm); - static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg); --static u32 vgic_nr_lr; -+static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr); -+static void vgic_set_lr(struct kvm_vcpu *vcpu, int lr, struct vgic_lr lr_desc); -+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); -+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); - --static unsigned int vgic_maint_irq; -+static const struct vgic_ops *vgic_ops; -+static const struct vgic_params *vgic; - - static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x, - int cpuid, u32 offset) -@@ -593,18 +590,6 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu, - return false; - } - --#define LR_CPUID(lr) \ -- (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) --#define LR_IRQID(lr) \ -- ((lr) & GICH_LR_VIRTUALID) -- --static void vgic_retire_lr(int lr_nr, int irq, struct vgic_cpu *vgic_cpu) --{ -- clear_bit(lr_nr, vgic_cpu->lr_used); -- vgic_cpu->vgic_lr[lr_nr] &= ~GICH_LR_STATE; -- vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; --} -- - /** - * vgic_unqueue_irqs - move pending IRQs from LRs to the distributor - * @vgic_cpu: Pointer to the vgic_cpu struct holding the LRs -@@ -622,13 +607,10 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu) - struct vgic_dist *dist = &vcpu->kvm->arch.vgic; - struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; - int vcpu_id = vcpu->vcpu_id; -- int i, irq, source_cpu; -- u32 *lr; -+ int i; - - for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) { -- lr = &vgic_cpu->vgic_lr[i]; -- irq = LR_IRQID(*lr); -- source_cpu = LR_CPUID(*lr); -+ struct vgic_lr lr = vgic_get_lr(vcpu, i); - - /* - * There are three options for the state bits: -@@ -640,7 +622,7 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu) - * If the LR holds only an active interrupt (not pending) then - * just leave it alone. - */ -- if ((*lr & GICH_LR_STATE) == GICH_LR_ACTIVE_BIT) -+ if ((lr.state & LR_STATE_MASK) == LR_STATE_ACTIVE) - continue; - - /* -@@ -649,18 +631,19 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu) - * is fine, then we are only setting a few bits that were - * already set. - */ -- vgic_dist_irq_set(vcpu, irq); -- if (irq < VGIC_NR_SGIS) -- dist->irq_sgi_sources[vcpu_id][irq] |= 1 << source_cpu; -- *lr &= ~GICH_LR_PENDING_BIT; -+ vgic_dist_irq_set(vcpu, lr.irq); -+ if (lr.irq < VGIC_NR_SGIS) -+ dist->irq_sgi_sources[vcpu_id][lr.irq] |= 1 << lr.source; -+ lr.state &= ~LR_STATE_PENDING; -+ vgic_set_lr(vcpu, i, lr); - - /* - * If there's no state left on the LR (it could still be - * active), then the LR does not hold any useful info and can - * be marked as free for other use. - */ -- if (!(*lr & GICH_LR_STATE)) -- vgic_retire_lr(i, irq, vgic_cpu); -+ if (!(lr.state & LR_STATE_MASK)) -+ vgic_retire_lr(i, lr.irq, vcpu); - - /* Finally update the VGIC state. */ - vgic_update_state(vcpu->kvm); -@@ -989,8 +972,73 @@ static void vgic_update_state(struct kvm *kvm) - } - } - --#define MK_LR_PEND(src, irq) \ -- (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) -+static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr) -+{ -+ return vgic_ops->get_lr(vcpu, lr); -+} -+ -+static void vgic_set_lr(struct kvm_vcpu *vcpu, int lr, -+ struct vgic_lr vlr) -+{ -+ vgic_ops->set_lr(vcpu, lr, vlr); -+} -+ -+static void vgic_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, -+ struct vgic_lr vlr) -+{ -+ vgic_ops->sync_lr_elrsr(vcpu, lr, vlr); -+} -+ -+static inline u64 vgic_get_elrsr(struct kvm_vcpu *vcpu) -+{ -+ return vgic_ops->get_elrsr(vcpu); -+} -+ -+static inline u64 vgic_get_eisr(struct kvm_vcpu *vcpu) -+{ -+ return vgic_ops->get_eisr(vcpu); -+} -+ -+static inline u32 vgic_get_interrupt_status(struct kvm_vcpu *vcpu) -+{ -+ return vgic_ops->get_interrupt_status(vcpu); -+} -+ -+static inline void vgic_enable_underflow(struct kvm_vcpu *vcpu) -+{ -+ vgic_ops->enable_underflow(vcpu); -+} -+ -+static inline void vgic_disable_underflow(struct kvm_vcpu *vcpu) -+{ -+ vgic_ops->disable_underflow(vcpu); -+} -+ -+static inline void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) -+{ -+ vgic_ops->get_vmcr(vcpu, vmcr); -+} -+ -+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) -+{ -+ vgic_ops->set_vmcr(vcpu, vmcr); -+} -+ -+static inline void vgic_enable(struct kvm_vcpu *vcpu) -+{ -+ vgic_ops->enable(vcpu); -+} -+ -+static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu) -+{ -+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; -+ struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr); -+ -+ vlr.state = 0; -+ vgic_set_lr(vcpu, lr_nr, vlr); -+ clear_bit(lr_nr, vgic_cpu->lr_used); -+ vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; -+} - - /* - * An interrupt may have been disabled after being made pending on the -@@ -1006,13 +1054,13 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu) - struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; - int lr; - -- for_each_set_bit(lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) { -- int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID; -+ for_each_set_bit(lr, vgic_cpu->lr_used, vgic->nr_lr) { -+ struct vgic_lr vlr = vgic_get_lr(vcpu, lr); - -- if (!vgic_irq_is_enabled(vcpu, irq)) { -- vgic_retire_lr(lr, irq, vgic_cpu); -- if (vgic_irq_is_active(vcpu, irq)) -- vgic_irq_clear_active(vcpu, irq); -+ if (!vgic_irq_is_enabled(vcpu, vlr.irq)) { -+ vgic_retire_lr(lr, vlr.irq, vcpu); -+ if (vgic_irq_is_active(vcpu, vlr.irq)) -+ vgic_irq_clear_active(vcpu, vlr.irq); - } - } - } -@@ -1024,6 +1072,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu) - static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) - { - struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; -+ struct vgic_lr vlr; - int lr; - - /* Sanitize the input... */ -@@ -1036,28 +1085,34 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) - lr = vgic_cpu->vgic_irq_lr_map[irq]; - - /* Do we have an active interrupt for the same CPUID? */ -- if (lr != LR_EMPTY && -- (LR_CPUID(vgic_cpu->vgic_lr[lr]) == sgi_source_id)) { -- kvm_debug("LR%d piggyback for IRQ%d %x\n", -- lr, irq, vgic_cpu->vgic_lr[lr]); -- BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); -- vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT; -- return true; -+ if (lr != LR_EMPTY) { -+ vlr = vgic_get_lr(vcpu, lr); -+ if (vlr.source == sgi_source_id) { -+ kvm_debug("LR%d piggyback for IRQ%d\n", lr, vlr.irq); -+ BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); -+ vlr.state |= LR_STATE_PENDING; -+ vgic_set_lr(vcpu, lr, vlr); -+ return true; -+ } - } - - /* Try to use another LR for this interrupt */ - lr = find_first_zero_bit((unsigned long *)vgic_cpu->lr_used, -- vgic_cpu->nr_lr); -- if (lr >= vgic_cpu->nr_lr) -+ vgic->nr_lr); -+ if (lr >= vgic->nr_lr) - return false; - - kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id); -- vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq); - vgic_cpu->vgic_irq_lr_map[irq] = lr; - set_bit(lr, vgic_cpu->lr_used); - -+ vlr.irq = irq; -+ vlr.source = sgi_source_id; -+ vlr.state = LR_STATE_PENDING; - if (!vgic_irq_is_edge(vcpu, irq)) -- vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI; -+ vlr.state |= LR_EOI_INT; -+ -+ vgic_set_lr(vcpu, lr, vlr); - - return true; - } -@@ -1155,9 +1210,9 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) - - epilog: - if (overflow) { -- vgic_cpu->vgic_hcr |= GICH_HCR_UIE; -+ vgic_enable_underflow(vcpu); - } else { -- vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE; -+ vgic_disable_underflow(vcpu); - /* - * We're about to run this VCPU, and we've consumed - * everything the distributor had in store for -@@ -1170,44 +1225,46 @@ epilog: - - static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) - { -- struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; -+ u32 status = vgic_get_interrupt_status(vcpu); - bool level_pending = false; - -- kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr); -+ kvm_debug("STATUS = %08x\n", status); - -- if (vgic_cpu->vgic_misr & GICH_MISR_EOI) { -+ if (status & INT_STATUS_EOI) { - /* - * Some level interrupts have been EOIed. Clear their - * active bit. - */ -- int lr, irq; -+ u64 eisr = vgic_get_eisr(vcpu); -+ unsigned long *eisr_ptr = (unsigned long *)&eisr; -+ int lr; - -- for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_eisr, -- vgic_cpu->nr_lr) { -- irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID; -+ for_each_set_bit(lr, eisr_ptr, vgic->nr_lr) { -+ struct vgic_lr vlr = vgic_get_lr(vcpu, lr); - -- vgic_irq_clear_active(vcpu, irq); -- vgic_cpu->vgic_lr[lr] &= ~GICH_LR_EOI; -+ vgic_irq_clear_active(vcpu, vlr.irq); -+ WARN_ON(vlr.state & LR_STATE_MASK); -+ vlr.state = 0; -+ vgic_set_lr(vcpu, lr, vlr); - - /* Any additional pending interrupt? */ -- if (vgic_dist_irq_is_pending(vcpu, irq)) { -- vgic_cpu_irq_set(vcpu, irq); -+ if (vgic_dist_irq_is_pending(vcpu, vlr.irq)) { -+ vgic_cpu_irq_set(vcpu, vlr.irq); - level_pending = true; - } else { -- vgic_cpu_irq_clear(vcpu, irq); -+ vgic_cpu_irq_clear(vcpu, vlr.irq); - } - - /* - * Despite being EOIed, the LR may not have - * been marked as empty. - */ -- set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); -- vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT; -+ vgic_sync_lr_elrsr(vcpu, lr, vlr); - } - } - -- if (vgic_cpu->vgic_misr & GICH_MISR_U) -- vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE; -+ if (status & INT_STATUS_UNDERFLOW) -+ vgic_disable_underflow(vcpu); - - return level_pending; - } -@@ -1220,29 +1277,31 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) - { - struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; - struct vgic_dist *dist = &vcpu->kvm->arch.vgic; -+ u64 elrsr; -+ unsigned long *elrsr_ptr; - int lr, pending; - bool level_pending; - - level_pending = vgic_process_maintenance(vcpu); -+ elrsr = vgic_get_elrsr(vcpu); -+ elrsr_ptr = (unsigned long *)&elrsr; - - /* Clear mappings for empty LRs */ -- for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr, -- vgic_cpu->nr_lr) { -- int irq; -+ for_each_set_bit(lr, elrsr_ptr, vgic->nr_lr) { -+ struct vgic_lr vlr; - - if (!test_and_clear_bit(lr, vgic_cpu->lr_used)) - continue; - -- irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID; -+ vlr = vgic_get_lr(vcpu, lr); - -- BUG_ON(irq >= VGIC_NR_IRQS); -- vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; -+ BUG_ON(vlr.irq >= VGIC_NR_IRQS); -+ vgic_cpu->vgic_irq_lr_map[vlr.irq] = LR_EMPTY; - } - - /* Check if we still have something up our sleeve... */ -- pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_elrsr, -- vgic_cpu->nr_lr); -- if (level_pending || pending < vgic_cpu->nr_lr) -+ pending = find_first_zero_bit(elrsr_ptr, vgic->nr_lr); -+ if (level_pending || pending < vgic->nr_lr) - set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu); - } - -@@ -1432,21 +1491,20 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) - } - - /* -- * By forcing VMCR to zero, the GIC will restore the binary -- * points to their reset values. Anything else resets to zero -- * anyway. -+ * Store the number of LRs per vcpu, so we don't have to go -+ * all the way to the distributor structure to find out. Only -+ * assembly code should use this one. - */ -- vgic_cpu->vgic_vmcr = 0; -+ vgic_cpu->nr_lr = vgic->nr_lr; - -- vgic_cpu->nr_lr = vgic_nr_lr; -- vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */ -+ vgic_enable(vcpu); - - return 0; - } - - static void vgic_init_maintenance_interrupt(void *info) - { -- enable_percpu_irq(vgic_maint_irq, 0); -+ enable_percpu_irq(vgic->maint_irq, 0); - } - - static int vgic_cpu_notify(struct notifier_block *self, -@@ -1459,7 +1517,7 @@ static int vgic_cpu_notify(struct notifier_block *self, - break; - case CPU_DYING: - case CPU_DYING_FROZEN: -- disable_percpu_irq(vgic_maint_irq); -+ disable_percpu_irq(vgic->maint_irq); - break; - } - -@@ -1470,30 +1528,37 @@ static struct notifier_block vgic_cpu_nb = { - .notifier_call = vgic_cpu_notify, - }; - -+static const struct of_device_id vgic_ids[] = { -+ { .compatible = "arm,cortex-a15-gic", .data = vgic_v2_probe, }, -+ { .compatible = "arm,gic-v3", .data = vgic_v3_probe, }, -+ {}, -+}; -+ - int kvm_vgic_hyp_init(void) - { -+ const struct of_device_id *matched_id; -+ int (*vgic_probe)(struct device_node *,const struct vgic_ops **, -+ const struct vgic_params **); -+ struct device_node *vgic_node; - int ret; -- struct resource vctrl_res; -- struct resource vcpu_res; - -- vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic"); -+ vgic_node = of_find_matching_node_and_match(NULL, -+ vgic_ids, &matched_id); - if (!vgic_node) { -- kvm_err("error: no compatible vgic node in DT\n"); -+ kvm_err("error: no compatible GIC node found\n"); - return -ENODEV; - } - -- vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0); -- if (!vgic_maint_irq) { -- kvm_err("error getting vgic maintenance irq from DT\n"); -- ret = -ENXIO; -- goto out; -- } -+ vgic_probe = matched_id->data; -+ ret = vgic_probe(vgic_node, &vgic_ops, &vgic); -+ if (ret) -+ return ret; - -- ret = request_percpu_irq(vgic_maint_irq, vgic_maintenance_handler, -+ ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler, - "vgic", kvm_get_running_vcpus()); - if (ret) { -- kvm_err("Cannot register interrupt %d\n", vgic_maint_irq); -- goto out; -+ kvm_err("Cannot register interrupt %d\n", vgic->maint_irq); -+ return ret; - } - - ret = __register_cpu_notifier(&vgic_cpu_nb); -@@ -1502,65 +1567,15 @@ int kvm_vgic_hyp_init(void) - goto out_free_irq; - } - -- ret = of_address_to_resource(vgic_node, 2, &vctrl_res); -- if (ret) { -- kvm_err("Cannot obtain VCTRL resource\n"); -- goto out_free_irq; -- } -- -- vgic_vctrl_base = of_iomap(vgic_node, 2); -- if (!vgic_vctrl_base) { -- kvm_err("Cannot ioremap VCTRL\n"); -- ret = -ENOMEM; -- goto out_free_irq; -- } -- -- vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR); -- vgic_nr_lr = (vgic_nr_lr & 0x3f) + 1; -- -- ret = create_hyp_io_mappings(vgic_vctrl_base, -- vgic_vctrl_base + resource_size(&vctrl_res), -- vctrl_res.start); -- if (ret) { -- kvm_err("Cannot map VCTRL into hyp\n"); -- goto out_unmap; -- } -- -- if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { -- kvm_err("Cannot obtain VCPU resource\n"); -- ret = -ENXIO; -- goto out_unmap; -- } -- -- if (!PAGE_ALIGNED(vcpu_res.start)) { -- kvm_err("GICV physical address 0x%llx not page aligned\n", -- (unsigned long long)vcpu_res.start); -- ret = -ENXIO; -- goto out_unmap; -- } -- -- if (!PAGE_ALIGNED(resource_size(&vcpu_res))) { -- kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n", -- (unsigned long long)resource_size(&vcpu_res), -- PAGE_SIZE); -- ret = -ENXIO; -- goto out_unmap; -- } -- -- vgic_vcpu_base = vcpu_res.start; -- -- kvm_info("%s@%llx IRQ%d\n", vgic_node->name, -- vctrl_res.start, vgic_maint_irq); - on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); - -- goto out; -+ /* Callback into for arch code for setup */ -+ vgic_arch_setup(vgic); -+ -+ return 0; - --out_unmap: -- iounmap(vgic_vctrl_base); - out_free_irq: -- free_percpu_irq(vgic_maint_irq, kvm_get_running_vcpus()); --out: -- of_node_put(vgic_node); -+ free_percpu_irq(vgic->maint_irq, kvm_get_running_vcpus()); - return ret; - } - -@@ -1593,7 +1608,7 @@ int kvm_vgic_init(struct kvm *kvm) - } - - ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base, -- vgic_vcpu_base, KVM_VGIC_V2_CPU_SIZE); -+ vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE); - if (ret) { - kvm_err("Unable to remap VGIC CPU to VCPU\n"); - goto out; -@@ -1639,7 +1654,8 @@ int kvm_vgic_create(struct kvm *kvm) - } - - spin_lock_init(&kvm->arch.vgic.lock); -- kvm->arch.vgic.vctrl_base = vgic_vctrl_base; -+ kvm->arch.vgic.in_kernel = true; -+ kvm->arch.vgic.vctrl_base = vgic->vctrl_base; - kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; - kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; - -@@ -1738,39 +1754,40 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) - static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu, - struct kvm_exit_mmio *mmio, phys_addr_t offset) - { -- struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; -- u32 reg, mask = 0, shift = 0; - bool updated = false; -+ struct vgic_vmcr vmcr; -+ u32 *vmcr_field; -+ u32 reg; -+ -+ vgic_get_vmcr(vcpu, &vmcr); - - switch (offset & ~0x3) { - case GIC_CPU_CTRL: -- mask = GICH_VMCR_CTRL_MASK; -- shift = GICH_VMCR_CTRL_SHIFT; -+ vmcr_field = &vmcr.ctlr; - break; - case GIC_CPU_PRIMASK: -- mask = GICH_VMCR_PRIMASK_MASK; -- shift = GICH_VMCR_PRIMASK_SHIFT; -+ vmcr_field = &vmcr.pmr; - break; - case GIC_CPU_BINPOINT: -- mask = GICH_VMCR_BINPOINT_MASK; -- shift = GICH_VMCR_BINPOINT_SHIFT; -+ vmcr_field = &vmcr.bpr; - break; - case GIC_CPU_ALIAS_BINPOINT: -- mask = GICH_VMCR_ALIAS_BINPOINT_MASK; -- shift = GICH_VMCR_ALIAS_BINPOINT_SHIFT; -+ vmcr_field = &vmcr.abpr; - break; -+ default: -+ BUG(); - } - - if (!mmio->is_write) { -- reg = (vgic_cpu->vgic_vmcr & mask) >> shift; -+ reg = *vmcr_field; - mmio_data_write(mmio, ~0, reg); - } else { - reg = mmio_data_read(mmio, ~0); -- reg = (reg << shift) & mask; -- if (reg != (vgic_cpu->vgic_vmcr & mask)) -+ if (reg != *vmcr_field) { -+ *vmcr_field = reg; -+ vgic_set_vmcr(vcpu, &vmcr); - updated = true; -- vgic_cpu->vgic_vmcr &= ~mask; -- vgic_cpu->vgic_vmcr |= reg; -+ } - } - return updated; - } diff --git a/kernel.spec b/kernel.spec index 6396d15df..087058fb4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -8,7 +8,7 @@ Summary: The Linux kernel # be 0. %global released_kernel 0 -%global aarch64patches 0 +%global aarch64patches 1 # Sign modules on x86. Make sure the config files match this setting if more # architectures are added. @@ -2240,6 +2240,9 @@ fi # ||----w | # || || %changelog +* Tue Aug 12 2014 Kyle McMartin <kyle@fedoraproject.org> +- kernel-arm64.patch: fix up merge conflict and re-enable + * Tue Aug 12 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.17.0-0.rc0.git4.1 - Linux v3.16-10473-gc8d6637d0497 |