mirror of
https://github.com/torvalds/linux.git
synced 2024-12-22 19:01:37 +00:00
7beaa24ba4
- x86: miscellaneous fixes, AVIC support (local APIC virtualization, AMD version) - s390: polling for interrupts after a VCPU goes to halted state is now enabled for s390; use hardware provided information about facility bits that do not need any hypervisor activity, and other fixes for cpu models and facilities; improve perf output; floating interrupt controller improvements. - MIPS: miscellaneous fixes - PPC: bugfixes only - ARM: 16K page size support, generic firmware probing layer for timer and GIC Christoffer Dall (KVM-ARM maintainer) says: "There are a few changes in this pull request touching things outside KVM, but they should all carry the necessary acks and it made the merge process much easier to do it this way." though actually the irqchip maintainers' acks didn't make it into the patches. Marc Zyngier, who is both irqchip and KVM-ARM maintainer, later acked at http://mid.gmane.org/573351D1.4060303@arm.com "more formally and for documentation purposes". -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJXPJjyAAoJEL/70l94x66DhioH/j4fwQ0FmfPSM9PArzaFHQdx LNE3tU4+bobbsy1BJr4DiAaOUQn3DAgwUvGLWXdeLiOXtoWXBiFHKaxlqEsCA6iQ xcTH1TgfxsVoqGQ6bT9X/2GCx70heYpcWG3f+zqBy7ZfFmQykLAC/HwOr52VQL8f hUFi3YmTHcnorp0n5Xg+9r3+RBS4D/kTbtdn6+KCLnPJ0RcgNkI3/NcafTemoofw Tkv8+YYFNvKV13qlIfVqxMa0GwWI3pP6YaNKhaS5XO8Pu16HuuF1JthJsUBDzwBa RInp8R9MoXgsBYhLpz3jc9vWG7G9yDl5LehsD9KOUGOaFYJ7sQN+QZOusa6jFgA= =llO5 -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm Pull KVM updates from Paolo Bonzini: "Small release overall. x86: - miscellaneous fixes - AVIC support (local APIC virtualization, AMD version) s390: - polling for interrupts after a VCPU goes to halted state is now enabled for s390 - use hardware provided information about facility bits that do not need any hypervisor activity, and other fixes for cpu models and facilities - improve perf output - floating interrupt controller improvements. MIPS: - miscellaneous fixes PPC: - bugfixes only ARM: - 16K page size support - generic firmware probing layer for timer and GIC Christoffer Dall (KVM-ARM maintainer) says: "There are a few changes in this pull request touching things outside KVM, but they should all carry the necessary acks and it made the merge process much easier to do it this way." though actually the irqchip maintainers' acks didn't make it into the patches. Marc Zyngier, who is both irqchip and KVM-ARM maintainer, later acked at http://mid.gmane.org/573351D1.4060303@arm.com ('more formally and for documentation purposes')" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (82 commits) KVM: MTRR: remove MSR 0x2f8 KVM: x86: make hwapic_isr_update and hwapic_irr_update look the same svm: Manage vcpu load/unload when enable AVIC svm: Do not intercept CR8 when enable AVIC svm: Do not expose x2APIC when enable AVIC KVM: x86: Introducing kvm_x86_ops.apicv_post_state_restore svm: Add VMEXIT handlers for AVIC svm: Add interrupt injection via AVIC KVM: x86: Detect and Initialize AVIC support svm: Introduce new AVIC VMCB registers KVM: split kvm_vcpu_wake_up from kvm_vcpu_kick KVM: x86: Introducing kvm_x86_ops VCPU blocking/unblocking hooks KVM: x86: Introducing kvm_x86_ops VM init/destroy hooks KVM: x86: Rename kvm_apic_get_reg to kvm_lapic_get_reg KVM: x86: Misc LAPIC changes to expose helper functions KVM: shrink halt polling even more for invalid wakeups KVM: s390: set halt polling to 80 microseconds KVM: halt_polling: provide a way to qualify wakeups during poll KVM: PPC: Book3S HV: Re-enable XICS fast path for irqfd-generated interrupts kvm: Conditionally register IRQ bypass consumer ...
149 lines
4.0 KiB
C
149 lines
4.0 KiB
C
/*
|
|
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
|
|
*
|
|
* 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/interrupt.h>
|
|
#include <linux/io.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/irqchip/arm-gic.h>
|
|
|
|
#include "irq-gic-common.h"
|
|
|
|
static const struct gic_kvm_info *gic_kvm_info;
|
|
|
|
const struct gic_kvm_info *gic_get_kvm_info(void)
|
|
{
|
|
return gic_kvm_info;
|
|
}
|
|
|
|
void gic_set_kvm_info(const struct gic_kvm_info *info)
|
|
{
|
|
BUG_ON(gic_kvm_info != NULL);
|
|
gic_kvm_info = info;
|
|
}
|
|
|
|
void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
|
|
void *data)
|
|
{
|
|
for (; quirks->desc; quirks++) {
|
|
if (quirks->iidr != (quirks->mask & iidr))
|
|
continue;
|
|
quirks->init(data);
|
|
pr_info("GIC: enabling workaround for %s\n", quirks->desc);
|
|
}
|
|
}
|
|
|
|
int gic_configure_irq(unsigned int irq, unsigned int type,
|
|
void __iomem *base, void (*sync_access)(void))
|
|
{
|
|
u32 confmask = 0x2 << ((irq % 16) * 2);
|
|
u32 confoff = (irq / 16) * 4;
|
|
u32 val, oldval;
|
|
int ret = 0;
|
|
|
|
/*
|
|
* Read current configuration register, and insert the config
|
|
* for "irq", depending on "type".
|
|
*/
|
|
val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
|
|
if (type & IRQ_TYPE_LEVEL_MASK)
|
|
val &= ~confmask;
|
|
else if (type & IRQ_TYPE_EDGE_BOTH)
|
|
val |= confmask;
|
|
|
|
/* If the current configuration is the same, then we are done */
|
|
if (val == oldval)
|
|
return 0;
|
|
|
|
/*
|
|
* Write back the new configuration, and possibly re-enable
|
|
* the interrupt. If we fail to write a new configuration for
|
|
* an SPI then WARN and return an error. If we fail to write the
|
|
* configuration for a PPI this is most likely because the GIC
|
|
* does not allow us to set the configuration or we are in a
|
|
* non-secure mode, and hence it may not be catastrophic.
|
|
*/
|
|
writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
|
|
if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) {
|
|
if (WARN_ON(irq >= 32))
|
|
ret = -EINVAL;
|
|
else
|
|
pr_warn("GIC: PPI%d is secure or misconfigured\n",
|
|
irq - 16);
|
|
}
|
|
|
|
if (sync_access)
|
|
sync_access();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void __init gic_dist_config(void __iomem *base, int gic_irqs,
|
|
void (*sync_access)(void))
|
|
{
|
|
unsigned int i;
|
|
|
|
/*
|
|
* Set all global interrupts to be level triggered, active low.
|
|
*/
|
|
for (i = 32; i < gic_irqs; i += 16)
|
|
writel_relaxed(GICD_INT_ACTLOW_LVLTRIG,
|
|
base + GIC_DIST_CONFIG + i / 4);
|
|
|
|
/*
|
|
* Set priority on all global interrupts.
|
|
*/
|
|
for (i = 32; i < gic_irqs; i += 4)
|
|
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
|
|
|
|
/*
|
|
* Deactivate and disable all SPIs. Leave the PPI and SGIs
|
|
* alone as they are in the redistributor registers on GICv3.
|
|
*/
|
|
for (i = 32; i < gic_irqs; i += 32) {
|
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
|
base + GIC_DIST_ACTIVE_CLEAR + i / 8);
|
|
writel_relaxed(GICD_INT_EN_CLR_X32,
|
|
base + GIC_DIST_ENABLE_CLEAR + i / 8);
|
|
}
|
|
|
|
if (sync_access)
|
|
sync_access();
|
|
}
|
|
|
|
void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* Deal with the banked PPI and SGI interrupts - disable all
|
|
* PPI interrupts, ensure all SGI interrupts are enabled.
|
|
* Make sure everything is deactivated.
|
|
*/
|
|
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
|
|
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
|
|
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
|
|
|
|
/*
|
|
* Set priority on PPI and SGI interrupts
|
|
*/
|
|
for (i = 0; i < 32; i += 4)
|
|
writel_relaxed(GICD_INT_DEF_PRI_X4,
|
|
base + GIC_DIST_PRI + i * 4 / 4);
|
|
|
|
if (sync_access)
|
|
sync_access();
|
|
}
|