All of lore.kernel.org
 help / color / mirror / Atom feed
From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 15/15] virt: arm: support hip04 gic
Date: Thu, 15 May 2014 10:42:00 +0100	[thread overview]
Message-ID: <53748BE8.8060203@arm.com> (raw)
In-Reply-To: <1399795571-17231-16-git-send-email-haojian.zhuang@linaro.org>

On 11/05/14 09:06, Haojian Zhuang wrote:
> In ARM standard GIC, GICH_APR offset is 0xf0 & GICH_LR0 offset is 0x100.
> In HiP04 GIC, GICH_APR offset is 0x70 & GICH_LR0 offset is 0x80.
> 
> Now reuse the nr_lr field in struct vgic_cpu. Bit[31:16] is used to store
> GICH_APR offset in HiP04, and bit[15:0] is used to store real nr_lr
> variable. In ARM standard GIC, don't set bit[31:16]. So we could avoid
> to change the VGIC implementation in arm64.
> 
> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
> ---
>  arch/arm/kvm/interrupts_head.S  | 32 ++++++++++++++++++++++------
>  include/kvm/arm_vgic.h          |  5 ++++-
>  include/linux/irqchip/arm-gic.h |  6 ++++++
>  virt/kvm/arm/vgic.c             | 47 +++++++++++++++++++++++++++++------------
>  4 files changed, 69 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
> index 76af9302..7aacaff 100644
> --- a/arch/arm/kvm/interrupts_head.S
> +++ b/arch/arm/kvm/interrupts_head.S
> @@ -419,7 +419,10 @@ vcpu	.req	r0		@ vcpu pointer always in r0
>  	ldr	r7, [r2, #GICH_EISR1]
>  	ldr	r8, [r2, #GICH_ELRSR0]
>  	ldr	r9, [r2, #GICH_ELRSR1]
> -	ldr	r10, [r2, #GICH_APR]
> +	ldr	r10, [r11, #VGIC_CPU_NR_LR]

Please rename this field to something else, now that it contains more
than the number of LRs.

> +	movs	r10, r10, lsr #HWCFG_APR_SHIFT
> +	ldrne	r10, [r2, r10]
> +	ldreq	r10, [r2, #GICH_APR]

No. Just encode the offset there always. No need for a test.

>  	str	r3, [r11, #VGIC_CPU_HCR]
>  	str	r4, [r11, #VGIC_CPU_VMCR]
> @@ -435,9 +438,16 @@ vcpu	.req	r0		@ vcpu pointer always in r0
>  	str	r5, [r2, #GICH_HCR]
>  
>  	/* Save list registers */
> -	add	r2, r2, #GICH_LR0
> -	add	r3, r11, #VGIC_CPU_LR
>  	ldr	r4, [r11, #VGIC_CPU_NR_LR]
> +	addeq	r2, r2, #GICH_LR0
> +	movne	r10, r4, lsr #HWCFG_APR_SHIFT
> +	/* the offset between GICH_APR & GICH_LR0 is 0x10 */
> +	addne	r10, r10, #0x10
> +	addne	r2, r2, r10
> +	add	r3, r11, #VGIC_CPU_LR
> +	/* Get NR_LR from VGIC_CPU_NR_LR */
> +	ldr	r6, =HWCFG_NR_LR_MASK
> +	and	r4, r4, r6

And the above simplifies all this complicated mess.

>  1:	ldr	r6, [r2], #4
>  	str	r6, [r3], #4
>  	subs	r4, r4, #1
> @@ -469,12 +479,22 @@ vcpu	.req	r0		@ vcpu pointer always in r0
>  
>  	str	r3, [r2, #GICH_HCR]
>  	str	r4, [r2, #GICH_VMCR]
> -	str	r8, [r2, #GICH_APR]
> +	ldr	r6, [r11, #VGIC_CPU_NR_LR]
> +	movs	r6, r6, lsr #HWCFG_APR_SHIFT
> +	strne	r8, [r2, r6]
> +	streq	r8, [r2, #GICH_APR]
>  
>  	/* Restore list registers */
> -	add	r2, r2, #GICH_LR0
> -	add	r3, r11, #VGIC_CPU_LR
>  	ldr	r4, [r11, #VGIC_CPU_NR_LR]
> +	addeq	r2, r2, #GICH_LR0
> +	movne	r6, r4, lsr #HWCFG_APR_SHIFT
> +	/* the offset between GICH_APR & GICH_LR0 is 0x10 */
> +	addne	r6, r6, #0x10
> +	addne	r2, r2, r6
> +	/* Get NR_LR from VGIC_CPU_NR_LR */
> +	add	r3, r11, #VGIC_CPU_LR
> +	ldr	r6, =HWCFG_NR_LR_MASK
> +	and	r4, r4, r6

Same here.

>  1:	ldr	r6, [r3], #4
>  	str	r6, [r2], #4
>  	subs	r4, r4, #1
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index f27000f..089de25 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -122,7 +122,10 @@ struct vgic_cpu {
>  	/* Bitmap of used/free list registers */
>  	DECLARE_BITMAP(	lr_used, VGIC_MAX_LRS);
>  
> -	/* Number of list registers on this CPU */
> +	/*
> +	 * bit[31:16]: GICH_APR offset
> +	 * bit[15:0]:  Number of list registers on this CPU
> +	 */
>  	int		nr_lr;

Make it a u32 to reflect the encoding, rename it to reflect the change
in functionality.

>  
>  	/* CPU vif control registers for world switch */
> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> index 45e2d8c..5530388 100644
> --- a/include/linux/irqchip/arm-gic.h
> +++ b/include/linux/irqchip/arm-gic.h
> @@ -49,6 +49,8 @@
>  #define GICH_ELRSR1 			0x34
>  #define GICH_APR			0xf0
>  #define GICH_LR0			0x100
> +#define HIP04_GICH_APR			0x70
> +/* GICH_LR0 offset in HiP04 is 0x80 */
>  
>  #define GICH_HCR_EN			(1 << 0)
>  #define GICH_HCR_UIE			(1 << 1)
> @@ -73,6 +75,10 @@
>  #define GICH_MISR_EOI			(1 << 0)
>  #define GICH_MISR_U			(1 << 1)
>  
> +#define HWCFG_NR_LR_MASK	0xffff
> +#define HWCFG_APR_MASK		0xffff
> +#define HWCFG_APR_SHIFT		16

HWCFG_APR_MASK is wrong, as it should be shifted.

>  #ifndef __ASSEMBLY__
>  
>  struct device_node;
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 47b2983..e635b9b 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -97,7 +97,7 @@ static void vgic_retire_disabled_irqs(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 u32 vgic_hw_cfg;
>  
>  static unsigned int vgic_maint_irq;
>  
> @@ -624,9 +624,9 @@ static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
>  	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>  	int vcpu_id = vcpu->vcpu_id;
>  	int i, irq, source_cpu;
> -	u32 *lr;
> +	u32 *lr, nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;

Define an accessor (vgic_nr_lr(vcpu)). and use it everywhere you've
introduced this construct.

>  
> -	for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
> +	for_each_set_bit(i, vgic_cpu->lr_used, nr_lr) {
>  		lr = &vgic_cpu->vgic_lr[i];
>  		irq = LR_IRQID(*lr);
>  		source_cpu = LR_CPUID(*lr);
> @@ -1005,8 +1005,9 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>  	int lr;
> +	int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
>  
> -	for_each_set_bit(lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
> +	for_each_set_bit(lr, vgic_cpu->lr_used, nr_lr) {
>  		int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
>  
>  		if (!vgic_irq_is_enabled(vcpu, irq)) {
> @@ -1025,6 +1026,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
>  {
>  	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>  	int lr;
> +	int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
>  
>  	/* Sanitize the input... */
>  	BUG_ON(sgi_source_id & ~7);
> @@ -1046,9 +1048,8 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
>  	}
>  
>  	/* 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)
> +	lr = find_first_zero_bit((unsigned long *)vgic_cpu->lr_used, nr_lr);
> +	if (lr >= nr_lr)
>  		return false;
>  
>  	kvm_debug("LR%d allocated for IRQ%d %x\n", lr, irq, sgi_source_id);
> @@ -1181,9 +1182,10 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
>  		 * active bit.
>  		 */
>  		int lr, irq;
> +		int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
>  
>  		for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_eisr,
> -				 vgic_cpu->nr_lr) {
> +				 nr_lr) {
>  			irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
>  
>  			vgic_irq_clear_active(vcpu, irq);
> @@ -1221,13 +1223,13 @@ 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;
>  	int lr, pending;
> +	int nr_lr = vgic_cpu->nr_lr & HWCFG_NR_LR_MASK;
>  	bool level_pending;
>  
>  	level_pending = vgic_process_maintenance(vcpu);
>  
>  	/* Clear mappings for empty LRs */
> -	for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr,
> -			 vgic_cpu->nr_lr) {
> +	for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr, nr_lr) {
>  		int irq;
>  
>  		if (!test_and_clear_bit(lr, vgic_cpu->lr_used))
> @@ -1241,8 +1243,8 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
>  
>  	/* 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)
> +				      nr_lr);
> +	if (level_pending || pending < nr_lr)
>  		set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu);
>  }
>  
> @@ -1438,7 +1440,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
>  	 */
>  	vgic_cpu->vgic_vmcr = 0;
>  
> -	vgic_cpu->nr_lr = vgic_nr_lr;
> +	vgic_cpu->nr_lr = vgic_hw_cfg;
>  	vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */
>  
>  	return 0;
> @@ -1470,17 +1472,33 @@ static struct notifier_block vgic_cpu_nb = {
>  	.notifier_call = vgic_cpu_notify,
>  };
>  
> +static const struct of_device_id of_vgic_ids[] = {
> +	{
> +		.compatible = "arm,cortex-a15-gic",
> +	}, {
> +		.compatible = "hisilicon,hip04-gic",
> +		.data = (void *)HIP04_GICH_APR,
> +	}, {
> +	},
> +};
> +
>  int kvm_vgic_hyp_init(void)
>  {
>  	int ret;
>  	struct resource vctrl_res;
>  	struct resource vcpu_res;
> +	const struct of_device_id *match;
> +	u32 vgic_nr_lr;
>  
> -	vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic");
> +	vgic_node = of_find_matching_node_and_match(NULL, of_vgic_ids, &match);
>  	if (!vgic_node) {
>  		kvm_err("error: no compatible vgic node in DT\n");
>  		return -ENODEV;
>  	}
> +	/* If it's standard ARM GIC, high word in vgic_hw_cfg is 0.
> +	 * Otherwise, it's the offset of non-standard GICH_APR (in HiP04).
> +	 */
> +	vgic_hw_cfg = (unsigned int)match->data << HWCFG_APR_SHIFT;
>  
>  	vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0);
>  	if (!vgic_maint_irq) {
> @@ -1517,6 +1535,7 @@ int kvm_vgic_hyp_init(void)
>  
>  	vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR);
>  	vgic_nr_lr = (vgic_nr_lr & 0x3f) + 1;
> +	vgic_hw_cfg |= vgic_nr_lr;
>  
>  	ret = create_hyp_io_mappings(vgic_vctrl_base,
>  				     vgic_vctrl_base + resource_size(&vctrl_res),
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

  reply	other threads:[~2014-05-15  9:42 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-11  8:05 [PATCH v6 00/15] enable HiP04 SoC Haojian Zhuang
2014-05-11  8:05 ` [PATCH v6 01/15] ARM: debug: add HiP04 debug uart Haojian Zhuang
2014-05-11  8:05 ` [PATCH v6 02/15] irq: gic: use mask field in GICC_IAR Haojian Zhuang
2014-05-19  0:40   ` Jason Cooper
2014-05-11  8:05 ` [PATCH v6 03/15] irq: gic: support hip04 gic Haojian Zhuang
2014-05-15  9:34   ` Marc Zyngier
2014-05-15 11:14     ` Arnd Bergmann
2014-05-15 12:08       ` Christoffer Dall
2014-05-15 12:13         ` Arnd Bergmann
2014-05-15 12:16           ` Christoffer Dall
2014-05-20  3:24     ` Haojian Zhuang
2014-05-20  9:02       ` Marc Zyngier
2014-05-20  9:35         ` Haojian Zhuang
2014-05-20  9:42           ` Marc Zyngier
2014-05-19  2:05   ` Jason Cooper
2014-05-20  3:35     ` Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 04/15] ARM: mcpm: support 4 clusters Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 05/15] ARM: hisi: add ARCH_HISI Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 06/15] ARM: hisi: enable MCPM implementation Haojian Zhuang
2014-05-13  8:28   ` Dave Martin
2014-05-13  9:46     ` Haojian Zhuang
2014-05-13 11:44   ` [PATCH v7 " Haojian Zhuang
2014-05-13 19:43     ` Nicolas Pitre
2014-05-15  6:23       ` Haojian Zhuang
2014-05-15 20:01         ` Nicolas Pitre
2014-05-20  4:43           ` Haojian Zhuang
2014-05-21 10:02             ` Dave Martin
2014-05-21 13:52             ` Nicolas Pitre
2014-05-11  8:06 ` [PATCH v6 07/15] ARM: hisi: enable HiP04 Haojian Zhuang
2014-05-13 11:45   ` [PATCH v7 " Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 08/15] document: dt: add the binding on HiP04 Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 09/15] document: dt: add the binding on HiP04 clock Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 10/15] ARM: dts: append hip04 dts Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 11/15] ARM: config: append lpae configuration Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 12/15] ARM: config: append hip04_defconfig Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 13/15] ARM: config: select ARCH_HISI in hi3xxx_defconfig Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 14/15] ARM: hisi: enable erratum 798181 of A15 on HiP04 Haojian Zhuang
2014-05-11  8:06 ` [PATCH v6 15/15] virt: arm: support hip04 gic Haojian Zhuang
2014-05-15  9:42   ` Marc Zyngier [this message]
2014-05-15 13:09     ` Haojian Zhuang
2014-05-15 13:26       ` Marc Zyngier
2014-07-01  8:57         ` Haojian Zhuang
2014-05-20 10:51       ` Christoffer Dall
2014-05-14 18:37 ` [PATCH v6 00/15] enable HiP04 SoC Arnd Bergmann
2014-05-15  9:20   ` Haojian Zhuang
2014-05-15  9:31     ` Marc Zyngier
2014-05-16  5:07       ` Jason Cooper
2014-05-16  7:57         ` Marc Zyngier
2014-05-16 13:31           ` Jason Cooper
2014-05-16 19:09           ` Jason Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53748BE8.8060203@arm.com \
    --to=marc.zyngier@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.