diff mbox

[V2,1/5] kvm: arm64: Enable ACPI support for virt arch timer

Message ID 1433909767-12189-2-git-send-email-wei@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Wei Huang June 10, 2015, 4:16 a.m. UTC
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(-)

Comments

Andrew Jones June 10, 2015, 12:51 p.m. UTC | #1
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
Hanjun Guo June 11, 2015, 11:27 a.m. UTC | #2
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 mbox

Patch

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;
 }