Message ID | 1433909767-12189-2-git-send-email-wei@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Jun 10, 2015 at 12:16:03AM -0400, Wei Huang wrote: > This patches enables ACPI support for KVM virtual arch timer. It allows > KVM to parse ACPI table for arch timer PPI when DT table is not present. > > Signed-off-by: Alexander Spyridaki <a.spyridakis@virtualopensystems.com> > Signed-off-by: Wei Huang <wei@redhat.com> > --- > virt/kvm/arm/arch_timer.c | 75 +++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 62 insertions(+), 13 deletions(-) > > diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c > index 98c95f2..a9da75a 100644 > --- a/virt/kvm/arm/arch_timer.c > +++ b/virt/kvm/arm/arch_timer.c > @@ -21,6 +21,7 @@ > #include <linux/kvm.h> > #include <linux/kvm_host.h> > #include <linux/interrupt.h> > +#include <linux/acpi.h> > > #include <clocksource/arm_arch_timer.h> > #include <asm/arch_timer.h> > @@ -274,9 +275,57 @@ static const struct of_device_id arch_timer_of_match[] = { > {}, > }; > > -int kvm_timer_hyp_init(void) > +static int kvm_timer_ppi_dt_parse(unsigned int *ppi) > { > struct device_node *np; > + > + np = of_find_matching_node(NULL, arch_timer_of_match); > + if (!np) > + return -ENODEV; > + > + *ppi = irq_of_parse_and_map(np, 2); > + if (*ppi == 0) { > + of_node_put(np); > + return -EINVAL; > + } > + > + return 0; > +} > + > +#ifdef CONFIG_ACPI > +struct acpi_table_gtdt *gtdt_acpi; I think gtdt_acpi can/should be static. > +static void arch_timer_acpi_parse(struct acpi_table_header *table) > +{ > + gtdt_acpi = container_of(table, struct acpi_table_gtdt, header); > +} > + > +static int kvm_timer_ppi_acpi_parse(unsigned int *ppi) > +{ > + u32 flags; > + int trigger, polarity; > + > + /*Get the interrupt number from the GTDT table */ > + acpi_table_parse(ACPI_SIG_GTDT, > + (acpi_tbl_table_handler)arch_timer_acpi_parse); > + > + if (!gtdt_acpi->virtual_timer_interrupt) > + return -EINVAL; > + > + flags = gtdt_acpi->virtual_timer_flags; > + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE > + : ACPI_LEVEL_SENSITIVE; > + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW > + : ACPI_ACTIVE_HIGH; > + > + *ppi = acpi_register_gsi(NULL, gtdt_acpi->virtual_timer_interrupt, > + trigger, polarity); > + > + return 0; > +} > +#endif > + > +int kvm_timer_hyp_init(void) > +{ > unsigned int ppi; > int err; > > @@ -284,19 +333,20 @@ int kvm_timer_hyp_init(void) > if (!timecounter) > return -ENODEV; > > - np = of_find_matching_node(NULL, arch_timer_of_match); > - if (!np) { > - kvm_err("kvm_arch_timer: can't find DT node\n"); > - return -ENODEV; > - } > + /* PPI parsing: try DT first, then ACPI */ > + err = kvm_timer_ppi_dt_parse(&ppi); > +#ifdef CONFIG_ACPI > + if (err && !acpi_disabled) > + err = kvm_timer_ppi_acpi_parse(&ppi); > +#endif > > - ppi = irq_of_parse_and_map(np, 2); > - if (!ppi) { > - kvm_err("kvm_arch_timer: no virtual timer interrupt\n"); > - err = -EINVAL; > - goto out; > + if (err) { > + kvm_err("kvm_arch_timer: can't find virtual timer info or " > + "config virtual timer interrupt\n"); > + return err; > } > > + /* configure IRQ handler */ > err = request_percpu_irq(ppi, kvm_arch_timer_handler, > "kvm guest timer", kvm_get_running_vcpus()); > if (err) { > @@ -319,14 +369,13 @@ int kvm_timer_hyp_init(void) > goto out_free; > } > > - kvm_info("%s IRQ%d\n", np->name, ppi); > + kvm_info("timer IRQ%d\n", ppi); > on_each_cpu(kvm_timer_init_interrupt, NULL, 1); > > goto out; > out_free: > free_percpu_irq(ppi, kvm_get_running_vcpus()); > out: > - of_node_put(np); > return err; > } > > -- > 1.8.3.1 > > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 06/10/2015 12:16 PM, Wei Huang wrote: > This patches enables ACPI support for KVM virtual arch timer. It allows > KVM to parse ACPI table for arch timer PPI when DT table is not present. > > Signed-off-by: Alexander Spyridaki <a.spyridakis@virtualopensystems.com> > Signed-off-by: Wei Huang <wei@redhat.com> > --- > virt/kvm/arm/arch_timer.c | 75 +++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 62 insertions(+), 13 deletions(-) > > diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c > index 98c95f2..a9da75a 100644 > --- a/virt/kvm/arm/arch_timer.c > +++ b/virt/kvm/arm/arch_timer.c > @@ -21,6 +21,7 @@ > #include <linux/kvm.h> > #include <linux/kvm_host.h> > #include <linux/interrupt.h> > +#include <linux/acpi.h> > > #include <clocksource/arm_arch_timer.h> > #include <asm/arch_timer.h> > @@ -274,9 +275,57 @@ static const struct of_device_id arch_timer_of_match[] = { > {}, > }; > > -int kvm_timer_hyp_init(void) > +static int kvm_timer_ppi_dt_parse(unsigned int *ppi) > { > struct device_node *np; > + > + np = of_find_matching_node(NULL, arch_timer_of_match); > + if (!np) > + return -ENODEV; > + > + *ppi = irq_of_parse_and_map(np, 2); > + if (*ppi == 0) { > + of_node_put(np); > + return -EINVAL; > + } > + > + return 0; > +} > + > +#ifdef CONFIG_ACPI > +struct acpi_table_gtdt *gtdt_acpi; > +static void arch_timer_acpi_parse(struct acpi_table_header *table) > +{ > + gtdt_acpi = container_of(table, struct acpi_table_gtdt, header); > +} > + > +static int kvm_timer_ppi_acpi_parse(unsigned int *ppi) > +{ > + u32 flags; > + int trigger, polarity; > + > + /*Get the interrupt number from the GTDT table */ > + acpi_table_parse(ACPI_SIG_GTDT, > + (acpi_tbl_table_handler)arch_timer_acpi_parse); > + > + if (!gtdt_acpi->virtual_timer_interrupt) > + return -EINVAL; ... > + > + flags = gtdt_acpi->virtual_timer_flags; > + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE > + : ACPI_LEVEL_SENSITIVE; > + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW > + : ACPI_ACTIVE_HIGH; > + > + *ppi = acpi_register_gsi(NULL, gtdt_acpi->virtual_timer_interrupt, > + trigger, polarity); Hmm, this is another duplication of getting trigger/polarity and registering the interrupt, currently we are working on introducing gtdt.c and put common used functions there [1], but I think this is just some nitpick, we can refactor it later when that patch set is accepted. [1]: https://lkml.org/lkml/2015/6/10/367 Thanks Hanjun -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 98c95f2..a9da75a 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -21,6 +21,7 @@ #include <linux/kvm.h> #include <linux/kvm_host.h> #include <linux/interrupt.h> +#include <linux/acpi.h> #include <clocksource/arm_arch_timer.h> #include <asm/arch_timer.h> @@ -274,9 +275,57 @@ static const struct of_device_id arch_timer_of_match[] = { {}, }; -int kvm_timer_hyp_init(void) +static int kvm_timer_ppi_dt_parse(unsigned int *ppi) { struct device_node *np; + + np = of_find_matching_node(NULL, arch_timer_of_match); + if (!np) + return -ENODEV; + + *ppi = irq_of_parse_and_map(np, 2); + if (*ppi == 0) { + of_node_put(np); + return -EINVAL; + } + + return 0; +} + +#ifdef CONFIG_ACPI +struct acpi_table_gtdt *gtdt_acpi; +static void arch_timer_acpi_parse(struct acpi_table_header *table) +{ + gtdt_acpi = container_of(table, struct acpi_table_gtdt, header); +} + +static int kvm_timer_ppi_acpi_parse(unsigned int *ppi) +{ + u32 flags; + int trigger, polarity; + + /*Get the interrupt number from the GTDT table */ + acpi_table_parse(ACPI_SIG_GTDT, + (acpi_tbl_table_handler)arch_timer_acpi_parse); + + if (!gtdt_acpi->virtual_timer_interrupt) + return -EINVAL; + + flags = gtdt_acpi->virtual_timer_flags; + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE + : ACPI_LEVEL_SENSITIVE; + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW + : ACPI_ACTIVE_HIGH; + + *ppi = acpi_register_gsi(NULL, gtdt_acpi->virtual_timer_interrupt, + trigger, polarity); + + return 0; +} +#endif + +int kvm_timer_hyp_init(void) +{ unsigned int ppi; int err; @@ -284,19 +333,20 @@ int kvm_timer_hyp_init(void) if (!timecounter) return -ENODEV; - np = of_find_matching_node(NULL, arch_timer_of_match); - if (!np) { - kvm_err("kvm_arch_timer: can't find DT node\n"); - return -ENODEV; - } + /* PPI parsing: try DT first, then ACPI */ + err = kvm_timer_ppi_dt_parse(&ppi); +#ifdef CONFIG_ACPI + if (err && !acpi_disabled) + err = kvm_timer_ppi_acpi_parse(&ppi); +#endif - ppi = irq_of_parse_and_map(np, 2); - if (!ppi) { - kvm_err("kvm_arch_timer: no virtual timer interrupt\n"); - err = -EINVAL; - goto out; + if (err) { + kvm_err("kvm_arch_timer: can't find virtual timer info or " + "config virtual timer interrupt\n"); + return err; } + /* configure IRQ handler */ err = request_percpu_irq(ppi, kvm_arch_timer_handler, "kvm guest timer", kvm_get_running_vcpus()); if (err) { @@ -319,14 +369,13 @@ int kvm_timer_hyp_init(void) goto out_free; } - kvm_info("%s IRQ%d\n", np->name, ppi); + kvm_info("timer IRQ%d\n", ppi); on_each_cpu(kvm_timer_init_interrupt, NULL, 1); goto out; out_free: free_percpu_irq(ppi, kvm_get_running_vcpus()); out: - of_node_put(np); return err; }