misc: Register a PPI for the vcpu stall detection virtual device
authorSebastian Ene <sebastianene@google.com>
Wed, 3 Jul 2024 15:37:32 +0000 (15:37 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Jul 2024 10:31:22 +0000 (12:31 +0200)
Request a PPI for each vCPU during probe which will be used by the host
to communicate a stall detected event on the vCPU. When the host raises
this interrupt from the virtual machine monitor, the guest is expected to
handle the interrupt and panic.

Signed-off-by: Sebastian Ene <sebastianene@google.com>
Link: https://lore.kernel.org/r/20240703153732.3214238-3-sebastianene@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/vcpu_stall_detector.c

index e2015c8..41b8c21 100644 (file)
@@ -32,6 +32,7 @@
 struct vcpu_stall_detect_config {
        u32 clock_freq_hz;
        u32 stall_timeout_sec;
+       int ppi_irq;
 
        void __iomem *membase;
        struct platform_device *dev;
@@ -77,6 +78,12 @@ vcpu_stall_detect_timer_fn(struct hrtimer *hrtimer)
        return HRTIMER_RESTART;
 }
 
+static irqreturn_t vcpu_stall_detector_irq(int irq, void *dev)
+{
+       panic("vCPU stall detector");
+       return IRQ_HANDLED;
+}
+
 static int start_stall_detector_cpu(unsigned int cpu)
 {
        u32 ticks, ping_timeout_ms;
@@ -132,7 +139,7 @@ static int stop_stall_detector_cpu(unsigned int cpu)
 
 static int vcpu_stall_detect_probe(struct platform_device *pdev)
 {
-       int ret;
+       int ret, irq;
        struct resource *r;
        void __iomem *membase;
        u32 clock_freq_hz = VCPU_STALL_DEFAULT_CLOCK_HZ;
@@ -169,9 +176,22 @@ static int vcpu_stall_detect_probe(struct platform_device *pdev)
        vcpu_stall_config = (struct vcpu_stall_detect_config) {
                .membase                = membase,
                .clock_freq_hz          = clock_freq_hz,
-               .stall_timeout_sec      = stall_timeout_sec
+               .stall_timeout_sec      = stall_timeout_sec,
+               .ppi_irq                = -1,
        };
 
+       irq = platform_get_irq_optional(pdev, 0);
+       if (irq > 0) {
+               ret = request_percpu_irq(irq,
+                                        vcpu_stall_detector_irq,
+                                        "vcpu_stall_detector",
+                                        vcpu_stall_detectors);
+               if (ret)
+                       goto err;
+
+               vcpu_stall_config.ppi_irq = irq;
+       }
+
        ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
                                "virt/vcpu_stall_detector:online",
                                start_stall_detector_cpu,
@@ -184,6 +204,9 @@ static int vcpu_stall_detect_probe(struct platform_device *pdev)
        vcpu_stall_config.hp_online = ret;
        return 0;
 err:
+       if (vcpu_stall_config.ppi_irq > 0)
+               free_percpu_irq(vcpu_stall_config.ppi_irq,
+                               vcpu_stall_detectors);
        return ret;
 }
 
@@ -193,6 +216,10 @@ static void vcpu_stall_detect_remove(struct platform_device *pdev)
 
        cpuhp_remove_state(vcpu_stall_config.hp_online);
 
+       if (vcpu_stall_config.ppi_irq > 0)
+               free_percpu_irq(vcpu_stall_config.ppi_irq,
+                               vcpu_stall_detectors);
+
        for_each_possible_cpu(cpu)
                stop_stall_detector_cpu(cpu);
 }