Re: [Xen-devel] [PATCH 1/1] hw/intc/arm_gicv3_its: Fix the VM termination in vm_change_state_handler()

2017-11-03 Thread Shanker Donthineni
Thanks Julien, sorry for sending to XEN mailing list and it was my mistake.

Thanks,
Shanker

-Original Message-
From: Xen-devel [mailto:xen-devel-boun...@lists.xen.org] On Behalf Of Julien 
Grall
Sent: Friday, November 3, 2017 6:51 AM
To: Shanker Donthineni <shank...@codeaurora.org>; xen-devel 
<xen-de...@lists.xensource.com>; Julien Grall <julien.gr...@arm.com>; Stefano 
Stabellini <sstabell...@kernel.org>
Cc: Philip Elcan <pel...@codeaurora.org>; Vikram Sethi <vikr...@codeaurora.org>
Subject: Re: [Xen-devel] [PATCH 1/1] hw/intc/arm_gicv3_its: Fix the VM 
termination in vm_change_state_handler()

Hi Shanker,

I think you sent this patch to the wrong ML and people. This patch seem KVM 
specific.

Cheers,

On 03/11/17 11:33, Shanker Donthineni wrote:
> The commit cddafd8f353d ("hw/intc/arm_gicv3_its: Implement state save
> /restore") breaks the backward compatibility with the older kernels 
> where vITS save/restore support is not available. The vmstate function
> vm_change_state_handler() should not be registered if the running 
> kernel doesn't support ITS save/restore feature. Otherwise VM instance 
> will be killed whenever vmstate callback function is invoked.
> 
> Observed a virtual machine shutdown with QEMU-2.10+linux-4.11 when 
> testing the reboot command "virsh reboot  --mode acpi" instead of 
> reboot.
> 
> KVM Error: 'KVM_SET_DEVICE_ATTR failed: Group 4 attr 0x01'
> 
> Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
> ---
>   hw/intc/arm_gicv3_its_kvm.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c 
> index 39903d5..9b00ce5 100644
> --- a/hw/intc/arm_gicv3_its_kvm.c
> +++ b/hw/intc/arm_gicv3_its_kvm.c
> @@ -111,13 +111,13 @@ static void kvm_arm_its_realize(DeviceState *dev, Error 
> **errp)
>   error_free(s->migration_blocker);
>   return;
>   }
> +} else {
> +qemu_add_vm_change_state_handler(vm_change_state_handler, s);
>   }
>   
>   kvm_msi_use_devid = true;
>   kvm_gsi_direct_mapping = false;
>   kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
> -
> -qemu_add_vm_change_state_handler(vm_change_state_handler, s);
>   }
>   
>   /**
> 

--
Julien Grall

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 1/1] hw/intc/arm_gicv3_its: Fix the VM termination in vm_change_state_handler()

2017-11-03 Thread Shanker Donthineni
The commit cddafd8f353d ("hw/intc/arm_gicv3_its: Implement state save
/restore") breaks the backward compatibility with the older kernels
where vITS save/restore support is not available. The vmstate function
vm_change_state_handler() should not be registered if the running kernel
doesn't support ITS save/restore feature. Otherwise VM instance will be
killed whenever vmstate callback function is invoked.

Observed a virtual machine shutdown with QEMU-2.10+linux-4.11 when testing
the reboot command "virsh reboot  --mode acpi" instead of reboot.

KVM Error: 'KVM_SET_DEVICE_ATTR failed: Group 4 attr 0x01'

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 hw/intc/arm_gicv3_its_kvm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index 39903d5..9b00ce5 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -111,13 +111,13 @@ static void kvm_arm_its_realize(DeviceState *dev, Error 
**errp)
 error_free(s->migration_blocker);
 return;
 }
+} else {
+qemu_add_vm_change_state_handler(vm_change_state_handler, s);
 }
 
 kvm_msi_use_devid = true;
 kvm_gsi_direct_mapping = false;
 kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
-
-qemu_add_vm_change_state_handler(vm_change_state_handler, s);
 }
 
 /**
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] xen/arm: acpi: Map MMIO on fault in stage-2 page table for the hardware domain

2017-03-30 Thread Shanker Donthineni
Hi Julien,


On 03/30/2017 07:58 AM, Julien Grall wrote:
>
> On 30/03/17 13:52, Shanker Donthineni wrote:
>> Hi Julien,
> Hi Shanker,
>
>> On 03/30/2017 07:43 AM, Julien Grall wrote:
>>> Shanker: You mentioned offline that you tested the patch. May I add
>>> your tested-by?
>> Sure add my tested-by. If you want I can test one more time this mailing 
>> list patch.
> The code is the same, but it would not hurt to have another go at it :).
>
> FWIW, I did some testing on Juno with a small patch to turn the mapping
> hypercall into a nop and adding a debug message when mapping:
>

Tested-by: Shanker Donthineni <shank...@codeaurora.org>

This patch has been tested on Qualcomm Datacenter Technologies QDF2400 server 
platform with ACPI based XEN/DOM0.

> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 626376090d..dd1b0bd2b2 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1116,6 +1116,8 @@ int map_dev_mmio_region(struct domain *d,
>  {
>  int res;
>  
> +return 0;
> +
>  if ( !(nr && iomem_access_permitted(d, mfn_x(mfn), mfn_x(mfn) + nr - 1)) 
> )
>  return 0;
>  
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index ebf915bb3b..9e6d2dafc8 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -2643,7 +2643,11 @@ static void do_trap_data_abort_guest(struct 
> cpu_user_regs *regs,
>  return;
>  
>  if ( try_map_mmio(_gfn(paddr_to_pfn(info.gpa))) )
> +{
> +gdprintk(XENLOG_DEBUG, "Map %#"PRIpaddr" - %#"PRIpaddr"\n",
> + info.gpa, info.gpa + PAGE_SIZE - 1);
>  return;
> +}
>  
>  break;
>  default:
>
> Cheers,
>

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] xen/arm: acpi: Map MMIO on fault in stage-2 page table for the hardware domain

2017-03-30 Thread Shanker Donthineni
Hi Julien,


On 03/30/2017 07:43 AM, Julien Grall wrote:
> When booting using ACPI, not all MMIOs can be discovered by parsing the
> static tables or the UEFI memory map. A lot of them will be described in
> the DSDT. However, Xen does not have an AML parser which requires us to
> find a different approach.
>
> During the first discussions on supporting ACPI (see design doc [1]), it
> was decided to rely on the hardware domain to make a request to the
> hypervisor to map the MMIO region in stage-2 page table before accessing
> it. This approach works fine if the OS has limited hooks to modify the
> page tables.
>
> In the case of Linux kernel, notifiers have been added to map
> the MMIO regions when adding a new AMBA/platform device. Whilst this is
> covering most of the MMIOs, some of them (e.g OpRegion, ECAM...) are not
> related to a specific device or the driver is not using the
> AMBA/platform API. So more hooks would need to be added in the code.
>
> Various approaches have been discussed (see [2]), one of them was to
> create stage-2 mappings seamlessly in Xen upon hardware memory faults.
> This approach was first ruled out because it relies on the hardware
> domain to probe the region before any use. So this would not work when
> DMA'ing to another device's MMIO region when the device is protected by
> an SMMU. It has been pointed out that this is a limited use case compare
> to DMA'ing between MMIO and RAM.
>
> This patch implements this approach. All MMIOs region will be mapped in
> stage-2 using p2m_mmio_direct_c (i.e normal memory outer and inner
> write-back cacheable). The stage-1 page table will be in control of the
> memory attribute. This is fine because the hardware domain is a trusted
> domain.
>
> Note that MMIO will only be mapped on a data abort fault. It is assumed
> that it will not be possible to execute code from MMIO
> (p2m_mmio_direct_c will forbid that).
>
> As mentioned above, this solution will cover most of the cases. If a
> platform requires to do DMA'ing to another device's MMIO region without
> any access performed by the OS. Then it will be expected to have
> specific platform code in the hypervisor to map the MMIO at boot time or
> the OS to use the existing hypercalls (i.e XENMEM_add_to_add_physmap{,_batch})
> before any access.
>
> [1] https://lists.xen.org/archives/html/xen-devel/2015-11/msg00488.html
> [2] https://marc.info/?l=linux-arm-kernel=148469169210500=2
>
> Signed-off-by: Julien Grall <julien.gr...@arm.com>
>
> ---
> This patch is a candidate for Xen 4.9. Whilst the last posting date
> was few days ago, I think it would be good to have this patch in the
> next release. Although ACPI support for ARM64 is still a technical
> preview, it would help servers to test Xen upstream on their platform
> with ACPI and provide feedback on missing features.
>
> All the code is gated by !acpi_disabled and therefore will not be
> executed on when using Device Tree.
>
> RM hat on: I will leave the decision to Stefano.
>
> Shanker: You mentioned offline that you tested the patch. May I add
> your tested-by?

Sure add my tested-by. If you want I can test one more time this mailing list 
patch.

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v2 14/27] ARM: vGICv3: introduce basic ITS emulation bits

2017-03-16 Thread Shanker Donthineni
r / sizeof(*its->cmdbuf));
> +switch (its_cmd_get_command(cmdptr))
> +{
> +case GITS_CMD_SYNC:
> +/* We handle ITS commands synchronously, so we ignore SYNC. */
> + break;
> +default:
> +gdprintk(XENLOG_G_WARNING, "ITS: unhandled ITS command %ld\n",
> +   its_cmd_get_command(cmdptr));
> +break;
> +}
> +
> +its->creadr += ITS_CMD_SIZE;
> +if ( its->creadr == ITS_CMD_BUFFER_SIZE(its->cbaser) )
> +its->creadr = 0;
> +}
> +its->cwriter = writer;
> +
> +spin_unlock(>vcmd_lock);
> +
> +return 0;
> +}
> +
> +/*
> + * ITS registers read access *
> + */
> +
> +/*
> + * The physical address is encoded slightly differently depending on
> + * the used page size: the highest four bits are stored in the lowest
> + * four bits of the field for 64K pages.
> + */
> +static paddr_t get_baser_phys_addr(uint64_t reg)
> +{
> +if ( reg & BIT(9) )
> +return (reg & GENMASK(47, 16)) | ((reg & GENMASK(15, 12)) << 36);
> +else
> +return reg & GENMASK(47, 12);
> +}
> +
> +static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
> + register_t *r, void *priv)
> +{
> +struct virt_its *its = priv;
> +
> +switch ( info->gpa & 0x )
> +{
> +case VREG32(GITS_CTLR):
> +    if ( info->dabt.size != DABT_WORD ) goto bad_width;
> +*r = vgic_reg32_extract(its->enabled | BIT(31), info);
> + break;
> +case VREG32(GITS_IIDR):
> +if ( info->dabt.size != DABT_WORD ) goto bad_width;
> +*r = vgic_reg32_extract(GITS_IIDR_VALUE, info);
> +break;
> +case VREG64(GITS_TYPER):
> +if ( info->dabt.size < DABT_WORD ) goto bad_width;
> +*r = vgic_reg64_extract(0x1eff1, info);

Please don't hard-code Devbits (bits 17-13) value to 16 here. For dom0, at 
least match to Kconfig option, or use ITS hardware reported value. On Qualcomm 
server chips, GITS_TYPER.Devbit is set to 32bits.

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v2 05/27] ARM: GICv3 ITS: introduce ITS command handling

2017-03-16 Thread Shanker Donthineni
cpu, (collection_id & GENMASK(15, 0)));
> +cmd[2] |= GITS_VALID_BIT;
> +cmd[3] = 0x00;
> +
> +return its_send_command(its, cmd);
> +}
> +
> +/* Set up the (1:1) collection mapping for the given host CPU. */
> +int gicv3_its_setup_collection(unsigned int cpu)
> +{
> +struct host_its *its;
> +int ret;
> +
> +list_for_each_entry(its, _its_list, entry)
> +{
> +if ( !its->cmd_buf )
> +continue;
> +
> +ret = its_send_cmd_mapc(its, cpu, cpu);
> +if ( ret )
> +return ret;
> +
> +ret = its_send_cmd_sync(its, cpu);
> +if ( ret )
> +return ret;
> +
> +ret = gicv3_its_wait_commands(its);
> +if ( ret )
> +return ret;
> +}
> +
> +return 0;
> +}
> +
>  #define BASER_ATTR_MASK   \
>  ((0x3UL << GITS_BASER_SHAREABILITY_SHIFT)   | \
>   (0x7UL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) | \
> @@ -184,22 +326,59 @@ retry:
>  return -EINVAL;
>  }
>  
> +/*
> + * Before an ITS gets initialized, it should be in a quiescent state, where
> + * all outstanding commands and transactions have finished.
> + * So if the ITS is already enabled, turn it off and wait for all outstanding
> + * operations to get processed by polling the QUIESCENT bit.
> + */
> +static int gicv3_disable_its(struct host_its *hw_its)
> +{
> +uint32_t reg;
> +s_time_t deadline = NOW() + MILLISECS(100);
> +
> +reg = readl_relaxed(hw_its->its_base + GITS_CTLR);
> +if ( (reg & GITS_CTLR_QUIESCENT) && !(reg & GITS_CTLR_ENABLE) )

nit: I prefer changing to 'if ( !(reg & GITS_CTLR_ENABLE) && (reg & 
GITS_CTLR_QUIESCENT) ) ' because bit GITS_CTLR_QUIESCENT is not valid if ITS 
hardware is in enabled state.

>  #endif

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 09/28] ARM: GICv3 ITS: map device and LPIs to the ITS on physdev_op hypercall

2017-03-01 Thread Shanker Donthineni

Hi Julien,


On 02/28/2017 12:29 PM, Julien Grall wrote:



On 27/02/17 17:20, Andre Przywara wrote:

Hi,


Hi Andre,


On 24/02/17 19:57, Shanker Donthineni wrote:

Hi Julien,


On 01/31/2017 10:18 AM, Julien Grall wrote:



On 31/01/17 16:02, Jaggi, Manish wrote:



On 1/31/2017 8:47 PM, Julien Grall wrote:



On 31/01/17 14:08, Jaggi, Manish wrote:

Hi Julien,

On 1/31/2017 7:16 PM, Julien Grall wrote:

On 31/01/17 13:19, Jaggi, Manish wrote:

On 1/31/2017 6:13 PM, Julien Grall wrote:

On 31/01/17 10:29, Jaggi, Manish wrote:

If you please go back to your comment where you wrote "we need to
find another way to get the DeviceID", I was referring that we
should add that another way in this series so that correct DeviceID
is programmed in ITS.


This is not the first time I am saying this, just saying "we should
add that another way..." is not helpful. You should also provide
some details on what you would do.


Julien, As you suggested we need to find another way, I assumed you
had something in mind.


I gave suggestions on my e-mail but you may have missed it...


Since we both agree that sbdf!=deviceID, the current series of ITS
patches will program the incorrect deviceID so there is a need to
have a way to map sbdf with deviceID in xen.

One option could be to add a new hypercall to supply sbdf and
deviceID to xen.


... as well as the part where I am saying that I am not in favor to
implement an hypercall temporarily, and against adding a new hypercall
for only a couple of weeks. As you may know PHYSDEV hypercall are part
of the stable ABI and once they are added they cannot be removed.

So we need to be sure the hypercall is necessary. In this case, the
hypercall is not necessary as all the information can be found in the
firmware tables. However this is not implemented yet and part of the
discussion on PCI Passthrough (see [1]).

We need a temporary solution that does not involve any commitment 
on the

ABI until Xen is able to discover PCI.



Why can't  we handle ITS device creation whenever a virtual ITS driver
receives the MAPD command from dom0/domU. In case of dom0, it's 
straight

forward dom0 always passes the real ITS device through MAPD command.
This way we can support PCIe devices without hard-coded MSI(x) limit 
32,

and platform devices transparently. I used the below code to platform
and PCIe device MSI(x) functionality on QDF2400 server platform.


But this breaks our assumption that no ITS commands can ever be
propagated at guest's runtime, which is the cornerstone of this series.
I agree that this is unfortunate and allowing it would simplify things,
but after long discussions we came to the conclusion that it's not
feasible to do so:
A malicious guest could flood the virtual ITS with MAPD commands. Xen
would need to propagate those to the hardware, which relies on the host
command queue to have free slots, which we can't guarantee. For
technical reasons we can't reschedule the guest (because this is an MMIO
trap), also the domain actually triggering the "final" MAPD might not be
the culprit, but an actual legitimate user.
So we agreed upon issuing all hardware ITS commands before a guest
actually starts (DomUs), respectively on hypercalls for Dom0.
I think we can do exceptions for Dom0, since it's not supposed to be
malicious.


Thank you for summarizing the problem :).



Direct VLPI injection feature is included in GICv4 architecture. A new 
set of VLPI commands are introduced to map ITS vpend/vprop tables, ITTE 
setup, and maintenance operations for VLPIs. In case of direct VLPI 
injection, domU/dom0 LPI commands are mapped to VLPI commands. Some of 
these commands must be applied to a real ITS hardware whenever XEN 
receives the ITS commands during runtime.



Any thought on this, how we are going to support a direct VLPI injection 
without prolongating dom0/domU ITS commands to hardware at runtime?


--

Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] xen/arm: Hiding SMMUs from Dom0 when using ACPI on Xen

2017-02-27 Thread Shanker Donthineni

Hi Julien,


On 02/27/2017 08:12 AM, Julien Grall wrote:



On 27/02/17 13:23, Vijay Kilari wrote:

Hi Julien,


Hello Vijay,

On Wed, Feb 22, 2017 at 7:40 PM, Julien Grall <julien.gr...@arm.com> 
wrote:

Hello,

There was few discussions recently about hiding SMMUs from DOM0 when 
using

ACPI. I thought it would be good to have a separate thread for this.

When using ACPI, the SMMUs will be described in the IO Remapping Table
(IORT). The specification can be found on the ARM website [1].

For a brief summary, the IORT can be used to discover the SMMUs 
present on
the platform and find for a given device the ID to configure 
components such

as ITS (DeviceID) and SMMU (StreamID).

The appendix A in the specification gives an example how DeviceID and
StreamID can be found. For instance, when a PCI device is both 
protected by

an SMMU and MSI-capable the following translation will happen:
RID -> StreamID -> DeviceID

Currently, SMMUs are hidden from DOM0 because they are been used by 
Xen and
we don't support stage-1 SMMU. If we pass the IORT as it is, DOM0 
will try

to initialize SMMU and crash.

I first thought about using a Xen specific way (STAO) or extending a 
flag in

IORT. But that is not ideal.

So we would have to rewrite the IORT for DOM0. Given that a range of 
RID can
mapped to multiple ranges of DeviceID, we would have to translate 
RID one by
one to find the associated DeviceID. I think this may end up to 
complex code

and have a big IORT table.


Why can't we replace Output base of IORT of PCI node with SMMU output 
base?.

I mean similar to PCI node without SMMU, why can't replace output base
of PCI node with
SMMU's output base?.


Because I don't see anything in the spec preventing one RC ID mapping 
to produce multiple SMMU ID mapping. So which output base would you use?




Basically, remove SMMU nodes, and replaces output of the PCIe and named 
nodes ID mappings with ITS nodes.


RID --> StreamID  --> dviceID  --> ITS device id = RID --> dviceID  --> 
ITS device id




The issue I see is RID is [15:0] where is DeviceID is [17:0].


Actuality device id is 32bit field.



However, given that DeviceID will be used by DOM0 to only configure 
the ITS.
We have no need to use to have the DOM0 DeviceID equal to the host 
DeviceID.
So I think we could simplify our life by generating DeviceID for 
each RID

range.


If DOM0 DeviceID != host Device ID, then we cannot initialize ITS 
using DOM0
ITS commands (MAPD). So, is it concluded that ITS initializes all the 
devices

with platform specific Device ID's in Xen?.


Initializing ITS using DOM0 ITS command is a workaround until we get 
PCI passthrough done. It would still be possible to implement that 
with vDeviceID != pDeviceID as Xen would likely have the mapping 
between the 2 DeviceID.




I believe mapping dom0 ITS commands to XEN ITS commands one to one is 
the better approach.  Physical DeviceID is unique per ITS group, not a 
system wide unique ID. In case of direct VLPI,  LPI number has to be 
programmed whenever dom0/domU calls the MAPTI command but not at the 
time of PCIe device creation.



--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 09/28] ARM: GICv3 ITS: map device and LPIs to the ITS on physdev_op hypercall

2017-02-24 Thread Shanker Donthineni

Hi Julien,


On 01/31/2017 10:18 AM, Julien Grall wrote:



On 31/01/17 16:02, Jaggi, Manish wrote:



On 1/31/2017 8:47 PM, Julien Grall wrote:



On 31/01/17 14:08, Jaggi, Manish wrote:

Hi Julien,

On 1/31/2017 7:16 PM, Julien Grall wrote:

On 31/01/17 13:19, Jaggi, Manish wrote:

On 1/31/2017 6:13 PM, Julien Grall wrote:

On 31/01/17 10:29, Jaggi, Manish wrote:
If you please go back to your comment where you wrote "we need to 
find another way to get the DeviceID", I was referring that we 
should add that another way in this series so that correct DeviceID 
is programmed in ITS.


This is not the first time I am saying this, just saying "we should 
add that another way..." is not helpful. You should also provide 
some details on what you would do.


Julien, As you suggested we need to find another way, I assumed you 
had something in mind.


I gave suggestions on my e-mail but you may have missed it...

Since we both agree that sbdf!=deviceID, the current series of ITS 
patches will program the incorrect deviceID so there is a need to

have a way to map sbdf with deviceID in xen.

One option could be to add a new hypercall to supply sbdf and 
deviceID to xen.


... as well as the part where I am saying that I am not in favor to
implement an hypercall temporarily, and against adding a new hypercall
for only a couple of weeks. As you may know PHYSDEV hypercall are part
of the stable ABI and once they are added they cannot be removed.

So we need to be sure the hypercall is necessary. In this case, the
hypercall is not necessary as all the information can be found in the
firmware tables. However this is not implemented yet and part of the
discussion on PCI Passthrough (see [1]).

We need a temporary solution that does not involve any commitment on the
ABI until Xen is able to discover PCI.



Why can't  we handle ITS device creation whenever a virtual ITS driver 
receives the MAPD command from dom0/domU. In case of dom0, it's straight 
forward dom0 always passes the real ITS device through MAPD command. 
This way we can support PCIe devices without hard-coded MSI(x) limit 32, 
and platform devices transparently. I used the below code to platform 
and PCIe device MSI(x) functionality on QDF2400 server platform.


@@ -383,10 +384,17 @@ static int its_handle_mapd(struct virt_its *its, 
uint64_t *cmdptr)

 int size = its_cmd_get_size(cmdptr);
 bool valid = its_cmd_get_validbit(cmdptr);
 paddr_t itt_addr = its_cmd_mask_field(cmdptr, 2, 0, 52) & 
GENMASK(51, 8);

+int ret;

 if ( !its->dev_table )
 return -1;

+size = size < 4 ? 4 : size;
+ret = gicv3_its_map_guest_device(hardware_domain, devid, devid, 
size + 1,

+ valid);
+if (ret < 0)
+    return ret;
+


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 07/28] ARM: GICv3 ITS: introduce device mapping

2017-02-24 Thread Shanker Donthineni

Hi Andre,


On 02/22/2017 01:06 AM, Vijay Kilari wrote:

Hi Andre,

On Tue, Jan 31, 2017 at 12:01 AM, Andre Przywara <andre.przyw...@arm.com> wrote:

The ITS uses device IDs to map LPIs to a device. Dom0 will later use
those IDs, which we directly pass on to the host.
For this we have to map each device that Dom0 may request to a host
ITS device with the same identifier.
Allocate the respective memory and enter each device into an rbtree to
later be able to iterate over it or to easily teardown guests.

Signed-off-by: Andre Przywara <andre.przyw...@arm.com>
---
  xen/arch/arm/gic-v3-its.c| 188 ++-
  xen/arch/arm/vgic-v3.c   |   3 +
  xen/include/asm-arm/domain.h |   3 +
  xen/include/asm-arm/gic_v3_its.h |  28 ++
  4 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 6578e8a..4a3a394 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -21,8 +21,10 @@
  #include 
  #include 
  #include 
-#include 
+#include 
+#include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -94,6 +96,21 @@ static int its_send_cmd_mapc(struct host_its *its, int 
collection_id, int cpu)
  return its_send_command(its, cmd);
  }

+static int its_send_cmd_mapd(struct host_its *its, uint32_t deviceid,
+ int size, uint64_t itt_addr, bool valid)
+{
+uint64_t cmd[4];
+
+cmd[0] = GITS_CMD_MAPD | ((uint64_t)deviceid << 32);
+cmd[1] = size & GENMASK(4, 0);
+cmd[2] = itt_addr & GENMASK(51, 8);
+if ( valid )
+cmd[2] |= GITS_VALID_BIT;
+cmd[3] = 0x00;
+
+return its_send_command(its, cmd);
+}
+
  /* Set up the (1:1) collection mapping for the given host CPU. */
  int gicv3_its_setup_collection(int cpu)
  {
@@ -293,6 +310,7 @@ int gicv3_its_init(struct host_its *hw_its)
  reg = readq_relaxed(hw_its->its_base + GITS_TYPER);
  if ( reg & GITS_TYPER_PTA )
  hw_its->flags |= HOST_ITS_USES_PTA;
+hw_its->itte_size = GITS_TYPER_ITT_SIZE(reg);

  for ( i = 0; i < GITS_BASER_NR_REGS; i++ )
  {
@@ -339,6 +357,173 @@ int gicv3_its_init(struct host_its *hw_its)
  return 0;
  }

+static void remove_mapped_guest_device(struct its_devices *dev)
+{
+if ( dev->hw_its )
+its_send_cmd_mapd(dev->hw_its, dev->host_devid, 0, 0, false);
+
+xfree(dev->itt_addr);
+xfree(dev);
+}
+
+int gicv3_its_map_guest_device(struct domain *d, int host_devid,
+   int guest_devid, int bits, bool valid)
+{
+void *itt_addr = NULL;
+struct its_devices *dev, *temp;
+struct rb_node **new = >arch.vgic.its_devices.rb_node, *parent = NULL;
+struct host_its *hw_its;
+int ret;
+
+/* check for already existing mappings */
+spin_lock(>arch.vgic.its_devices_lock);
+while (*new)
+{
+temp = rb_entry(*new, struct its_devices, rbnode);
+
+if ( temp->guest_devid == guest_devid )
+{
+if ( !valid )
+rb_erase(>rbnode, >arch.vgic.its_devices);
+
+spin_unlock(>arch.vgic.its_devices_lock);
+
+if ( valid )
+return -EBUSY;
+
+remove_mapped_guest_device(temp);
+
+return 0;
+}
+
+if ( guest_devid < temp->guest_devid )
+new = &((*new)->rb_right);

Shouldn't be rb_left here?

+else
+new = &((*new)->rb_left);

Shouldn't be rb_right here?



I found the same thing when I tested ITS feature on Qualcomm platform.


+}

I see duplicate code in find and inserting node into rb_tree.


+
+if ( !valid )
+{
+ret = -ENOENT;
+goto out_unlock;
+}
+
+/*
+ * TODO: Work out the correct hardware ITS to use here.
+ * Maybe a per-platform function: devid -> ITS?
+ * Or parsing the DT to find the msi_parent?
+ * Or get Dom0 to give us this information?
+ * For now just use the first ITS.
+ */
+hw_its = list_first_entry(_its_list, struct host_its, entry);
+
+ret = -ENOMEM;
+
+itt_addr = _xmalloc(BIT(bits) * hw_its->itte_size, 256);


Please use _xzalloc() to avoid potential issues with ITS hardware 
prefetching feature.


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 04/28] ARM: GICv3 ITS: allocate device and collection table

2017-02-24 Thread Shanker Donthineni

Hi Andre


On 02/16/2017 01:03 PM, Shanker Donthineni wrote:

Hi Andre,


On 01/30/2017 12:31 PM, Andre Przywara wrote:

Each ITS maps a pair of a DeviceID (usually the PCI b/d/f triplet) and
an EventID (the MSI payload or interrupt ID) to a pair of LPI number
and collection ID, which points to the target CPU.
This mapping is stored in the device and collection tables, which 
software

has to provide for the ITS to use.
Allocate the required memory and hand it the ITS.
The maximum number of devices is limited to a compile-time constant
exposed in Kconfig.

Signed-off-by: Andre Przywara <andre.przyw...@arm.com>
---
  xen/arch/arm/Kconfig |  14 +
  xen/arch/arm/gic-v3-its.c| 129
+++
  xen/arch/arm/gic-v3.c|   5 ++
  xen/include/asm-arm/gic_v3_its.h |  55 -
  4 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 71734a1..81bc233 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -64,6 +64,20 @@ config MAX_PHYS_LPI_BITS
This can be overriden on the command line with the 
max_lpi_bits

parameter.

+config MAX_PHYS_ITS_DEVICE_BITS
+depends on HAS_ITS
+int "Number of device bits the ITS supports"
+range 1 32
+default "10"
+help
+  Specifies the maximum number of devices which want to use the
ITS.
+  Xen needs to allocates memory for the whole range very early.
+  The allocation scheme may be sparse, so a much larger 
number must
+  be supported to cover devices with a high bus number or 
those on

+  separate bus segments.
+  This can be overriden on the command line with the
max_its_device_bits
+  parameter.
+
  endmenu

  menu "ARM errata workaround via the alternative framework"
diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index ff0f571..c31fef6 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -20,9 +20,138 @@
  #include 
  #include 
  #include 
+#include 
+#include 
  #include 
  #include 
  #include 
+#include 
+
+#define BASER_ATTR_MASK   \
+((0x3UL << GITS_BASER_SHAREABILITY_SHIFT)   | \
+ (0x7UL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) | \
+ (0x7UL << GITS_BASER_INNER_CACHEABILITY_SHIFT))
+#define BASER_RO_MASK   (GENMASK(58, 56) | GENMASK(52, 48))
+
+static uint64_t encode_phys_addr(paddr_t addr, int page_bits)
+{
+uint64_t ret;
+
+if ( page_bits < 16 )
+return (uint64_t)addr & GENMASK(47, page_bits);
+
+ret = addr & GENMASK(47, 16);
+return ret | (addr & GENMASK(51, 48)) >> (48 - 12);
+}
+
+#define PAGE_BITS(sz) ((sz) * 2 + PAGE_SHIFT)
+
+static int its_map_baser(void __iomem *basereg, uint64_t regc, int
nr_items)
+{
+uint64_t attr, reg;
+int entry_size = ((regc >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) 
+ 1;

+int pagesz = 0, order, table_size;


Please try ITS page sizes in the order 64K, 16K and 4K to cover more ITS 
devices using a flat table. Similar to Linux ITS driver.



+void *buffer = NULL;
+
+attr  = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
+attr |= GIC_BASER_CACHE_SameAsInner <<
GITS_BASER_OUTER_CACHEABILITY_SHIFT;
+attr |= GIC_BASER_CACHE_RaWaWb << 
GITS_BASER_INNER_CACHEABILITY_SHIFT;

+
+/*
+ * Setup the BASE register with the attributes that we like. 
Then read

+ * it back and see what sticks (page size, cacheability and
shareability
+ * attributes), retrying if necessary.
+ */
+while ( 1 )
+{
+table_size = ROUNDUP(nr_items * entry_size,
BIT(PAGE_BITS(pagesz)));
+order = get_order_from_bytes(table_size);
+


Limit to 256 ITS pages, ITS spec doesn't support more than 256 ITS pages.

   /* Maximum of 256 ITS pages are allowed */
   if ( (table_size >> PAGE_BITS(pagesz)) > GITS_BASER_PAGES_MAX )
   table_size = BIT(PAGE_BITS(pagesz)) * GITS_BASER_PAGES_MAX;


+if ( !buffer )
+buffer = alloc_xenheap_pages(order, 0);
+if ( !buffer )
+return -ENOMEM;
+


Please zero memory memset(buffer, 0x00, order << PAGE_SHIFT)


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 04/28] ARM: GICv3 ITS: allocate device and collection table

2017-02-16 Thread Shanker Donthineni
@@ -42,8 +90,9 @@ void gicv3_its_dt_init(const struct dt_device_node *node);
  uint64_t gicv3_lpi_get_proptable(void);
  uint64_t gicv3_lpi_allocate_pendtable(void);

-/* Initialize the host structures for LPIs. */
+/* Initialize the host structures for LPIs and the host ITSes. */
  int gicv3_lpi_init_host_lpis(unsigned int nr_lpis);
+int gicv3_its_init(struct host_its *hw_its);

  #else

@@ -62,6 +111,10 @@ static inline int gicv3_lpi_init_host_lpis(unsigned int
nr_lpis)
  {
  return 0;
  }
+static inline int gicv3_its_init(struct host_its *hw_its)
+{
+return 0;
+}
  #endif /* CONFIG_HAS_ITS */

  #endif /* __ASSEMBLY__ */


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 15/28] ARM: vGICv3: introduce basic ITS emulation bits

2017-02-15 Thread Shanker Donthineni
ly differently depending on
+ * the used page size: the highest four bits are stored in the lowest
+ * four bits of the field for 64K pages.
+ */
+static paddr_t get_baser_phys_addr(uint64_t reg)
+{
+if ( reg & BIT(9) )
+return (reg & GENMASK(47, 16)) | ((reg & GENMASK(15, 12)) << 36);
+else
+return reg & GENMASK(47, 12);
+}
+
+static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
+ register_t *r, void *priv)
+{
+struct virt_its *its = priv;
+
+switch ( info->gpa & 0x )
+{
+case VREG32(GITS_CTLR):
+if ( info->dabt.size != DABT_WORD ) goto bad_width;
+*r = vgic_reg32_extract(its->enabled | BIT(31), info);
+   break;
+case VREG32(GITS_IIDR):
+if ( info->dabt.size != DABT_WORD ) goto bad_width;
+*r = vgic_reg32_extract(GITS_IIDR_VALUE, info);
+break;
+case VREG64(GITS_TYPER):
+if ( info->dabt.size < DABT_WORD ) goto bad_width;
+*r = vgic_reg64_extract(0x1eff1, info);
Why GITS_TYPER is hard-coded here? For DOM0, at least MOVP, ID_bits and 
Devbits fields should be same as hardware otherwise MSI(x) feature fails 
for some devices.


Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 04/28] ARM: GICv3 ITS: allocate device and collection table

2017-02-15 Thread Shanker Donthineni
 GITS_BASER_SHAREABILITY_MASK   (0x3ULL <<
GITS_BASER_SHAREABILITY_SHIFT)
+#define GITS_BASER_OUTER_CACHEABILITY_MASK   (0x7ULL <<
GITS_BASER_OUTER_CACHEABILITY_SHIFT)
+#define GITS_BASER_INNER_CACHEABILITY_MASK   (0x7ULL <<
GITS_BASER_INNER_CACHEABILITY_SHIFT)
+
  #ifndef __ASSEMBLY__
  #include 

@@ -27,6 +74,7 @@ struct host_its {
  const struct dt_device_node *dt_node;
  paddr_t addr;
  paddr_t size;
+void __iomem *its_base;
  };

  extern struct list_head host_its_list;
@@ -42,8 +90,9 @@ void gicv3_its_dt_init(const struct dt_device_node *node);
  uint64_t gicv3_lpi_get_proptable(void);
  uint64_t gicv3_lpi_allocate_pendtable(void);

-/* Initialize the host structures for LPIs. */
+/* Initialize the host structures for LPIs and the host ITSes. */
  int gicv3_lpi_init_host_lpis(unsigned int nr_lpis);
+int gicv3_its_init(struct host_its *hw_its);

  #else

@@ -62,6 +111,10 @@ static inline int gicv3_lpi_init_host_lpis(unsigned int
nr_lpis)
  {
  return 0;
  }
+static inline int gicv3_its_init(struct host_its *hw_its)
+{
+return 0;
+}
  #endif /* CONFIG_HAS_ITS */

  #endif /* __ASSEMBLY__ */


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH] arm/acpi: hide watchdog timer in GTDT table for dom0

2016-11-30 Thread Shanker Donthineni

Hi Julien,

We are using Fu's  [v5] patch series 
https://patchwork.codeaurora.org/patch/20325/ in our testing. We thought 
system crash in xen was related to watchdog timer driver, so removed the 
watchdog timer sections including GT blocks in GTDT to fix the crash. 
Let me root cause the issue and update the results to you by end of this 
week.


Thanks,
Shanker

--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH] arm/acpi: hide watchdog timer in GTDT table for dom0

2016-11-30 Thread Shanker Donthineni

Hi Julien,


On 11/30/2016 08:31 AM, Shanker Donthineni wrote:

Hi Julien,


On 11/30/2016 04:29 AM, Julien Grall wrote:

Hi Shanker,

On 29/11/2016 02:59, Shanker Donthineni wrote:

Either we have to hide the watchdog timer section in GTDT or emulate
watchdog timer block for dom0. Otherwise, system gets panic when
dom0 accesses its MMIO registers. The current XEN doesn't support
virtualization of watchdog timer, so hide the watchdog timer section
for dom0.


IHMO, the patch description is not really accurate. You are removing
the platform timer array that contains watchdog but also Block Timer.

Whilst you mention watchdog, you don't have a word on the Block Timer.



Sure, I'll include detailed description that has word  'Block Timer' 
in v2 patch.



Taking a step back, DOM0 is not able to use it because it does not
request to map the memory region (this is the behavior expected for
PCI and AMBA devices). So this is a bug in the kernel for me.


Not all the drivers/modules in the Linux kernel are bounded to a device
object 'struct device'.  The watchdog timer driver is one of this
category, neither a PCIe nor a AMBA device.

You can find GTDT watchdog timer code at 
https://lkml.org/lkml/2016/7/25/34.




Sorry, right link is https://lkml.org/lkml/2016/7/25/345


Assuming this would be fixed, what would be the drawback to give
access to dom0 to the watchdogs?


Absolutely no problem.


My worry with that change is what if in the future we decide to expose
watchdog to DOM0? Linux will still not be ready, unless we have Xen to
map those regions at DOM0 build time. That would break the design we
have for ACPI.



Agree, I was also thinking in the same direction. Let me create a v2
patch that does stage-2 map of MMIO regions at the time of building the
dom0 domain to fix the problem.


Regards,





--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH] arm/acpi: hide watchdog timer in GTDT table for dom0

2016-11-30 Thread Shanker Donthineni

Hi Julien,


On 11/30/2016 04:29 AM, Julien Grall wrote:

Hi Shanker,

On 29/11/2016 02:59, Shanker Donthineni wrote:

Either we have to hide the watchdog timer section in GTDT or emulate
watchdog timer block for dom0. Otherwise, system gets panic when
dom0 accesses its MMIO registers. The current XEN doesn't support
virtualization of watchdog timer, so hide the watchdog timer section
for dom0.


IHMO, the patch description is not really accurate. You are removing 
the platform timer array that contains watchdog but also Block Timer.


Whilst you mention watchdog, you don't have a word on the Block Timer.



Sure, I'll include detailed description that has word  'Block Timer'.

Taking a step back, DOM0 is not able to use it because it does not 
request to map the memory region (this is the behavior expected for 
PCI and AMBA devices). So this is a bug in the kernel for me.


Not all the drivers/modules in the Linux kernel are bounded to a device 
object 'struct device'.  The watchdog timer driver is one of this 
category, neither a PCIe nor a AMBA device.


You can find GTDT watchdog timer code at https://lkml.org/lkml/2016/7/25/34.

Assuming this would be fixed, what would be the drawback to give 
access to dom0 to the watchdogs?



Absolutely no problem.

My worry with that change is what if in the future we decide to expose 
watchdog to DOM0? Linux will still not be ready, unless we have Xen to 
map those regions at DOM0 build time. That would break the design we 
have for ACPI.




Agree, I was also thinking in the same direction. Let me create a v2 
patch that does stage-2 map of MMIO regions at the time of building the 
dom0 domain to fix the problem.



Regards,



--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH] arm/acpi: hide watchdog timer in GTDT table for dom0

2016-11-28 Thread Shanker Donthineni
Either we have to hide the watchdog timer section in GTDT or emulate
watchdog timer block for dom0. Otherwise, system gets panic when
dom0 accesses its MMIO registers. The current XEN doesn't support
virtualization of watchdog timer, so hide the watchdog timer section
for dom0.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain_build.c | 41 +
 xen/include/asm-arm/acpi.h  |  1 +
 2 files changed, 42 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index e8a400c..611c803 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1668,6 +1668,8 @@ static int acpi_create_xsdt(struct domain *d, struct 
membank tbl_add[])
ACPI_SIG_FADT, tbl_add[TBL_FADT].start);
 acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
+acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+   ACPI_SIG_GTDT, tbl_add[TBL_GTDT].start);
 xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
 
 xsdt->header.length = table_size;
@@ -1718,6 +1720,41 @@ static int acpi_create_stao(struct domain *d, struct 
membank tbl_add[])
 return 0;
 }
 
+static int acpi_create_gtdt(struct domain *d, struct membank tbl_add[])
+{
+struct acpi_table_header *table = NULL;
+struct acpi_table_gtdt *gtdt = NULL;
+u32 table_size = sizeof(struct acpi_table_gtdt);
+u32 offset = acpi_get_table_offset(tbl_add, TBL_GTDT);
+acpi_status status;
+u8 *base_ptr, checksum;
+
+status = acpi_get_table(ACPI_SIG_GTDT, 0, );
+
+if ( ACPI_FAILURE(status) )
+{
+const char *msg = acpi_format_exception(status);
+
+printk("Failed to get GTDT table, %s\n", msg);
+return -EINVAL;
+}
+
+base_ptr = d->arch.efi_acpi_table + offset;
+ACPI_MEMCPY(base_ptr, table, sizeof(struct acpi_table_gtdt));
+
+gtdt = (struct acpi_table_gtdt *)base_ptr;
+gtdt->header.length = table_size;
+gtdt->platform_timer_count = 0;
+gtdt->platform_timer_offset = table_size;
+checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, gtdt), table_size);
+gtdt->header.checksum -= checksum;
+
+tbl_add[TBL_GTDT].start = d->arch.efi_acpi_gpa + offset;
+tbl_add[TBL_GTDT].size = table_size;
+
+return 0;
+}
+
 static int acpi_create_madt(struct domain *d, struct membank tbl_add[])
 {
 struct acpi_table_header *table = NULL;
@@ -1909,6 +1946,10 @@ static int prepare_acpi(struct domain *d, struct 
kernel_info *kinfo)
 if ( rc != 0 )
 return rc;
 
+rc = acpi_create_gtdt(d, tbl_add);
+if ( rc != 0 )
+return rc;
+
 rc = acpi_create_xsdt(d, tbl_add);
 if ( rc != 0 )
 return rc;
diff --git a/xen/include/asm-arm/acpi.h b/xen/include/asm-arm/acpi.h
index 9f954d3..214511c 100644
--- a/xen/include/asm-arm/acpi.h
+++ b/xen/include/asm-arm/acpi.h
@@ -36,6 +36,7 @@ typedef enum {
 TBL_FADT,
 TBL_MADT,
 TBL_STAO,
+TBL_GTDT,
 TBL_XSDT,
 TBL_RSDP,
 TBL_EFIT,
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v2 5/6] xen/arm: traps: Avoid unnecessary VA -> IPA translation in abort handlers

2016-08-17 Thread Shanker Donthineni



On 08/17/2016 06:11 AM, Julien Grall wrote:

On 17/08/16 03:19, Shanker Donthineni wrote:

Hi Julien,


Hello Shanker,


On 07/27/2016 12:09 PM, Julien Grall wrote:

Translating a VA to a IPA is expensive. Currently, Xen is assuming that
HPFAR_EL2 is only valid when the stage-2 data/instruction abort 
happened

during a translation table walk of a first stage translation (i.e S1PTW
is set).

However, based on the ARM ARM (D7.2.34 in DDI 0487A.j), the register is
also valid when the data/instruction abort occured for a translation
fault.

With this change, the VA -> IPA translation will only happen for
permission faults that are not related to a translation table of a
first stage translation.

Signed-off-by: Julien Grall <julien.gr...@arm.com>

---
 Changes in v2:
 - Use fsc in the switch in do_trap_data_abort_guest
---
  xen/arch/arm/traps.c | 24 
  1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index ea105f2..83a30fa 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2382,13 +2382,28 @@ static inline paddr_t get_faulting_ipa(vaddr_t
gva)
  return ipa;
  }

+static inline bool hpfar_is_valid(bool s1ptw, uint8_t fsc)
+{
+/*
+ * HPFAR is valid if one of the following cases are true:
+ *  1. the stage 2 fault happen during a stage 1 page table walk
+ *  (the bit ESR_EL2.S1PTW is set)
+ *  2. the fault was due to a translation fault
+ *
+ * Note that technically HPFAR is valid for other cases, but they
+ * are currently not supported by Xen.
+ */
+return s1ptw || (fsc == FSC_FLT_TRANS);


Yes, XEN is not supporting the stage 2 access flag but we should handle
a stage 2 address size fault.


The function hpfar_is_valid indicates whether the register HPFAR is 
valid. If the function returns false, Xen will use the hardware do the 
translation.


It will only lead to a waste of cycle but this is fine as the address 
size fault is not a hot path for now.



I think we should do some thing like to below to match ARM ARM.

return s1ptw || (fsc != FSC_FLT_PERM);


This does not match the ARM ARM, with this check you consider that 
HPFAR will be valid for all the fault but permission ones which is not 
true.


I purposefully choose a white list because it is safer to use the 
hardware to do the translation more often than the invert.


So I don't see why we should handle stage 2 access flag with the 
current Xen. If you still disagree, please explain why with a concrete 
example.




Agree with you, I have suggested the above change because I saw the same 
check in Linux KVM.
As per ARM ARM, it should be 'return s1ptw || (fsc == FSC_FLT_TRANS) || 
(fsc == FSC_FLT_ACCESS) || (fsc == 0x00)';



Regards,



--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC 00/22] xen/arm: Rework the P2M code to follow break-before-make sequence

2016-08-16 Thread Shanker Donthineni

Hi Julien,

I have verified this patch series on Qualcomm Server platform QDF2XXX 
without any issue.


Tested-by: Shanker Donthineni <shank...@codeaurora.org>

On 08/15/2016 10:06 AM, Edgar E. Iglesias wrote:

On Thu, Jul 28, 2016 at 03:51:23PM +0100, Julien Grall wrote:

Hello all,

The ARM architecture mandates the use of a break-before-make sequence when
changing translation entries if the page table is shared between multiple
CPUs whenever a valid entry is replaced by another valid entry (see D4.7.1
in ARM DDI 0487A.j for more details).

The current P2M code does not respect this sequence and may result to
break coherency on some processors.

Adapting the current implementation to use break-before-make sequence would
imply some code duplication and more TLBs invalidations than necessary.
For instance, if we are replacing a 4KB page and the current mapping in
the P2M is using a 1GB superpage, the following steps will happen:
 1) Shatter the 1GB superpage into a series of 2MB superpages
 2) Shatter the 2MB superpage into a series of 4KB superpages
 3) Replace the 4KB page

As the current implementation is shattering while descending and install
the mapping before continuing to the next level, Xen would need to issue 3
TLB invalidation instructions which is clearly inefficient.

Furthermore, all the operations which modify the page table are using the
same skeleton. It is more complicated to maintain different code paths than
having a generic function that set an entry and take care of the break-before-
make sequence.

The new implementation is based on the x86 EPT one which, I think, fits
quite well for the break-before-make sequence whilst keeping the code
simple.

I sent this patch series as an RFC because there are still some TODOs
in the code (mostly sanity check and possible optimization) and I have
done limited testing. However, I think it is a good shape to start reviewing,
get more feedback and have wider testing on different board.

Also, I need to figure out the impact on ARM32 because the domheap is not
always mapped.

This series has dependencies on some rework sent separately ([1] and [2]).
I have provided a branch with all the dependencies and this series applied:

git://xenbits.xen.org/people/julieng/xen-unstable.git branch p2m-rfc


Hi Julien,

FWIW, I gave this a spin on the ZynqMP and it seems to be working fine.
I tried dom0 and starting a few additional guests. All looks good.

Tested-by: Edgar E. Iglesias <edgar.igles...@xilinx.com>

Cheers,
Edgar



Comments are welcome.

Yours sincerely,

Cc: Razvan Cojocaru <rcojoc...@bitdefender.com>
Cc: Tamas K Lengyel <ta...@tklengyel.com>
Cc: Shanker Donthineni <shank...@codeaurora.org>
Cc: Dirk Behme <dirk.be...@de.bosch.com>
Cc: Edgar E. Iglesias <edgar.igles...@xilinx.com>

[1] https://lists.xenproject.org/archives/html/xen-devel/2016-07/msg02936.html
[2] https://lists.xenproject.org/archives/html/xen-devel/2016-07/msg02830.html

Julien Grall (22):
   xen/arm: do_trap_instr_abort_guest: Move the IPA computation out of
 the switch
   xen/arm: p2m: Store in p2m_domain whether we need to clean the entry
   xen/arm: p2m: Rename parameter in p2m_{remove,write}_pte...
   xen/arm: p2m: Use typesafe gfn in p2m_mem_access_radix_set
   xen/arm: traps: Move MMIO emulation code in a separate helper
   xen/arm: traps: Check the P2M before injecting a data/instruction
 abort
   xen/arm: p2m: Rework p2m_put_l3_page
   xen/arm: p2m: Invalidate the TLBs when write unlocking the p2m
   xen/arm: p2m: Change the type of level_shifts from paddr_t to unsigned
 int
   xen/arm: p2m: Move the lookup helpers at the top of the file
   xen/arm: p2m: Introduce p2m_get_root_pointer and use it in
 __p2m_lookup
   xen/arm: p2m: Introduce p2m_get_entry and use it to implement
 __p2m_lookup
   xen/arm: p2m: Replace all usage of __p2m_lookup with p2m_get_entry
   xen/arm: p2m: Re-implement p2m_cache_flush using p2m_get_entry
   xen/arm: p2m: Re-implement relinquish_p2m_mapping using p2m_get_entry
   xen/arm: p2m: Make p2m_{valid,table,mapping} helpers inline
   xen/arm: p2m: Introduce a helper to check if an entry is a superpage
   xen/arm: p2m: Introduce p2m_set_entry and __p2m_set_entry
   xen/arm: p2m: Re-implement p2m_remove_using using p2m_set_entry
   xen/arm: p2m: Re-implement p2m_insert_mapping using p2m_set_entry
   xen/arm: p2m: Re-implement p2m_set_mem_access using
 p2m_{set,get}_entry
   xen/arm: p2m: Do not handle shattering in p2m_create_table

  xen/arch/arm/domain.c  |8 +-
  xen/arch/arm/p2m.c | 1274 ++--
  xen/arch/arm/traps.c   |  126 +++--
  xen/include/asm-arm/p2m.h  |   14 +
  xen/include/asm-arm/page.h |4 +
  5 files changed, 742 insertions(+), 684 deletions(-)

--
1.9.1



--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies,

Re: [Xen-devel] [PATCH v2 5/6] xen/arm: traps: Avoid unnecessary VA -> IPA translation in abort handlers

2016-08-16 Thread Shanker Donthineni

Hi Julien,

On 07/27/2016 12:09 PM, Julien Grall wrote:

Translating a VA to a IPA is expensive. Currently, Xen is assuming that
HPFAR_EL2 is only valid when the stage-2 data/instruction abort happened
during a translation table walk of a first stage translation (i.e S1PTW
is set).

However, based on the ARM ARM (D7.2.34 in DDI 0487A.j), the register is
also valid when the data/instruction abort occured for a translation
fault.

With this change, the VA -> IPA translation will only happen for
permission faults that are not related to a translation table of a
first stage translation.

Signed-off-by: Julien Grall <julien.gr...@arm.com>

---
 Changes in v2:
 - Use fsc in the switch in do_trap_data_abort_guest
---
  xen/arch/arm/traps.c | 24 
  1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index ea105f2..83a30fa 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2382,13 +2382,28 @@ static inline paddr_t get_faulting_ipa(vaddr_t gva)
  return ipa;
  }

+static inline bool hpfar_is_valid(bool s1ptw, uint8_t fsc)
+{
+/*
+ * HPFAR is valid if one of the following cases are true:
+ *  1. the stage 2 fault happen during a stage 1 page table walk
+ *  (the bit ESR_EL2.S1PTW is set)
+ *  2. the fault was due to a translation fault
+ *
+ * Note that technically HPFAR is valid for other cases, but they
+ * are currently not supported by Xen.
+ */
+return s1ptw || (fsc == FSC_FLT_TRANS);


Yes, XEN is not supporting the stage 2 access flag but we should handle 
a stage 2 address size fault.

I think we should do some thing like to below to match ARM ARM.

return s1ptw || (fsc != FSC_FLT_PERM);



+}
+
  static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
const union hsr hsr)
  {
  int rc;
  register_t gva = READ_SYSREG(FAR_EL2);
+uint8_t fsc = hsr.iabt.ifsc & ~FSC_LL_MASK;

-switch ( hsr.iabt.ifsc & ~FSC_LL_MASK )
+switch ( fsc )
  {
  case FSC_FLT_PERM:
  {
@@ -2399,7 +2414,7 @@ static void do_trap_instr_abort_guest(struct
cpu_user_regs *regs,
  .kind = hsr.iabt.s1ptw ? npfec_kind_in_gpt :
npfec_kind_with_gla
  };

-if ( hsr.iabt.s1ptw )
+if ( hpfar_is_valid(hsr.iabt.s1ptw, fsc) )
  gpa = get_faulting_ipa(gva);
  else
  {
@@ -2434,6 +2449,7 @@ static void do_trap_data_abort_guest(struct
cpu_user_regs *regs,
  const struct hsr_dabt dabt = hsr.dabt;
  int rc;
  mmio_info_t info;
+uint8_t fsc = hsr.dabt.dfsc & ~FSC_LL_MASK;

  info.dabt = dabt;
  #ifdef CONFIG_ARM_32
@@ -2442,7 +2458,7 @@ static void do_trap_data_abort_guest(struct
cpu_user_regs *regs,
  info.gva = READ_SYSREG64(FAR_EL2);
  #endif

-if ( dabt.s1ptw )
+if ( hpfar_is_valid(hsr.iabt.s1ptw, fsc) )
  info.gpa = get_faulting_ipa(info.gva);
  else
  {
@@ -2451,7 +2467,7 @@ static void do_trap_data_abort_guest(struct
cpu_user_regs *regs,
  return; /* Try again */
  }

-switch ( dabt.dfsc & ~FSC_LL_MASK )
+switch ( fsc )
  {
  case FSC_FLT_PERM:
  {


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 2/4] xen: Add generic implementation of binary search

2016-07-20 Thread Shanker Donthineni
This patch adds the generic implementation of binary search algorithm
which is copied from Linux kernel v4.7-rc7. No functional changes.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Reviewed-by: Andrew Cooper <andrew.coop...@citrix.com>
Reviewed-by: Julien Grall <julien.gr...@arm.com>
---
Changes since v2:
 Fixed the compilation issue due to a missing ';'.
 Fixed typo.

Changes since v1:
 Removed the header file xen/include/xen/bsearch.h.
 Defined function bsearch() prototype in the header file xen/lib.h.

 xen/common/Makefile   |  1 +
 xen/common/bsearch.c  | 51 +++
 xen/include/xen/lib.h |  3 +++
 3 files changed, 55 insertions(+)
 create mode 100644 xen/common/bsearch.c

diff --git a/xen/common/Makefile b/xen/common/Makefile
index dbf00c6..f8123c2 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -43,6 +43,7 @@ obj-y += schedule.o
 obj-y += shutdown.o
 obj-y += softirq.o
 obj-y += sort.o
+obj-y += bsearch.o
 obj-y += smp.o
 obj-y += spinlock.o
 obj-y += stop_machine.o
diff --git a/xen/common/bsearch.c b/xen/common/bsearch.c
new file mode 100644
index 000..7090930
--- /dev/null
+++ b/xen/common/bsearch.c
@@ -0,0 +1,51 @@
+/*
+ * A generic implementation of binary search for the Linux kernel
+ *
+ * Copyright (C) 2008-2009 Ksplice, Inc.
+ * Author: Tim Abbott <tabb...@ksplice.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ */
+
+#include 
+
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt))
+{
+   size_t start = 0, end = num;
+   int result;
+
+   while (start < end) {
+   size_t mid = start + (end - start) / 2;
+
+   result = cmp(key, base + mid * size);
+   if (result < 0)
+   end = mid;
+   else if (result > 0)
+   start = mid + 1;
+   else
+   return (void *)base + mid * size;
+   }
+
+   return NULL;
+}
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index b1b0fb2..b90d582 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -153,4 +153,7 @@ void dump_execstate(struct cpu_user_regs *);
 
 void init_constructors(void);
 
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+  int (*cmp)(const void *key, const void *elt));
+
 #endif /* __LIB_H__ */
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 4/4] arm/vgic: Change fixed number of mmio handlers to variable number

2016-07-20 Thread Shanker Donthineni
Compute the number of mmio handlers that are required for vGICv3 and
vGICv2 emulation drivers in vgic_v3_init()/vgic_v2_init(). Augment
this variable number of mmio handers to a fixed number MAX_IO_HANDLER
and pass it to domain_io_init() to allocate enough memory.

New code path:
 domain_vgic_register()
   domain_io_init(count + MAX_IO_HANDLER)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c  | 12 +++-
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++---
 xen/include/asm-arm/vgic.h |  5 +++--
 5 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 0170cee..4e5259b 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc, count;
+int rc, count = 0;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,10 +569,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -609,6 +605,12 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d, )) != 0 )
+goto fail;
+
+if ( (rc = domain_io_init(d, count + MAX_IO_HANDLER)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 6a5e67b..c6d280e 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -711,7 +711,7 @@ static const struct vgic_ops vgic_v2_ops = {
 .max_vcpus = 8,
 };
 
-int vgic_v2_init(struct domain *d)
+int vgic_v2_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v2_hw.enabled )
 {
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+*mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index be9a9a3..ec038a3 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1499,7 +1499,7 @@ static const struct vgic_ops v3_ops = {
 .max_vcpus = 4096,
 };
 
-int vgic_v3_init(struct domain *d)
+int vgic_v3_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v3_hw.enabled )
 {
@@ -1509,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Redistributors */
+*mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index a7ccfe7..768cb91 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,18 +88,18 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d, int *mmio_count)
 {
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
 case GIC_V3:
-if ( vgic_v3_init(d) )
+if ( vgic_v3_init(d, mmio_count) )
return -ENODEV;
 break;
 #endif
 case GIC_V2:
-if ( vgic_v2_init(d) )
+if ( vgic_v2_init(d, mmio_count) )
 return -ENODEV;
 break;
 default:
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0 )
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c3cc4f6..300f461 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -304,9 +304,10 @@ extern int vgic_emulate(struct cpu_user_regs *regs, union 
hsr hsr);
 extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
-int vgic_v2_init(struct domain *d);
-int vgic_v3_init(struct domain *d);
+int vgic_v2_init(struct domain *d, int *mmio_count);
+int vgic_v3_init(struct domain *d, int *mmio_count);
 
+extern int domain_vgic_register(struct domain *d, int *mmio_count);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qual

[Xen-devel] [PATCH V3 0/4] Change fixed mmio handlers to a variable number

2016-07-20 Thread Shanker Donthineni
The maximum number of mmio handlers that are allowed is limited to
a macro MAX_IO_HANDLER(16), which is not enough for supporting per CPU
Redistributor regions. We need at least MAX_IO_HANDLER+CONFIG_NR_CPUS
mmio handlers in order to support ACPI based XEN boot.

This patchset uses the dynamic allocation strategy to allocate memory
resource dynamically depends on the number of Redistributor regions
that are described in the APCI MADT table.

Shanker Donthineni (4):
  arm/io: Use separate memory allocation for mmio handlers
  xen: Add generic implementation of binary search
  xen/arm: io: Use binary search for mmio handler lookup
  arm/vgic: Change fixed number of mmio handlers to variable number

 xen/arch/arm/domain.c  | 12 +++
 xen/arch/arm/io.c  | 52 +++---
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++--
 xen/common/Makefile|  1 +
 xen/common/bsearch.c   | 51 +
 xen/include/asm-arm/mmio.h |  7 +--
 xen/include/asm-arm/vgic.h |  5 +++--
 xen/include/xen/lib.h  |  3 +++
 10 files changed, 115 insertions(+), 34 deletions(-)
 create mode 100644 xen/common/bsearch.c

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 3/4] xen/arm: io: Use binary search for mmio handler lookup

2016-07-20 Thread Shanker Donthineni
As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/io.c | 39 ---
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 40330f0..e8aa7fa 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -70,27 +71,31 @@ static int handle_write(const struct mmio_handler *handler, 
struct vcpu *v,
handler->priv);
 }
 
-static const struct mmio_handler *find_mmio_handler(struct domain *d,
-paddr_t gpa)
+/* This function assumes that mmio regions are not overlapped */
+static int cmp_mmio_handler(const void *key, const void *elem)
 {
-const struct mmio_handler *handler;
-unsigned int i;
-struct vmmio *vmmio = >arch.vmmio;
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
 
-read_lock(>lock);
+if ( handler0->addr < handler1->addr )
+return -1;
 
-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( handler0->addr > (handler1->addr + handler1->size) )
+return 1;
 
-if ( (gpa >= handler->addr) &&
- (gpa < (handler->addr + handler->size)) )
-break;
-}
+return 0;
+}
 
-if ( i == vmmio->num_entries )
-handler = NULL;
+static const struct mmio_handler *find_mmio_handler(struct domain *d,
+paddr_t gpa)
+{
+struct vmmio *vmmio = >arch.vmmio;
+struct mmio_handler key = {.addr = gpa};
+const struct mmio_handler *handler;
 
+read_lock(>lock);
+handler = bsearch(, vmmio->handlers, vmmio->num_entries,
+  sizeof(*handler), cmp_mmio_handler);
 read_unlock(>lock);
 
 return handler;
@@ -131,6 +136,10 @@ void register_mmio_handler(struct domain *d,
 
 vmmio->num_entries++;
 
+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
+ cmp_mmio_handler, NULL);
+
 write_unlock(>lock);
 }
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 1/4] arm/io: Use separate memory allocation for mmio handlers

2016-07-20 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 13 +++--
 xen/include/asm-arm/mmio.h |  7 +--
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 61fc08e..0170cee 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,7 +569,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -663,6 +664,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 5a96836..40330f0 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -118,7 +118,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 write_lock(>lock);
 
@@ -134,14 +134,23 @@ void register_mmio_handler(struct domain *d,
 write_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
 rwlock_init(>arch.vmmio.lock);
 d->arch.vmmio.num_entries = 0;
+d->arch.vmmio.max_num_entries = max_count;
+d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+if ( !d->arch.vmmio.handlers )
+return -ENOMEM;
 
 return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index 32f10f2..c620eed 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -52,15 +52,18 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 rwlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
+
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 1/4] arm/io: Use separate memory allocation for mmio handlers

2016-07-17 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 13 +++--
 xen/include/asm-arm/mmio.h |  7 +--
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 61fc08e..0170cee 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,7 +569,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -663,6 +664,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 5a96836..40330f0 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -118,7 +118,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 write_lock(>lock);
 
@@ -134,14 +134,23 @@ void register_mmio_handler(struct domain *d,
 write_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
 rwlock_init(>arch.vmmio.lock);
 d->arch.vmmio.num_entries = 0;
+d->arch.vmmio.max_num_entries = max_count;
+d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+if ( !d->arch.vmmio.handlers )
+return -ENOMEM;
 
 return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index 32f10f2..c620eed 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -52,15 +52,18 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 rwlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
+
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 2/4] xen: Add generic implementation of binary search

2016-07-17 Thread Shanker Donthineni
This patch adds the generic implementation of binary search algorithm
whcih is copied from Linux kernel v4.7-rc7. No functional changes.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Reviewed-by: Andrew Cooper <andrew.coop...@citrix.com>
---
Changes since v1:
 Removed the header file xen/include/xen/bsearch.h.
 Defined function bsearch() prototype in the header file xen/lib.h.

 xen/common/Makefile   |  1 +
 xen/common/bsearch.c  | 51 +++
 xen/include/xen/lib.h |  3 +++
 3 files changed, 55 insertions(+)
 create mode 100644 xen/common/bsearch.c

diff --git a/xen/common/Makefile b/xen/common/Makefile
index dbf00c6..f8123c2 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -43,6 +43,7 @@ obj-y += schedule.o
 obj-y += shutdown.o
 obj-y += softirq.o
 obj-y += sort.o
+obj-y += bsearch.o
 obj-y += smp.o
 obj-y += spinlock.o
 obj-y += stop_machine.o
diff --git a/xen/common/bsearch.c b/xen/common/bsearch.c
new file mode 100644
index 000..7090930
--- /dev/null
+++ b/xen/common/bsearch.c
@@ -0,0 +1,51 @@
+/*
+ * A generic implementation of binary search for the Linux kernel
+ *
+ * Copyright (C) 2008-2009 Ksplice, Inc.
+ * Author: Tim Abbott <tabb...@ksplice.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ */
+
+#include 
+
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt))
+{
+   size_t start = 0, end = num;
+   int result;
+
+   while (start < end) {
+   size_t mid = start + (end - start) / 2;
+
+   result = cmp(key, base + mid * size);
+   if (result < 0)
+   end = mid;
+   else if (result > 0)
+   start = mid + 1;
+   else
+   return (void *)base + mid * size;
+   }
+
+   return NULL;
+}
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index b1b0fb2..b90d582 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -153,4 +153,7 @@ void dump_execstate(struct cpu_user_regs *);
 
 void init_constructors(void);
 
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+  int (*cmp)(const void *key, const void *elt))
+
 #endif /* __LIB_H__ */
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 0/4] Change fixed mmio handlers to a variable number

2016-07-17 Thread Shanker Donthineni
The maximum number of mmio handlers that are allowed is limited to
a macro MAX_IO_HANDLER(16), which is not enough for supporting per CPU
Redistributor regions. We need at least MAX_IO_HANDLER+CONFIG_NR_CPUS
mmio handlers in order to support ACPI based XEN boot.

This patchset uses the dynamic allocation strategy to allocate memory
resource dynamically depends on the number of Redistributor regions
that are described in the APCI MADT table.

Shanker Donthineni (4):
  arm/io: Use separate memory allocation for mmio handlers
  xen: Add generic implementation of binary search
  xen/arm: io: Use binary search for mmio handler lookup
  arm/vgic: Change fixed number of mmio handlers to variable number

 xen/arch/arm/domain.c  | 12 +++
 xen/arch/arm/io.c  | 52 +++---
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++--
 xen/common/Makefile|  1 +
 xen/common/bsearch.c   | 51 +
 xen/include/asm-arm/mmio.h |  7 +--
 xen/include/asm-arm/vgic.h |  5 +++--
 xen/include/xen/lib.h  |  3 +++
 10 files changed, 115 insertions(+), 34 deletions(-)
 create mode 100644 xen/common/bsearch.c

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 4/4] arm/vgic: Change fixed number of mmio handlers to variable number

2016-07-17 Thread Shanker Donthineni
Compute the number of mmio handlers that are required for vGICv3 and
vGICv2 emulation drivers in vgic_v3_init()/vgic_v2_init(). Augment
this variable number of mmio handers to a fixed number MAX_IO_HANDLER
and pass it to domain_io_init() to allocate enough memory.

New code path:
 domain_vgic_register()
   domain_io_init(count + MAX_IO_HANDLER)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c  | 12 +++-
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++---
 xen/include/asm-arm/vgic.h |  5 +++--
 5 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 0170cee..4e5259b 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc, count;
+int rc, count = 0;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,10 +569,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -609,6 +605,12 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d, )) != 0 )
+goto fail;
+
+if ( (rc = domain_io_init(d, count + MAX_IO_HANDLER)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 6a5e67b..c6d280e 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -711,7 +711,7 @@ static const struct vgic_ops vgic_v2_ops = {
 .max_vcpus = 8,
 };
 
-int vgic_v2_init(struct domain *d)
+int vgic_v2_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v2_hw.enabled )
 {
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+*mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index be9a9a3..ec038a3 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1499,7 +1499,7 @@ static const struct vgic_ops v3_ops = {
 .max_vcpus = 4096,
 };
 
-int vgic_v3_init(struct domain *d)
+int vgic_v3_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v3_hw.enabled )
 {
@@ -1509,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Redistributors */
+*mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index a7ccfe7..768cb91 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,18 +88,18 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d, int *mmio_count)
 {
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
 case GIC_V3:
-if ( vgic_v3_init(d) )
+if ( vgic_v3_init(d, mmio_count) )
return -ENODEV;
 break;
 #endif
 case GIC_V2:
-if ( vgic_v2_init(d) )
+if ( vgic_v2_init(d, mmio_count) )
 return -ENODEV;
 break;
 default:
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0 )
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c3cc4f6..300f461 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -304,9 +304,10 @@ extern int vgic_emulate(struct cpu_user_regs *regs, union 
hsr hsr);
 extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
-int vgic_v2_init(struct domain *d);
-int vgic_v3_init(struct domain *d);
+int vgic_v2_init(struct domain *d, int *mmio_count);
+int vgic_v3_init(struct domain *d, int *mmio_count);
 
+extern int domain_vgic_register(struct domain *d, int *mmio_count);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qual

Re: [Xen-devel] [PATCH RESEND 2/4] xen: Add generic implementation of binary search

2016-07-15 Thread Shanker Donthineni

Hi Andrew,

On 07/15/2016 12:42 PM, Andrew Cooper wrote:

On 15/07/16 18:35, Shanker Donthineni wrote:

This patch adds the generic implementation of binary search algorithm
whcih is copied from Linux kernel v4.7-rc7. No functional changes.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
  Resend to fix the In-Reply-To/References header feilds.

  xen/common/Makefile   |  1 +
  xen/common/bsearch.c  | 51

+++

  xen/include/xen/bsearch.h |  9 +

Having a header file for a single is silly (I have no idea why Linux
does it like that).

I would move it into xen/lib.h which contains a number of other
stdlib.h-like functions.

With that done, Reviewed-by: Andrew Cooper <andrew.coop...@citrix.com>


I'll follow your suggestion.

--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH RESEND 3/4] xen/arm: io: Use binary search for mmio handler lookup

2016-07-15 Thread Shanker Donthineni
As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 Resend to fix the In-Reply-To/References header feilds.

 xen/arch/arm/io.c | 40 +---
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 40330f0..cdc3aa3 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -70,27 +72,31 @@ static int handle_write(const struct mmio_handler *handler, 
struct vcpu *v,
handler->priv);
 }
 
-static const struct mmio_handler *find_mmio_handler(struct domain *d,
-paddr_t gpa)
+/* This function assumes that mmio regions are not overlapped */
+static int cmp_mmio_handler(const void *key, const void *elem)
 {
-const struct mmio_handler *handler;
-unsigned int i;
-struct vmmio *vmmio = >arch.vmmio;
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
 
-read_lock(>lock);
+if ( handler0->addr < handler1->addr )
+return -1;
 
-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( handler0->addr > (handler1->addr + handler1->size) )
+return 1;
 
-if ( (gpa >= handler->addr) &&
- (gpa < (handler->addr + handler->size)) )
-break;
-}
+return 0;
+}
 
-if ( i == vmmio->num_entries )
-handler = NULL;
+static const struct mmio_handler *find_mmio_handler(struct domain *d,
+paddr_t gpa)
+{
+struct vmmio *vmmio = >arch.vmmio;
+struct mmio_handler key = {.addr = gpa};
+const struct mmio_handler *handler;
 
+read_lock(>lock);
+handler = bsearch(, vmmio->handlers, vmmio->num_entries,
+  sizeof(*handler), cmp_mmio_handler);
 read_unlock(>lock);
 
 return handler;
@@ -131,6 +137,10 @@ void register_mmio_handler(struct domain *d,
 
 vmmio->num_entries++;
 
+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
+ cmp_mmio_handler, NULL);
+
 write_unlock(>lock);
 }
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH RESEND 1/4] arm/io: Use separate memory allocation for mmio handlers

2016-07-15 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
 Resend to fix the In-Reply-To/References header feilds.

 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 13 +++--
 xen/include/asm-arm/mmio.h |  7 +--
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 61fc08e..0170cee 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,7 +569,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -663,6 +664,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 5a96836..40330f0 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -118,7 +118,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 write_lock(>lock);
 
@@ -134,14 +134,23 @@ void register_mmio_handler(struct domain *d,
 write_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
 rwlock_init(>arch.vmmio.lock);
 d->arch.vmmio.num_entries = 0;
+d->arch.vmmio.max_num_entries = max_count;
+d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+if ( !d->arch.vmmio.handlers )
+return -ENOMEM;
 
 return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index 32f10f2..c620eed 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -52,15 +52,18 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 rwlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
+
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH RESEND 4/4] arm/vgic: Change fixed number of mmio handlers to variable number

2016-07-15 Thread Shanker Donthineni
Compute the number of mmio handlers that are required for vGICv3 and
vGICv2 emulation drivers in vgic_v3_init()/vgic_v2_init(). Augment
this variable number of mmio handers to a fixed number MAX_IO_HANDLER
and pass it to domain_io_init() to allocate enough memory.

New code path:
 domain_vgic_register()
   domain_io_init(count + MAX_IO_HANDLER)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 Resend to fix the In-Reply-To/References header fields.

 xen/arch/arm/domain.c  | 12 +++-
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++---
 xen/include/asm-arm/vgic.h |  5 +++--
 5 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 0170cee..4e5259b 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc, count;
+int rc, count = 0;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,10 +569,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -609,6 +605,12 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d, )) != 0 )
+goto fail;
+
+if ( (rc = domain_io_init(d, count + MAX_IO_HANDLER)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 6a5e67b..c6d280e 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -711,7 +711,7 @@ static const struct vgic_ops vgic_v2_ops = {
 .max_vcpus = 8,
 };
 
-int vgic_v2_init(struct domain *d)
+int vgic_v2_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v2_hw.enabled )
 {
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+*mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index be9a9a3..ec038a3 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1499,7 +1499,7 @@ static const struct vgic_ops v3_ops = {
 .max_vcpus = 4096,
 };
 
-int vgic_v3_init(struct domain *d)
+int vgic_v3_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v3_hw.enabled )
 {
@@ -1509,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Redistributors */
+*mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index a7ccfe7..768cb91 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,18 +88,18 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d, int *mmio_count)
 {
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
 case GIC_V3:
-if ( vgic_v3_init(d) )
+if ( vgic_v3_init(d, mmio_count) )
return -ENODEV;
 break;
 #endif
 case GIC_V2:
-if ( vgic_v2_init(d) )
+if ( vgic_v2_init(d, mmio_count) )
 return -ENODEV;
 break;
 default:
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0 )
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c3cc4f6..300f461 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -304,9 +304,10 @@ extern int vgic_emulate(struct cpu_user_regs *regs, union 
hsr hsr);
 extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
-int vgic_v2_init(struct domain *d);
-int vgic_v3_init(struct domain *d);
+int vgic_v2_init(struct domain *d, int *mmio_count);
+int vgic_v3_init(struct domain *d, int *mmio_count);
 
+extern int domain_vgic_register(struct domain *d, int *mmio_count);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 

[Xen-devel] [PATCH RESEND 2/4] xen: Add generic implementation of binary search

2016-07-15 Thread Shanker Donthineni
This patch adds the generic implementation of binary search algorithm
whcih is copied from Linux kernel v4.7-rc7. No functional changes.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 Resend to fix the In-Reply-To/References header feilds.

 xen/common/Makefile   |  1 +
 xen/common/bsearch.c  | 51 +++
 xen/include/xen/bsearch.h |  9 +
 3 files changed, 61 insertions(+)
 create mode 100644 xen/common/bsearch.c
 create mode 100644 xen/include/xen/bsearch.h

diff --git a/xen/common/Makefile b/xen/common/Makefile
index dbf00c6..f8123c2 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -43,6 +43,7 @@ obj-y += schedule.o
 obj-y += shutdown.o
 obj-y += softirq.o
 obj-y += sort.o
+obj-y += bsearch.o
 obj-y += smp.o
 obj-y += spinlock.o
 obj-y += stop_machine.o
diff --git a/xen/common/bsearch.c b/xen/common/bsearch.c
new file mode 100644
index 000..3bcfd72
--- /dev/null
+++ b/xen/common/bsearch.c
@@ -0,0 +1,51 @@
+/*
+ * A generic implementation of binary search for the Linux kernel
+ *
+ * Copyright (C) 2008-2009 Ksplice, Inc.
+ * Author: Tim Abbott <tabb...@ksplice.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ */
+
+#include 
+
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt))
+{
+   size_t start = 0, end = num;
+   int result;
+
+   while (start < end) {
+   size_t mid = start + (end - start) / 2;
+
+   result = cmp(key, base + mid * size);
+   if (result < 0)
+   end = mid;
+   else if (result > 0)
+   start = mid + 1;
+   else
+   return (void *)base + mid * size;
+   }
+
+   return NULL;
+}
diff --git a/xen/include/xen/bsearch.h b/xen/include/xen/bsearch.h
new file mode 100644
index 000..07cf604
--- /dev/null
+++ b/xen/include/xen/bsearch.h
@@ -0,0 +1,9 @@
+#ifndef __XEN_BSEARCH_H__
+#define __XEN_BSEARCH_H__
+
+#include 
+
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt));
+
+#endif /* __XEN_BSEARCH_H__ */
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH RESEND 0/4] Change fixed mmio handlers to a variable number

2016-07-15 Thread Shanker Donthineni
The maximum number of mmio handlers that are allowed is limited to
a macro MAX_IO_HANDLER(16), which is not enough for supporting per CPU
Redistributor regions. We need at least MAX_IO_HANDLER+CONFIG_NR_CPUS
mmio handlers in order to support ACPI based XEN boot.

This patchset uses the dynamic allocation strategy to allocate memory
resource dynamically depends on the number of Redistributor regions
that are described in the APCI MADT table.

Shanker Donthineni (4):
  arm/io: Use separate memory allocation for mmio handlers
  xen: Add generic implementation of binary search
  xen/arm: io: Use binary search for mmio handler lookup
  arm/vgic: Change fixed number of mmio handlers to variable number

 xen/arch/arm/domain.c  | 12 +++
 xen/arch/arm/io.c  | 53 +++---
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++--
 xen/common/Makefile|  1 +
 xen/common/bsearch.c   | 51 
 xen/include/asm-arm/mmio.h |  7 --
 xen/include/asm-arm/vgic.h |  5 +++--
 xen/include/xen/bsearch.h  |  9 
 10 files changed, 122 insertions(+), 34 deletions(-)
 create mode 100644 xen/common/bsearch.c
 create mode 100644 xen/include/xen/bsearch.h

Changes:
  Resend to fix the Message-ID, References and In-Reply-To fields.

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 0/4] Change fixed mmio handlers to a variable number

2016-07-15 Thread Shanker Donthineni

Hi Julien,
On 07/15/2016 10:32 AM, Julien Grall wrote:

Hi Shanker,

It looks like this series is not threaded. I looked to the headers, 
and some patch miss the In-Reply-To/References header or they are wrong.


Please try to thread the series, it is much easier to find the 
associated patch.


Sorry for asking more things, I am still leaning the XEN upstream 
guidelines.  Please guide me how do I fix the issue 'thread the series' 
that you are talking.


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 4/4] arm/vgic: Change fixed number of mmio handlers to variable number

2016-07-15 Thread Shanker Donthineni
Compute the number of mmio handlers that are required for vGICv3 and
vGICv2 emulation drivers in vgic_v3_init()/vgic_v2_init(). Augment
this variable number of mmio handers to a fixed number MAX_IO_HANDLER
and pass it to domain_io_init() to allocate enough memory.

New code path:
 domain_vgic_register()
   domain_io_init(count + MAX_IO_HANDLER)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c  | 12 +++-
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++---
 xen/include/asm-arm/vgic.h |  5 +++--
 5 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 0170cee..4e5259b 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc, count;
+int rc, count = 0;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,10 +569,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -609,6 +605,12 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d, )) != 0 )
+goto fail;
+
+if ( (rc = domain_io_init(d, count + MAX_IO_HANDLER)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 6a5e67b..c6d280e 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -711,7 +711,7 @@ static const struct vgic_ops vgic_v2_ops = {
 .max_vcpus = 8,
 };
 
-int vgic_v2_init(struct domain *d)
+int vgic_v2_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v2_hw.enabled )
 {
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+*mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index be9a9a3..ec038a3 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1499,7 +1499,7 @@ static const struct vgic_ops v3_ops = {
 .max_vcpus = 4096,
 };
 
-int vgic_v3_init(struct domain *d)
+int vgic_v3_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v3_hw.enabled )
 {
@@ -1509,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Redistributors */
+*mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index a7ccfe7..768cb91 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,18 +88,18 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d, int *mmio_count)
 {
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
 case GIC_V3:
-if ( vgic_v3_init(d) )
+if ( vgic_v3_init(d, mmio_count) )
return -ENODEV;
 break;
 #endif
 case GIC_V2:
-if ( vgic_v2_init(d) )
+if ( vgic_v2_init(d, mmio_count) )
 return -ENODEV;
 break;
 default:
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0 )
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c3cc4f6..300f461 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -304,9 +304,10 @@ extern int vgic_emulate(struct cpu_user_regs *regs, union 
hsr hsr);
 extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
-int vgic_v2_init(struct domain *d);
-int vgic_v3_init(struct domain *d);
+int vgic_v2_init(struct domain *d, int *mmio_count);
+int vgic_v3_init(struct domain *d, int *mmio_count);
 
+extern int domain_vgic_register(struct domain *d, int *mmio_count);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qual

[Xen-devel] [PATCH 3/4] xen/arm: io: Use binary search for mmio handler lookup

2016-07-15 Thread Shanker Donthineni
As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/io.c | 40 +---
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 40330f0..cdc3aa3 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -70,27 +72,31 @@ static int handle_write(const struct mmio_handler *handler, 
struct vcpu *v,
handler->priv);
 }
 
-static const struct mmio_handler *find_mmio_handler(struct domain *d,
-paddr_t gpa)
+/* This function assumes that mmio regions are not overlapped */
+static int cmp_mmio_handler(const void *key, const void *elem)
 {
-const struct mmio_handler *handler;
-unsigned int i;
-struct vmmio *vmmio = >arch.vmmio;
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
 
-read_lock(>lock);
+if ( handler0->addr < handler1->addr )
+return -1;
 
-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( handler0->addr > (handler1->addr + handler1->size) )
+return 1;
 
-if ( (gpa >= handler->addr) &&
- (gpa < (handler->addr + handler->size)) )
-break;
-}
+return 0;
+}
 
-if ( i == vmmio->num_entries )
-handler = NULL;
+static const struct mmio_handler *find_mmio_handler(struct domain *d,
+paddr_t gpa)
+{
+struct vmmio *vmmio = >arch.vmmio;
+struct mmio_handler key = {.addr = gpa};
+const struct mmio_handler *handler;
 
+read_lock(>lock);
+handler = bsearch(, vmmio->handlers, vmmio->num_entries,
+  sizeof(*handler), cmp_mmio_handler);
 read_unlock(>lock);
 
 return handler;
@@ -131,6 +137,10 @@ void register_mmio_handler(struct domain *d,
 
 vmmio->num_entries++;
 
+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
+ cmp_mmio_handler, NULL);
+
 write_unlock(>lock);
 }
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 0/4] Change fixed mmio handlers to a variable number

2016-07-15 Thread Shanker Donthineni
The maximum number of mmio handlers that are allowed is limited to
a macro MAX_IO_HANDLER(16), which is not enough for supporting per CPU
Redistributor regions. We need at least MAX_IO_HANDLER+CONFIG_NR_CPUS
mmio handlers in order to support ACPI based XEN boot.

This patchset uses the dynamic allocation strategy to allocate memory
resource dynamically depends on the number of Redistributor regions
that are described in the APCI MADT table.

Shanker Donthineni (4):
  arm/io: Use separate memory allocation for mmio handlers
  xen: Add generic implementation of binary search
  xen/arm: io: Use binary search for mmio handler lookup
  arm/vgic: Change fixed number of mmio handlers to variable number

 xen/arch/arm/domain.c  | 12 +++
 xen/arch/arm/io.c  | 53 +++---
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++--
 xen/common/Makefile|  1 +
 xen/common/bsearch.c   | 51 
 xen/include/asm-arm/mmio.h |  7 --
 xen/include/asm-arm/vgic.h |  5 +++--
 xen/include/xen/bsearch.h  |  9 
 10 files changed, 122 insertions(+), 34 deletions(-)
 create mode 100644 xen/common/bsearch.c
 create mode 100644 xen/include/xen/bsearch.h

-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 1/4] arm/io: Use separate memory allocation for mmio handlers

2016-07-15 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 13 +++--
 xen/include/asm-arm/mmio.h |  7 +--
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 61fc08e..0170cee 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -546,7 +546,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -569,7 +569,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -663,6 +664,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 5a96836..40330f0 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -118,7 +118,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 write_lock(>lock);
 
@@ -134,14 +134,23 @@ void register_mmio_handler(struct domain *d,
 write_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
 rwlock_init(>arch.vmmio.lock);
 d->arch.vmmio.num_entries = 0;
+d->arch.vmmio.max_num_entries = max_count;
+d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+if ( !d->arch.vmmio.handlers )
+return -ENOMEM;
 
 return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index 32f10f2..c620eed 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -52,15 +52,18 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 rwlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
+
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 2/4] xen: Add generic implementation of binary search

2016-07-15 Thread Shanker Donthineni
This patch adds the generic implementation of binary search algorithm
whcih is copied from Linux kernel v4.7-rc7. No functional changes.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/common/Makefile   |  1 +
 xen/common/bsearch.c  | 51 +++
 xen/include/xen/bsearch.h |  9 +
 3 files changed, 61 insertions(+)
 create mode 100644 xen/common/bsearch.c
 create mode 100644 xen/include/xen/bsearch.h

diff --git a/xen/common/Makefile b/xen/common/Makefile
index dbf00c6..f8123c2 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -43,6 +43,7 @@ obj-y += schedule.o
 obj-y += shutdown.o
 obj-y += softirq.o
 obj-y += sort.o
+obj-y += bsearch.o
 obj-y += smp.o
 obj-y += spinlock.o
 obj-y += stop_machine.o
diff --git a/xen/common/bsearch.c b/xen/common/bsearch.c
new file mode 100644
index 000..3bcfd72
--- /dev/null
+++ b/xen/common/bsearch.c
@@ -0,0 +1,51 @@
+/*
+ * A generic implementation of binary search for the Linux kernel
+ *
+ * Copyright (C) 2008-2009 Ksplice, Inc.
+ * Author: Tim Abbott <tabb...@ksplice.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ */
+
+#include 
+
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt))
+{
+   size_t start = 0, end = num;
+   int result;
+
+   while (start < end) {
+   size_t mid = start + (end - start) / 2;
+
+   result = cmp(key, base + mid * size);
+   if (result < 0)
+   end = mid;
+   else if (result > 0)
+   start = mid + 1;
+   else
+   return (void *)base + mid * size;
+   }
+
+   return NULL;
+}
diff --git a/xen/include/xen/bsearch.h b/xen/include/xen/bsearch.h
new file mode 100644
index 000..07cf604
--- /dev/null
+++ b/xen/include/xen/bsearch.h
@@ -0,0 +1,9 @@
+#ifndef __XEN_BSEARCH_H__
+#define __XEN_BSEARCH_H__
+
+#include 
+
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt));
+
+#endif /* __XEN_BSEARCH_H__ */
-- 
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm Technologies, 
Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V4 10/11] xen/arm: io: Use binary search for mmio handler lookup

2016-07-14 Thread Shanker Donthineni

Hi Julien,

On 07/14/2016 11:46 AM, Julien Grall wrote:

Hi Shanker,

On 14/07/16 17:18, Shanker Donthineni wrote:

As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v3:
   Moved the function bsearch() to common file xen/common/bsearch.c.

Changes since v2:
   Converted mmio lookup code to a critical section.
   Copied the function bsreach() from Linux kernel.

  xen/arch/arm/io.c | 42 +-
  1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 40330f0..0471ba8 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,8 @@
  #include 
  #include 
  #include 
+#include 
+#include 
  #include 
  #include 

@@ -70,27 +72,29 @@ static int handle_write(const struct mmio_handler 
*handler, struct vcpu *v,

 handler->priv);
  }

-static const struct mmio_handler *find_mmio_handler(struct domain *d,
-paddr_t gpa)
+static int cmp_mmio_handler(const void *key, const void *elem)


Would it be worth to mention in a comment that we don't support 
overlapping?




Sure, I'll do.


  {
-const struct mmio_handler *handler;
-unsigned int i;
-struct vmmio *vmmio = >arch.vmmio;
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;

-read_lock(>lock);
+if ( handler0->addr < handler1->addr )
+return -1;

-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( handler0->addr > (handler1->addr + handler1->size) )
+return 1;

-if ( (gpa >= handler->addr) &&
- (gpa < (handler->addr + handler->size)) )
-break;
-}
+return 0;
+}

-if ( i == vmmio->num_entries )
-handler = NULL;
+static const struct mmio_handler *find_mmio_handler(struct vcpu *v, 
paddr_t gpa)


Why have you changed the prototype of find_mmio_handler?



As such there is no reason for this change, I'll revert this change in 
next patchset.

+{
+struct vmmio *vmmio = >domain->arch.vmmio;
+struct mmio_handler key = {.addr = gpa};


I know it is not currently the case, but should not we take into 
account the size of the access?




I agree with you, we definitely need to consider size of the access for 
traps/emulation drivers similar to what Linux KVM code does currently. 
Do you know which emulation drivers are using non aligned accesses?




+const struct mmio_handler *handler;

+read_lock(>lock);
+handler = bsearch(, vmmio->handlers, vmmio->num_entries,
+  sizeof(*handler), cmp_mmio_handler);
  read_unlock(>lock);

  return handler;
@@ -99,9 +103,9 @@ static const struct mmio_handler 
*find_mmio_handler(struct domain *d,

  int handle_mmio(mmio_info_t *info)
  {
  struct vcpu *v = current;
-const struct mmio_handler *handler = NULL;
+const struct mmio_handler *handler;


Why this change?



No need to initialize this local variable because the following line 
always initializes it. I'll revert this change anyway to avoid confusion.




-handler = find_mmio_handler(v->domain, info->gpa);
+handler = find_mmio_handler(v, info->gpa);


ditto.


  if ( !handler )
  return 0;

@@ -131,6 +135,10 @@ void register_mmio_handler(struct domain *d,

  vmmio->num_entries++;

+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct 
mmio_handler),

+cmp_mmio_handler, NULL);


The indentation looks wrong here.



I don't quite understand what you mean. It has 8 spaces, do I need more 
than 8 spaces or something else?

+
  write_unlock(>lock);
  }






--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v2 0/9] xen/arm: Support SPIs routing

2016-07-14 Thread Shanker Donthineni

Hi Julien,

Tested-by: Shanker Donthineni<shank...@codeaurora.org>

I have tested this patchset on Qualcomm Technologies QDF2XXX server platform 
without any issue.


On 07/14/2016 11:21 AM, Julien Grall wrote:

Hello all,

Currently, Xen does not route SPIs to DOM0 when ACPI is inuse after
the functionality has been reverted in Xen 4.7 by commit 909bd14.

In the previous approach, the SPIs was routed when DOM0 was writing into
ISENABLER. However, this has resulted to deadlock (see more details in [1])
as soon as the IRQ was enabled by DOM0.

We have multiple solutions to route the IRQ:
 1) Rework route_irq_to_guest to avoid the deadlock
 2) Route and enable the IRQ outside of the emulation of ISENABLER
 3) Remove the dependency on the IRQ type in the routing function
 and route all the unused IRQs during domain building
 4) Add a new hypercall to let DOM0 routing the IRQ

I think that 1) and 2) are not resilient because route_irq_to_guest may fail
and there is no way to report this error to the guest (except by killing it).

Furthermore, in solution 2) enabling the interrupt would need to be defer
until the routing has been done. This would require a lot of code duplication.

Which leave solution 3) and 4). The solution 4) requires to introduce a new
(or re-use one) stable hypercall. I am not sure why we ruled out this
solution when we reviewed the ACPI design document.

This patch series is implementing the 3rd solution which defer the IRQ
type configuration for DOM0 IRQ when ACPI is inuse. However, this will
slightly increase the memory usage of Xen (54KB).

I am happy to consider any other solutions.

I only tested briefly this patch series, Shanker can you give a try on
your hardware?

A branch with all the patches can be found here:

git://xenbits.xen.org/people/julieng/xen-unstable.git branch irq-routing-acpi-v2

Yours sincerely,

[1] http://lists.xenproject.org/archives/html/xen-devel/2016-05/msg02633.html

Julien Grall (9):
   xen/arm: gic: Consolidate the IRQ affinity set in a single place
   xen/arm: gic: Do not configure affinity during routing
   xen/arm: gic: split set_irq_properties
   xen/arm: gic: set_type: Pass the type in parameter rather than in
 desc->arch.type
   xen/arm: gic: Document how gic_set_irq_type should be called
   Revert "xen/arm: warn the user that we cannot route SPIs to Dom0 on
 ACPI"
   xen/arm: Allow DOM0 to set the IRQ type
   xen/arm: acpi: route all unused IRQs to DOM0
   xen/arm: Fix coding style and update comment in acpi_route_spis

  xen/arch/arm/domain_build.c | 33 +++--
  xen/arch/arm/gic-v2.c   | 28 +---
  xen/arch/arm/gic-v3.c   | 22 ++
  xen/arch/arm/gic.c  | 36 ++--
  xen/arch/arm/irq.c  | 17 ++---
  xen/arch/arm/vgic.c | 32 ++--
  xen/include/asm-arm/gic.h   | 14 --
  xen/include/asm-arm/irq.h   |  6 ++
  8 files changed, 106 insertions(+), 82 deletions(-)



--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V4 09/11] xen: Add generic implementation of binary search

2016-07-14 Thread Shanker Donthineni
This patch adds the generic implementation of binary search algorithm
whcih is copied from Linux kernel. Only coding style changes to match
the general XEN coding style. No functional changes.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/common/Makefile   |  1 +
 xen/common/bsearch.c  | 52 +++
 xen/include/xen/bsearch.h |  9 
 3 files changed, 62 insertions(+)
 create mode 100644 xen/common/bsearch.c
 create mode 100644 xen/include/xen/bsearch.h

diff --git a/xen/common/Makefile b/xen/common/Makefile
index 2a83261..2fa36a4 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -41,6 +41,7 @@ obj-y += schedule.o
 obj-y += shutdown.o
 obj-y += softirq.o
 obj-y += sort.o
+obj-y += bsearch.o
 obj-y += smp.o
 obj-y += spinlock.o
 obj-y += stop_machine.o
diff --git a/xen/common/bsearch.c b/xen/common/bsearch.c
new file mode 100644
index 000..0946762
--- /dev/null
+++ b/xen/common/bsearch.c
@@ -0,0 +1,52 @@
+/*
+ * A generic implementation of binary search for the Linux kernel
+ *
+ * Copyright (C) 2008-2009 Ksplice, Inc.
+ * Author: Tim Abbott <tabb...@ksplice.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ */
+
+#include 
+
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt))
+{
+size_t start = 0, end = num;
+int result;
+
+while ( start < end )
+{
+size_t mid = start + (end - start) / 2;
+
+result = cmp(key, base + mid * size);
+if ( result < 0 )
+end = mid;
+else if ( result > 0 )
+start = mid + 1;
+else
+return (void *)base + mid * size;
+}
+
+return NULL;
+}
diff --git a/xen/include/xen/bsearch.h b/xen/include/xen/bsearch.h
new file mode 100644
index 000..07cf604
--- /dev/null
+++ b/xen/include/xen/bsearch.h
@@ -0,0 +1,9 @@
+#ifndef __XEN_BSEARCH_H__
+#define __XEN_BSEARCH_H__
+
+#include 
+
+void *bsearch(const void *key, const void *base, size_t num, size_t size,
+ int (*cmp)(const void *key, const void *elt));
+
+#endif /* __XEN_BSEARCH_H__ */
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V4 10/11] xen/arm: io: Use binary search for mmio handler lookup

2016-07-14 Thread Shanker Donthineni
As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v3:
  Moved the function bsearch() to common file xen/common/bsearch.c.

Changes since v2:
  Converted mmio lookup code to a critical section.
  Copied the function bsreach() from Linux kernel.

 xen/arch/arm/io.c | 42 +-
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 40330f0..0471ba8 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -70,27 +72,29 @@ static int handle_write(const struct mmio_handler *handler, 
struct vcpu *v,
handler->priv);
 }
 
-static const struct mmio_handler *find_mmio_handler(struct domain *d,
-paddr_t gpa)
+static int cmp_mmio_handler(const void *key, const void *elem)
 {
-const struct mmio_handler *handler;
-unsigned int i;
-struct vmmio *vmmio = >arch.vmmio;
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
 
-read_lock(>lock);
+if ( handler0->addr < handler1->addr )
+return -1;
 
-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( handler0->addr > (handler1->addr + handler1->size) )
+return 1;
 
-if ( (gpa >= handler->addr) &&
- (gpa < (handler->addr + handler->size)) )
-break;
-}
+return 0;
+}
 
-if ( i == vmmio->num_entries )
-handler = NULL;
+static const struct mmio_handler *find_mmio_handler(struct vcpu *v, paddr_t 
gpa)
+{
+struct vmmio *vmmio = >domain->arch.vmmio;
+struct mmio_handler key = {.addr = gpa};
+const struct mmio_handler *handler;
 
+read_lock(>lock);
+handler = bsearch(, vmmio->handlers, vmmio->num_entries,
+  sizeof(*handler), cmp_mmio_handler);
 read_unlock(>lock);
 
 return handler;
@@ -99,9 +103,9 @@ static const struct mmio_handler *find_mmio_handler(struct 
domain *d,
 int handle_mmio(mmio_info_t *info)
 {
 struct vcpu *v = current;
-const struct mmio_handler *handler = NULL;
+const struct mmio_handler *handler;
 
-handler = find_mmio_handler(v->domain, info->gpa);
+handler = find_mmio_handler(v, info->gpa);
 if ( !handler )
 return 0;
 
@@ -131,6 +135,10 @@ void register_mmio_handler(struct domain *d,
 
 vmmio->num_entries++;
 
+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
+cmp_mmio_handler, NULL);
+
 write_unlock(>lock);
 }
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH V4 11/11] arm/vgic: Change fixed number of mmio handlers to variable number

2016-07-14 Thread Shanker Donthineni
Compute the number of mmio handlers that are required for vGICv3 and
vGICv2 emulation drivers in vgic_v3_init()/vgic_v2_init(). Augment
this variable number of mmio handers to a fixed number MAX_IO_HANDLER
and pass it to domain_io_init() to allocate enough memory.

New code path:
 domain_vgic_register()
   domain_io_init(count + MAX_IO_HANDLER)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v3:
  Removed the variable 'mmio_count' from structure 'arch_domain', handle 
through a function argument.  

 xen/arch/arm/domain.c  | 12 +++-
 xen/arch/arm/vgic-v2.c |  3 ++-
 xen/arch/arm/vgic-v3.c |  5 -
 xen/arch/arm/vgic.c| 10 +++---
 xen/include/asm-arm/vgic.h |  5 +++--
 5 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 4010ff2..ddecd45 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -527,7 +527,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc, count;
+int rc, count = 0;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -550,10 +550,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -590,6 +586,12 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d, )) != 0 )
+goto fail;
+
+if ( (rc = domain_io_init(d, count + MAX_IO_HANDLER)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index f5778e6..928f9af 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -711,7 +711,7 @@ static const struct vgic_ops vgic_v2_ops = {
 .max_vcpus = 8,
 };
 
-int vgic_v2_init(struct domain *d)
+int vgic_v2_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v2_hw.enabled )
 {
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+*mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index be9a9a3..f926fe6 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1499,7 +1499,7 @@ static const struct vgic_ops v3_ops = {
 .max_vcpus = 4096,
 };
 
-int vgic_v3_init(struct domain *d)
+int vgic_v3_init(struct domain *d, int *mmio_count)
 {
 if ( !vgic_v3_hw.enabled )
 {
@@ -1509,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Redistributors */
+*mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index f5e89af..de8a94d 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,18 +88,18 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d, int *mmio_count)
 {
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
 case GIC_V3:
-if ( vgic_v3_init(d) )
+if ( vgic_v3_init(d, mmio_count) )
return -ENODEV;
 break;
 #endif
 case GIC_V2:
-if ( vgic_v2_init(d) )
+if ( vgic_v2_init(d, mmio_count) )
 return -ENODEV;
 break;
 default:
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0 )
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c3cc4f6..300f461 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -304,9 +304,10 @@ extern int vgic_emulate(struct cpu_user_regs *regs, union 
hsr hsr);
 extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n);
 extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops);
-int vgic_v2_init(struct domain *d);
-int vgic_v3_init(struct domain *d);
+int vgic_v2_init(struct domain *d, int *mmio_count);
+int vgic_v3_init(struct domain *d, int *mmio_count);
 
+extern int domain_vgic_register(struct domain *d, int *mmio_count);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t s

[Xen-devel] [PATCH V4 08/11] arm/io: Use separate memory allocation for mmio handlers

2016-07-14 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
Changes since v1:
  Moved registration of vgic_v3/v2 functionality to a new domain_vgic_register()

 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 13 +++--
 xen/include/asm-arm/mmio.h |  7 +--
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 1365b4a..4010ff2 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -527,7 +527,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -550,7 +550,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -644,6 +645,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 5a96836..40330f0 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -118,7 +118,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 write_lock(>lock);
 
@@ -134,14 +134,23 @@ void register_mmio_handler(struct domain *d,
 write_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
 rwlock_init(>arch.vmmio.lock);
 d->arch.vmmio.num_entries = 0;
+d->arch.vmmio.max_num_entries = max_count;
+d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+if ( !d->arch.vmmio.handlers )
+return -ENOMEM;
 
 return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index 32f10f2..c620eed 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -52,15 +52,18 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 rwlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
+
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V3 01/10] arm/gic-v3: Use acpi_table_parse_madt() to parse MADT subtables

2016-07-14 Thread Shanker Donthineni

Hi Stefano/Juilen

On 07/14/2016 09:18 AM, Stefano Stabellini wrote:

On Mon, 27 Jun 2016, Shanker Donthineni wrote:

The function acpi_table_parse_madt() does the same functionality as
function acpi_parse_entries() expect it takes a few arguments.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>

I committed patches 1 to 7



Thanks, I'll post the remaining patches for code review.


--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V3 04/10] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-28 Thread Shanker Donthineni



On 06/28/2016 08:51 AM, Shanker Donthineni wrote:

Hi Julien,


On 06/28/2016 05:40 AM, Julien Grall wrote:

Hello Shanker,

On 27/06/16 21:33, Shanker Donthineni wrote:

@@ -1397,6 +1408,36 @@ gic_acpi_parse_madt_distributor(struct

acpi_subtable_header *header,

  }

  static int __init
+gic_acpi_parse_cpu_redistributor(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *processor;
+u32 size;
+
+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( !(processor->flags & ACPI_MADT_ENABLED) )
+return 0;


You did not answer to my question on previous version of this patch. 
You said that "Disabled GICC entries should be skipped because its 
Redistributor region is not always-on power domain." However from my 
understanding, an usable CPU may have his Redistributor in the not 
always-on power domain. So the issue would the same, correct?




The gicv3_populate_rdist() is not supposed to read GICR registers if 
the  the associated hardware GICR block is in power-off state. The CPU 
accesses to disabled GICR region leads to either a system hang or an 
unexpected behavior.



The description of flag ACPI_MADT_ENABLED in ACPI-6.1 says "If zero, 
this processor in unusable, and the operating system support will not 
attempt to use it".




Regards,





--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V3 04/10] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-28 Thread Shanker Donthineni

Hi Julien,


On 06/28/2016 05:40 AM, Julien Grall wrote:

Hello Shanker,

On 27/06/16 21:33, Shanker Donthineni wrote:

@@ -1397,6 +1408,36 @@ gic_acpi_parse_madt_distributor(struct

acpi_subtable_header *header,

  }

  static int __init
+gic_acpi_parse_cpu_redistributor(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *processor;
+u32 size;
+
+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( !(processor->flags & ACPI_MADT_ENABLED) )
+return 0;


You did not answer to my question on previous version of this patch. 
You said that "Disabled GICC entries should be skipped because its 
Redistributor region is not always-on power domain." However from my 
understanding, an usable CPU may have his Redistributor in the not 
always-on power domain. So the issue would the same, correct?




The gicv3_populate_rdist() is not supposed to read GICR registers if 
the  the associated hardware GICR block is in power-off state. The CPU 
accesses to disabled GICR region leads to either a system hang or an 
unexpected behavior.




Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V3 09/10] xen/arm: io: Use binary search for mmio handler lookup

2016-06-28 Thread Shanker Donthineni


Hi Julien,

On 06/28/2016 05:49 AM, Julien Grall wrote:

Hi Shanker,

On 27/06/16 21:33, Shanker Donthineni wrote:

As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v2:
   Converted mmio lookup code to a critical section.
   Copied the function bsreach() from Linux kernel.

  xen/arch/arm/io.c | 97

+++

  1 file changed, 84 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index a5b2c2d..c31fdf3 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,9 +20,50 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 

+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field. However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+static void *bsearch(const void *key, const void *base, size_t num,

size_t size,

+ int (*cmp)(const void *key, const void *elt))


This function is not specific to I/O handlers. So this should be moved 
to common code. Also please mention in the commit message where the 
code came from.




Should I move to xen/arch/arm folder?


+{
+size_t start = 0, end = num;
+int result;
+
+while ( start < end )
+{
+size_t mid = start + (end - start) / 2;
+
+result = cmp(key, base + mid * size);
+if ( result < 0 )
+end = mid;
+else if ( result > 0 )
+start = mid + 1;
+else
+return (void *)base + mid * size;
+}
+
+return NULL;
+}
+
  static int handle_read(const struct mmio_handler *handler, struct vcpu

*v,

 mmio_info_t *info)
  {
@@ -70,23 +111,41 @@ static int handle_write(const struct mmio_handler

*handler, struct vcpu *v,

handler->priv);
  }

-int handle_mmio(mmio_info_t *info)
+static int match_mmio_handler(const void *key, const void *elem)
  {
-struct vcpu *v = current;
-int i;
-const struct mmio_handler *handler = NULL;
-const struct vmmio *vmmio = >domain->arch.vmmio;
+const struct mmio_handler *handler = elem;
+paddr_t addr = (paddr_t)key;

-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( addr < handler->addr )
+return -1;

-if ( (info->gpa >= handler->addr) &&
- (info->gpa < (handler->addr + handler->size)) )
-break;
-}
+if ( addr > (handler->addr + handler->size) )
+return 1;
+
+return 0;
+}

-if ( i == vmmio->num_entries )
+static const struct mmio_handler *
+find_mmio_handler(struct vcpu *v, paddr_t addr)
+{
+struct vmmio *vmmio = >domain->arch.vmmio;
+const struct mmio_handler *handler;
+
+spin_lock(>lock);
+handler = bsearch((const void *)addr, vmmio->handlers,

vmmio->num_entries,

paddr_t is always 64-bit regardless the architecture (ARM64 vs ARM32). 
So the cast will lead to a compilation error on ARM32.




I'll fix.

Please try to at least compile test your patch with ARM64, ARM32 and 
x86 (when you touch common code).




Thanks, I'll follow next time.

Anyway, I would try to merge the two compare functions 
(match_mmio_handler, cmp_mmio_handler) which have very similar behavior.




Yes, they are not exactly same. One compares only start address and 
other one compares the range.



+  sizeof(*handler), match_mmio_handler);
+spin_unlock(>lock);
+
+return handler;
+}
+
+int handle_mmio(mmio_info_t *info)
+{
+const struct mmio_handler *handler;
+struct vcpu *v = current;
+
+handler = find_mmio_handler(v, info->gpa);
+if ( !handler )
  return 0;

  if ( info->dabt.write )
@@ -95,6 +154,14 @@ int handle_mmio(mmio_info_t *info)
  return handle_read(handler, v, info);
  }

+static int cmp_mmio_handler(const void *

[Xen-devel] [PATCH V3 03/10] arm/gic-v3: Move GICR subtable parsing into a new function

2016-06-27 Thread Shanker Donthineni
Add a new function to parse GICR subtable and move the code that
is specific to GICR table to a new function without changing the
function gicv3_acpi_init() behavior.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v2:
  Changed function gic_acpi_add_rdist_region() protoype.
  Removed the address validation check in gic_acpi_parse_madt_redistributor().
  Edited commit text.

Changes since v1:
  Removed the unnecessary GICR ioremap operation inside GICR table parse code.


 xen/arch/arm/gic-v3.c | 56 +++
 1 file changed, 34 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 1f8fbc4..efdb56b 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1282,6 +1282,14 @@ static int gicv3_iomem_deny_access(const struct domain 
*d)
 }
 
 #ifdef CONFIG_ACPI
+static void __init gic_acpi_add_rdist_region(paddr_t base, paddr_t size)
+{
+unsigned int idx = gicv3.rdist_count++;
+
+gicv3.rdist_regions[idx].base = base;
+gicv3.rdist_regions[idx].size = size;
+}
+
 static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
 {
 struct acpi_subtable_header *header;
@@ -1387,6 +1395,22 @@ gic_acpi_parse_madt_distributor(struct 
acpi_subtable_header *header,
 
 return 0;
 }
+
+static int __init
+gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_redistributor *rdist;
+
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
+
+gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+
+return 0;
+}
+
 static int __init
 gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header *header,
 const unsigned long end)
@@ -1400,7 +1424,7 @@ gic_acpi_get_madt_redistributor_num(struct 
acpi_subtable_header *header,
 static void __init gicv3_acpi_init(void)
 {
 struct rdist_region *rdist_regs;
-int count, i;
+int count;
 
 /*
  * Find distributor base address. We expect one distributor entry since
@@ -1419,37 +1443,25 @@ static void __init gicv3_acpi_init(void)
 if ( count <= 0 )
 panic("GICv3: No valid GICR entries exists");
 
-gicv3.rdist_count = count;
-
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
+if ( count > MAX_RDIST_COUNT )
 panic("GICv3: Number of redistributor regions is more than"
   "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
 
-rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
+rdist_regs = xzalloc_array(struct rdist_region, count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
 
-for ( i = 0; i < gicv3.rdist_count; i++ )
-{
-struct acpi_subtable_header *header;
-struct acpi_madt_generic_redistributor *gic_rdist;
-
-header = 
acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
-   i);
-if ( !header )
-panic("GICv3: Can't get GICR entry");
-
-gic_rdist =
-   container_of(header, struct acpi_madt_generic_redistributor, 
header);
-rdist_regs[i].base = gic_rdist->base_address;
-rdist_regs[i].size = gic_rdist->length;
-}
+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+  gic_acpi_parse_madt_redistributor, count);
+if ( count <= 0 )
+panic("GICv3: Can't get Redistributor entry");
 
 /* The vGIC code requires the region to be sorted */
 sort(rdist_regs, gicv3.rdist_count, sizeof(*rdist_regs), cmp_rdist, NULL);
 
-gicv3.rdist_regions= rdist_regs;
-
 /* Collect CPU base addresses */
 count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
   gic_acpi_parse_madt_cpu, 0);
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 09/10] xen/arm: io: Use binary search for mmio handler lookup

2016-06-27 Thread Shanker Donthineni
As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v2:
  Converted mmio lookup code to a critical section.
  Copied the function bsreach() from Linux kernel.

 xen/arch/arm/io.c | 97 +++
 1 file changed, 84 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index a5b2c2d..c31fdf3 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,9 +20,50 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
+/*
+ * bsearch - binary search an array of elements
+ * @key: pointer to item being searched for
+ * @base: pointer to first element to search
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ *
+ * This function does a binary search on the given array.  The
+ * contents of the array should already be in ascending sorted order
+ * under the provided comparison function.
+ *
+ * Note that the key need not have the same type as the elements in
+ * the array, e.g. key could be a string and the comparison function
+ * could compare the string with the struct's name field.  However, if
+ * the key and elements in the array are of the same type, you can use
+ * the same comparison function for both sort() and bsearch().
+ */
+static void *bsearch(const void *key, const void *base, size_t num, size_t 
size,
+ int (*cmp)(const void *key, const void *elt))
+{
+size_t start = 0, end = num;
+int result;
+
+while ( start < end )
+{
+size_t mid = start + (end - start) / 2;
+
+result = cmp(key, base + mid * size);
+if ( result < 0 )
+end = mid;
+else if ( result > 0 )
+start = mid + 1;
+else
+return (void *)base + mid * size;
+}
+
+return NULL;
+}
+
 static int handle_read(const struct mmio_handler *handler, struct vcpu *v,
mmio_info_t *info)
 {
@@ -70,23 +111,41 @@ static int handle_write(const struct mmio_handler 
*handler, struct vcpu *v,
handler->priv);
 }
 
-int handle_mmio(mmio_info_t *info)
+static int match_mmio_handler(const void *key, const void *elem)
 {
-struct vcpu *v = current;
-int i;
-const struct mmio_handler *handler = NULL;
-const struct vmmio *vmmio = >domain->arch.vmmio;
+const struct mmio_handler *handler = elem;
+paddr_t addr = (paddr_t)key;
 
-for ( i = 0; i < vmmio->num_entries; i++ )
-{
-handler = >handlers[i];
+if ( addr < handler->addr )
+return -1;
 
-if ( (info->gpa >= handler->addr) &&
- (info->gpa < (handler->addr + handler->size)) )
-break;
-}
+if ( addr > (handler->addr + handler->size) )
+return 1;
+
+return 0;
+}
 
-if ( i == vmmio->num_entries )
+static const struct mmio_handler *
+find_mmio_handler(struct vcpu *v, paddr_t addr)
+{
+struct vmmio *vmmio = >domain->arch.vmmio;
+const struct mmio_handler *handler;
+
+spin_lock(>lock);
+handler = bsearch((const void *)addr, vmmio->handlers, vmmio->num_entries,
+  sizeof(*handler), match_mmio_handler);
+spin_unlock(>lock);
+
+return handler;
+}
+
+int handle_mmio(mmio_info_t *info)
+{
+const struct mmio_handler *handler;
+struct vcpu *v = current;
+
+handler = find_mmio_handler(v, info->gpa);
+if ( !handler )
 return 0;
 
 if ( info->dabt.write )
@@ -95,6 +154,14 @@ int handle_mmio(mmio_info_t *info)
 return handle_read(handler, v, info);
 }
 
+static int cmp_mmio_handler(const void *key, const void *elem)
+{
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
+
+return (handler0->addr < handler1->addr) ? -1 : 0;
+}
+
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv)
@@ -122,6 +189,10 @@ void register_mmio_handler(struct domain *d,
 
 vmmio->num_entries++;
 
+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
+ cmp_mmio_handler, NULL);
+
 spin_unlock(>lock);
 }
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Cod

[Xen-devel] [PATCH V3 08/10] arm/io: Use separate memory allocation for mmio handlers

2016-06-27 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
Changes since v1:
  Moved registration of vgic_v3/v2 functionality to a new 
domain_vgic_register().

 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 14 --
 xen/include/asm-arm/mmio.h |  6 --
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 1365b4a..4010ff2 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -527,7 +527,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -550,7 +550,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -644,6 +645,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 0156755..a5b2c2d 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -102,7 +102,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 spin_lock(>lock);
 
@@ -125,14 +125,24 @@ void register_mmio_handler(struct domain *d,
 spin_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
spin_lock_init(>arch.vmmio.lock);
d->arch.vmmio.num_entries = 0;
 
+   d->arch.vmmio.max_num_entries = max_count;
+   d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+   if ( !d->arch.vmmio.handlers )
+   return -ENOMEM;
+
return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index da1cc2e..276b263 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -51,15 +51,17 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 spinlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 07/10] arm: vgic: Split vgic_domain_init() functionality into two functions

2016-06-27 Thread Shanker Donthineni
Separate the code logic that does the registration of vgic_v3/v2 ops
to a new function domain_vgic_register(). The intention of this
separation is to record the required mmio count in vgic_v3/v2_init()
and pass it to function domain_io_init() in a follow-up patch patch.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v2:
  Edited commit text.

 xen/arch/arm/vgic.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 5df5f01..f5e89af 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,19 +88,8 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-int domain_vgic_init(struct domain *d, unsigned int nr_spis)
+static int domain_vgic_register(struct domain *d)
 {
-int i;
-int ret;
-
-d->arch.vgic.ctlr = 0;
-
-/* Limit the number of virtual SPIs supported to (1020 - 32) = 988  */
-if ( nr_spis > (1020 - NR_LOCAL_IRQS) )
-return -EINVAL;
-
-d->arch.vgic.nr_spis = nr_spis;
-
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
@@ -119,6 +108,26 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 return -ENODEV;
 }
 
+return 0;
+}
+
+int domain_vgic_init(struct domain *d, unsigned int nr_spis)
+{
+int i;
+int ret;
+
+d->arch.vgic.ctlr = 0;
+
+/* Limit the number of virtual SPIs supported to (1020 - 32) = 988  */
+if ( nr_spis > (1020 - NR_LOCAL_IRQS) )
+return -EINVAL;
+
+d->arch.vgic.nr_spis = nr_spis;
+
+ret = domain_vgic_register(d);
+if ( ret < 0 )
+return ret;
+
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 04/10] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-27 Thread Shanker Donthineni
The redistributor address can be specified either as part of GICC or
GICR subtable depending on the power domain. The current driver
doesn't support parsing redistributor entry that is defined in GICC
subtable. The GIC CPU subtable entry holds the associated Redistributor
base address if it is not on always-on power domain.

The per CPU Redistributor size is not defined in ACPI specification.
Set the GICR region size to SZ_256K if the GIC hardware is capable of
Direct Virtual LPI Injection feature, SZ_128K otherwise.

This patch adds necessary code to handle both types of Redistributors
base addresses.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v2:
  Removed the unnecessary validation checks and edited commit text.

 xen/arch/arm/gic-v3.c | 68 +++
 xen/include/asm-arm/gic.h |  1 +
 xen/include/asm-arm/gic_v3_defs.h |  1 +
 3 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index efdb56b..352799e 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -659,6 +659,10 @@ static int __init gicv3_populate_rdist(void)
 smp_processor_id(), i, ptr);
 return 0;
 }
+
+if ( gicv3.rdist_regions[i].single_rdist )
+break;
+
 if ( gicv3.rdist_stride )
 ptr += gicv3.rdist_stride;
 else
@@ -1282,14 +1286,21 @@ static int gicv3_iomem_deny_access(const struct domain 
*d)
 }
 
 #ifdef CONFIG_ACPI
-static void __init gic_acpi_add_rdist_region(paddr_t base, paddr_t size)
+static void __init
+gic_acpi_add_rdist_region(paddr_t base, paddr_t size, bool single_rdist)
 {
 unsigned int idx = gicv3.rdist_count++;
 
+gicv3.rdist_regions[idx].single_rdist = single_rdist;
 gicv3.rdist_regions[idx].base = base;
 gicv3.rdist_regions[idx].size = size;
 }
 
+static inline bool gic_dist_supports_dvis(void)
+{
+return !!(readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_DVIS);
+}
+
 static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
 {
 struct acpi_subtable_header *header;
@@ -1397,6 +1408,36 @@ gic_acpi_parse_madt_distributor(struct 
acpi_subtable_header *header,
 }
 
 static int __init
+gic_acpi_parse_cpu_redistributor(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *processor;
+u32 size;
+
+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( !(processor->flags & ACPI_MADT_ENABLED) )
+return 0;
+
+size = gic_dist_supports_dvis() ? 4 * SZ_64K : 2 * SZ_64K;
+gic_acpi_add_rdist_region(processor->gicr_base_address, size, true);
+
+return 0;
+}
+
+static int __init
+gic_acpi_get_madt_cpu_num(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *cpuif;
+
+cpuif = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(cpuif, end) || !cpuif->gicr_base_address )
+return -EINVAL;
+
+return 0;
+}
+
+static int __init
 gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
   const unsigned long end)
 {
@@ -1406,7 +1447,7 @@ gic_acpi_parse_madt_redistributor(struct 
acpi_subtable_header *header,
 if ( BAD_MADT_ENTRY(rdist, end) )
 return -EINVAL;
 
-gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+gic_acpi_add_rdist_region(rdist->base_address, rdist->length, false);
 
 return 0;
 }
@@ -1424,6 +1465,7 @@ gic_acpi_get_madt_redistributor_num(struct 
acpi_subtable_header *header,
 static void __init gicv3_acpi_init(void)
 {
 struct rdist_region *rdist_regs;
+bool gicr_table = true;
 int count;
 
 /*
@@ -1440,8 +1482,15 @@ static void __init gicv3_acpi_init(void)
 /* Get number of redistributor */
 count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
   gic_acpi_get_madt_redistributor_num, 0);
-if ( count <= 0 )
-panic("GICv3: No valid GICR entries exists");
+/* Count the total number of CPU interface entries */
+if ( count <= 0 ) {
+count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+  gic_acpi_get_madt_cpu_num, 0);
+if (count <= 0)
+panic("GICv3: No valid GICR entries exists");
+
+gicr_table = false;
+}
 
 if ( count > MAX_RDIST_COUNT )
 panic("GICv3: Number of redistributor regions is more than"
@@ -1453,9 +1502,14 @@ static void __init gicv3_acpi_init(void)
 
 gicv3.rdist_regions = rdist_regs;
 
-/* Parse always-on power domain Re-distributor entries */
-count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR

[Xen-devel] [PATCH V3 05/10] xen/arm: vgic: Use dynamic memory allocation for vgic_rdist_region

2016-06-27 Thread Shanker Donthineni
The number of Redistributor regions allowed for dom0 is hardcoded
to a define MAX_RDIST_COUNT which is 4. Some systems, especially
latest server chips, may have more than 4 redistributors. Either we
have to increase MAX_RDIST_COUNT to a bigger number or allocate
memory based on the number of redistributors that are found in MADT
table. In the worst case scenario, the macro MAX_RDIST_COUNT should
be equal to CONFIG_NR_CPUS in order to support per CPU Redistributors.

Increasing MAX_RDIST_COUNT has a effect, it blows 'struct domain'
size and hits BUILD_BUG_ON() in domain build code path.

struct domain *alloc_domain_struct(void)
{
struct domain *d;
BUILD_BUG_ON(sizeof(*d) > PAGE_SIZE);
d = alloc_xenheap_pages(0, 0);
if ( d == NULL )
return NULL;
...

This patch uses the second approach to fix the BUILD_BUG().

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes sicne v2:
  Edited commit text.

 xen/arch/arm/vgic-v2.c   |  6 ++
 xen/arch/arm/vgic-v3.c   | 27 ---
 xen/arch/arm/vgic.c  |  1 +
 xen/include/asm-arm/domain.h |  2 +-
 xen/include/asm-arm/vgic.h   |  2 ++
 5 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 9adb4a9..f5778e6 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -699,9 +699,15 @@ static int vgic_v2_domain_init(struct domain *d)
 return 0;
 }
 
+static void vgic_v2_domain_free(struct domain *d)
+{
+/* Nothing to be cleanup for this driver */
+}
+
 static const struct vgic_ops vgic_v2_ops = {
 .vcpu_init   = vgic_v2_vcpu_init,
 .domain_init = vgic_v2_domain_init,
+.domain_free = vgic_v2_domain_free,
 .max_vcpus = 8,
 };
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index b37a7c0..be9a9a3 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1391,9 +1391,26 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
 return 0;
 }
 
+static inline unsigned int vgic_v3_rdist_count(struct domain *d)
+{
+return is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
+   GUEST_GICV3_RDIST_REGIONS;
+}
+
 static int vgic_v3_domain_init(struct domain *d)
 {
-int i;
+struct vgic_rdist_region *rdist_regions;
+int rdist_count, i;
+
+/* Allocate memory for Re-distributor regions */
+rdist_count = vgic_v3_rdist_count(d);
+
+rdist_regions = xzalloc_array(struct vgic_rdist_region, rdist_count);
+if ( !rdist_regions )
+return -ENOMEM;
+
+d->arch.vgic.nr_regions = rdist_count;
+d->arch.vgic.rdist_regions = rdist_regions;
 
 /*
  * Domain 0 gets the hardware address.
@@ -1426,7 +1443,6 @@ static int vgic_v3_domain_init(struct domain *d)
 
 first_cpu += size / d->arch.vgic.rdist_stride;
 }
-d->arch.vgic.nr_regions = vgic_v3_hw.nr_rdist_regions;
 }
 else
 {
@@ -1435,7 +1451,6 @@ static int vgic_v3_domain_init(struct domain *d)
 /* XXX: Only one Re-distributor region mapped for the guest */
 BUILD_BUG_ON(GUEST_GICV3_RDIST_REGIONS != 1);
 
-d->arch.vgic.nr_regions = GUEST_GICV3_RDIST_REGIONS;
 d->arch.vgic.rdist_stride = GUEST_GICV3_RDIST_STRIDE;
 
 /* The first redistributor should contain enough space for all CPUs */
@@ -1467,9 +1482,15 @@ static int vgic_v3_domain_init(struct domain *d)
 return 0;
 }
 
+static void vgic_v3_domain_free(struct domain *d)
+{
+xfree(d->arch.vgic.rdist_regions);
+}
+
 static const struct vgic_ops v3_ops = {
 .vcpu_init   = vgic_v3_vcpu_init,
 .domain_init = vgic_v3_domain_init,
+.domain_free = vgic_v3_domain_free,
 .emulate_sysreg  = vgic_v3_emulate_sysreg,
 /*
  * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 3e1c572..5df5f01 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -177,6 +177,7 @@ void domain_vgic_free(struct domain *d)
 }
 }
 
+d->arch.vgic.handler->domain_free(d);
 xfree(d->arch.vgic.shared_irqs);
 xfree(d->arch.vgic.pending_irqs);
 xfree(d->arch.vgic.allocated_irqs);
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 370cdeb..29346c6 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -107,7 +107,7 @@ struct arch_domain
 paddr_t base;   /* Base address */
 paddr_t size;   /* Size */
 unsigned int first_cpu; /* First CPU handled */
-} rdist_regions[MAX_RDIST_COUNT];
+} *rdist_regions;
 int nr_regions; /* Number of rdist regions */
 uint32_t rdist_stride;  /* Re-Distributor stride */
 #endif
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index a2fccc0..c3cc4f6 100644
--- a/xen/include/asm-arm/vgic

[Xen-devel] [PATCH v3 06/10] arm/gic-v3: Remove an unused macro MAX_RDIST_COUNT

2016-06-27 Thread Shanker Donthineni
The macro MAX_RDIST_COUNT is not being used after converting code
to handle number of redistributor dynamically. So remove it from
header file and the two other panic() messages that are not valid
anymore.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
 xen/arch/arm/gic-v3.c | 8 
 xen/include/asm-arm/gic.h | 1 -
 2 files changed, 9 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 352799e..948052b 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1200,10 +1200,6 @@ static void __init gicv3_dt_init(void)
 _count) )
 gicv3.rdist_count = 1;
 
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
-panic("GICv3: Number of redistributor regions is more than"
-  "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
-
 rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
@@ -1492,10 +1488,6 @@ static void __init gicv3_acpi_init(void)
 gicr_table = false;
 }
 
-if ( count > MAX_RDIST_COUNT )
-panic("GICv3: Number of redistributor regions is more than"
-  "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
-
 rdist_regs = xzalloc_array(struct rdist_region, count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index fedf1fa..db7b2d0 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -20,7 +20,6 @@
 
 #define NR_GIC_LOCAL_IRQS  NR_LOCAL_IRQS
 #define NR_GIC_SGI 16
-#define MAX_RDIST_COUNT4
 
 #define GICD_CTLR   (0x000)
 #define GICD_TYPER  (0x004)
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 02/10] arm/gic-v3: Do early GICD ioremap and clean up

2016-06-27 Thread Shanker Donthineni
For ACPI based XEN boot, the GICD region needs to be accessed inside
the function gicv3_acpi_init() in later patch. There is a duplicate
panic() message, one in the DTS probe and second one in the ACPI probe
path. For these two reasons, move the code that validates the GICD base
address and does the region ioremap to a separate function. The
following patch accesses the GICD region inside gicv3_acpi_init() for
finding per CPU Redistributor size.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Acked-by: Julien Grall <julien.gr...@arm.com>
---
Changes sicne v1:
  Edited commit text.

 xen/arch/arm/gic-v3.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 166f1c1..1f8fbc4 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1169,6 +1169,17 @@ static void __init gicv3_init_v2(void)
 vgic_v2_setup_hw(dbase, cbase, csize, vbase, 0);
 }
 
+static void __init gicv3_ioremap_distributor(paddr_t dist_paddr)
+{
+if ( dist_paddr & ~PAGE_MASK )
+panic("GICv3:  Found unaligned distributor address %"PRIpaddr"",
+  dbase);
+
+gicv3.map_dbase = ioremap_nocache(dist_paddr, SZ_64K);
+if ( !gicv3.map_dbase )
+panic("GICv3: Failed to ioremap for GIC distributor\n");
+}
+
 static void __init gicv3_dt_init(void)
 {
 struct rdist_region *rdist_regs;
@@ -1179,9 +1190,7 @@ static void __init gicv3_dt_init(void)
 if ( res )
 panic("GICv3: Cannot find a valid distributor address");
 
-if ( (dbase & ~PAGE_MASK) )
-panic("GICv3:  Found unaligned distributor address %"PRIpaddr"",
-  dbase);
+gicv3_ioremap_distributor(dbase);
 
 if ( !dt_property_read_u32(node, "#redistributor-regions",
 _count) )
@@ -1402,9 +1411,7 @@ static void __init gicv3_acpi_init(void)
 if ( count <= 0 )
 panic("GICv3: No valid GICD entries exists");
 
-if ( (dbase & ~PAGE_MASK) )
-panic("GICv3: Found unaligned distributor address %"PRIpaddr"",
-  dbase);
+gicv3_ioremap_distributor(dbase);
 
 /* Get number of redistributor */
 count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
@@ -1476,10 +1483,6 @@ static int __init gicv3_init(void)
 else
 gicv3_acpi_init();
 
-gicv3.map_dbase = ioremap_nocache(dbase, SZ_64K);
-if ( !gicv3.map_dbase )
-panic("GICv3: Failed to ioremap for GIC distributor\n");
-
 reg = readl_relaxed(GICD + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
 if ( reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4 )
  panic("GICv3: no distributor detected\n");
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V3 10/10] arm/vgic: Change fixed number of mmio handlers to variable number

2016-06-27 Thread Shanker Donthineni
Record the number of mmio handlers that are required for vGICv3/2
in variable 'arch_domain.vgic.mmio_count' in vgic_v3/v2_init().
Augment this variable number to a fixed number MAX_IO_HANDLER and
pass it to domain_io_init() to allocate enough memory for handlers.

New code path:
 domain_vgic_register()
   count = MAX_IO_HANDLER + d->arch.vgic.mmio_count;
   domain_io_init(count)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c| 11 +++
 xen/arch/arm/vgic-v2.c   |  1 +
 xen/arch/arm/vgic-v3.c   |  3 +++
 xen/arch/arm/vgic.c  |  6 +-
 xen/include/asm-arm/domain.h |  1 +
 xen/include/asm-arm/vgic.h   |  1 +
 6 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 4010ff2..ebc12ac 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -550,10 +550,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -590,6 +586,13 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d)) != 0 )
+goto fail;
+
+count = MAX_IO_HANDLER + d->arch.vgic.mmio_count;
+if ( (rc = domain_io_init(d, count)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index f5778e6..d5367b3 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+d->arch.vgic.mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index be9a9a3..e527f3f 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1509,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Re-distributors */
+d->arch.vgic.mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index f5e89af..0658bfc 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,7 +88,7 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d)
 {
 switch ( d->arch.vgic.version )
 {
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0 )
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 29346c6..b205461 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -111,6 +111,7 @@ struct arch_domain
 int nr_regions; /* Number of rdist regions */
 uint32_t rdist_stride;  /* Re-Distributor stride */
 #endif
+uint32_t mmio_count;/* Number of mmio handlers */
 } vgic;
 
 struct vuart {
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index c3cc4f6..a693f95 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -307,6 +307,7 @@ extern void register_vgic_ops(struct domain *d, const 
struct vgic_ops *ops);
 int vgic_v2_init(struct domain *d);
 int vgic_v3_init(struct domain *d);
 
+extern int domain_vgic_register(struct domain *d);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 03/10] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 11:09 AM, Julien Grall wrote:

On 27/06/16 17:07, Shanker Donthineni wrote:

On 06/27/2016 10:41 AM, Julien Grall wrote:



On 27/06/16 16:40, Shanker Donthineni wrote:

+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+ gic_acpi_parse_madt_redistributor,

table,

+ ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,

count);

Please use acpi_table_parse_madt here.



How do we pass MADT table pointer that we are using to a function
acpi_table_parse_madt()?  We have already obtained  the MADT table
address by calling  acpi_get_table() at the beginning of the function
gicv3_acpi_init().


You don't need to pass it. The function will take care to get the MADT
table for you.



Are you expecting me to modify current driver to replace
acpi_parse_entries() calls with acpi_table_parse_madt() before my

changes?

No, I was just suggesting to modify the caller you changed/added 
within the different patch.




Code becomes ugly for readability purpose using two set of functions in 
a single function.



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 03/10] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-27 Thread Shanker Donthineni

 be

On 06/27/2016 10:41 AM, Julien Grall wrote:



On 27/06/16 16:40, Shanker Donthineni wrote:

+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+ gic_acpi_parse_madt_redistributor,

table,

+ ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,

count);

Please use acpi_table_parse_madt here.



How do we pass MADT table pointer that we are using to a function
acpi_table_parse_madt()?  We have already obtained  the MADT table
address by calling  acpi_get_table() at the beginning of the function
gicv3_acpi_init().


You don't need to pass it. The function will take care to get the MADT 
table for you.




Are you expecting me to modify current driver to replace 
acpi_parse_entries() calls with acpi_table_parse_madt() before my changes?





Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 03/10] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 06:26 AM, Julien Grall wrote:

Hi Shanker,

Title: I think you want to say "Move GICR..." rather than "Fold GICR...".

On 26/06/16 18:48, Shanker Donthineni wrote:

Add a new function for parsing GICR subtable and move the code


Add a new function to parse GICR...


that is specific to GICR table to new function without changing


to a new function


the function gicv3_acpi_init() behavior.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
   Removed the unnecessary GICR ioremap operation inside GICR table

parse code.


  xen/arch/arm/gic-v3.c | 61

---

  1 file changed, 39 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 542c4f3..0471fea 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1282,6 +1282,14 @@ static int gicv3_iomem_deny_access(const struct

domain *d)

  }

  #ifdef CONFIG_ACPI
+static void __init gic_acpi_add_rdist_region(u64 base_addr, u32 size)


Please use paddr_t for both parameter. Also the suffix _addr is 
pointless.



+{
+unsigned int idx = gicv3.rdist_count++;
+
+gicv3.rdist_regions[idx].base = base_addr;
+gicv3.rdist_regions[idx].size = size;
+}
+
  static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
  {
  struct acpi_subtable_header *header;
@@ -1387,6 +1395,25 @@ gic_acpi_parse_madt_distributor(struct

acpi_subtable_header *header,


  return 0;
  }
+
+static int __init
+gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_redistributor *rdist;
+
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
+
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;


In the commit message you said that the behavior is unchanged, however 
this check is not part of the previous code.


Anyway, I don't think this check is necessary.


+
+gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+
+return 0;
+}
+
  static int __init
  gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header

*header,

const unsigned long end)
@@ -1402,7 +1429,7 @@ static void __init gicv3_acpi_init(void)
  struct acpi_table_header *table;
  struct rdist_region *rdist_regs;
  acpi_status status;
-int count, i;
+int count;

  status = acpi_get_table(ACPI_SIG_MADT, 0, );

@@ -1433,37 +1460,27 @@ static void __init gicv3_acpi_init(void)
  if ( count <= 0 )
  panic("GICv3: No valid GICR entries exists");

-gicv3.rdist_count = count;
-
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
+if ( count > MAX_RDIST_COUNT )
  panic("GICv3: Number of redistributor regions is more than"
"%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);

-rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
+rdist_regs = xzalloc_array(struct rdist_region, count);
  if ( !rdist_regs )
  panic("GICv3: Failed to allocate memory for rdist regions\n");

-for ( i = 0; i < gicv3.rdist_count; i++ )
-{
-struct acpi_subtable_header *header;
-struct acpi_madt_generic_redistributor *gic_rdist;
-
-header =

acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,

- i);
-if ( !header )
-panic("GICv3: Can't get GICR entry");
-
-gic_rdist =
-   container_of(header, struct acpi_madt_generic_redistributor,

header);

-rdist_regs[i].base = gic_rdist->base_address;
-rdist_regs[i].size = gic_rdist->length;
-}
+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+ gic_acpi_parse_madt_redistributor,

table,

+ ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,

count);

Please use acpi_table_parse_madt here.



How do we pass MADT table pointer that we are using to a function 
acpi_table_parse_madt()?  We have already obtained  the MADT table 
address by calling  acpi_get_table() at the beginning of the function 
gicv3_acpi_init().




+if ( count <= 0 )
+panic("GICv3: Can't get Redistributor entry");

  /* The vGIC code requires the region to be sorted */
  sort(rdist_regs, gicv3.rdist_count, sizeof(*rdist_regs),

cmp_rdist, NULL);


-gicv3.rdist_regions= rdist_regs;
-
  /* Collect CPU base addresses */
  count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct

acpi_table_madt),

gic_acpi_parse_madt_cpu, table,



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Ce

Re: [Xen-devel] [PATCH V2 10/10] arm/vgic: Change fixed number of mmio handlers to variable number

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 08:35 AM, Julien Grall wrote:

Hi Shanker,

On 26/06/16 18:48, Shanker Donthineni wrote:

diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 29346c6..b205461 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -111,6 +111,7 @@ struct arch_domain
  int nr_regions; /* Number of rdist regions

*/

  uint32_t rdist_stride;  /* Re-Distributor stride

*/

  #endif
+uint32_t mmio_count;/* Number of mmio handlers

*/

Is it necessary to have this value part of the arch_domain? I.e Do we 
need this value after the initialization? If not, then it might be 
better to add a parameter to domain_vgic_register uint32_t *pointer.


Absolutely, we don't need this variable after the domain build process. 
I have taken this approach to avoid too many code changes. Your 
suggestion requires changes to functions vgic_v2/v3_init() prototype for 
adding a new parameter.



  } vgic;

  struct vuart {
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index fbb763a..1ce441c 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -307,6 +307,7 @@ extern void register_vgic_ops(struct domain *d,

const struct vgic_ops *ops);

  int vgic_v2_init(struct domain *d);
  int vgic_v3_init(struct domain *d);

+extern int domain_vgic_register(struct domain *d);
  extern int vcpu_vgic_free(struct vcpu *v);
  extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
 enum gic_sgi_mode irqmode, int virq,



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 09/10] xen/arm: io: Use binary search for mmio handler lookup

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 08:31 AM, Julien Grall wrote:

Hi Shanker,

On 26/06/16 18:48, Shanker Donthineni wrote:

As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
  xen/arch/arm/io.c | 50

+++---

  1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index a5b2c2d..abf49fb 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 

@@ -70,23 +71,38 @@ static int handle_write(const struct mmio_handler

*handler, struct vcpu *v,

handler->priv);
  }

-int handle_mmio(mmio_info_t *info)
+const struct mmio_handler *find_mmio_handler(struct vcpu *v, paddr_t

addr)

  {
-struct vcpu *v = current;
-int i;
-const struct mmio_handler *handler = NULL;
  const struct vmmio *vmmio = >domain->arch.vmmio;
+const struct mmio_handler *handler = vmmio->handlers;
+unsigned int eidx = vmmio->num_entries;
+unsigned int midx = eidx / 2;
+unsigned int sidx = 0;

-for ( i = 0; i < vmmio->num_entries; i++ )
+/* Do binary search for matching mmio handler */
+while ( sidx != midx )
  {
-handler = >handlers[i];
-
-if ( (info->gpa >= handler->addr) &&
- (info->gpa < (handler->addr + handler->size)) )
-break;
+if ( addr < handler[midx].addr )
+eidx = midx;
+else
+sidx = midx;
+midx = sidx + (eidx - sidx) / 2;


This binary search can be simplified. For instance, why do you want to 
compute midx at the end rather than at the beginning. This would avoid 
to have "unsigned int midx = eidx / 2" at the beginning.




Let me try to use "do while()" loop logic to simplify the above code logic.


  }

-if ( i == vmmio->num_entries )
+if ( (addr >= handler[sidx].addr) &&
+ (addr < (handler[sidx].addr + handler[sidx].size)) )
+return handler + sidx;


Please use a temporary variable for handler[sidx]. So it will be 
easier to read the code.



+
+return NULL;
+}
+
+int handle_mmio(mmio_info_t *info)
+{
+const struct mmio_handler *handler;
+struct vcpu *v = current;
+
+handler = find_mmio_handler(v, info->gpa);


I would have expected some locking here. Could you explain why it is 
safe to looking find the handler with your solution?


For what is worth, there was no locking before because 
register_mmio_handler was always adding the handler at the end of the 
array. This is not true anymore because you are sorting the array.




The function register_mmio_handler() is called only during dom0/domU 
domain build code path. We don't need locking here until unless some 
code inserting mmio handlers at runtime.





+if ( !handler )
  return 0;

  if ( info->dabt.write )
@@ -95,6 +111,14 @@ int handle_mmio(mmio_info_t *info)
  return handle_read(handler, v, info);
  }

+static int cmp_mmio_handler(const void *key, const void *elem)
+{
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
+
+return (handler0->addr < handler1->addr) ? -1 : 0;
+}
+
  void register_mmio_handler(struct domain *d,
 const struct mmio_handler_ops *ops,
 paddr_t addr, paddr_t size, void *priv)
@@ -122,6 +146,10 @@ void register_mmio_handler(struct domain *d,

  vmmio->num_entries++;

+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct

mmio_handler),

+ cmp_mmio_handler, NULL);
+
  spin_unlock(>lock);
  }




Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 05/10] xen/arm: vgic: Use dynamic memory allocation for vgic_rdist_region

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 07:38 AM, Julien Grall wrote:

Hi Shanker,

On 26/06/16 18:48, Shanker Donthineni wrote:

The number of Re-distributor regions allowed for dom0 is hardcoded


s/Re-distributor/Redistributor/


to a compile time macro MAX_RDIST_COUNT which is 4. On some systems,


s/a compile time macro/a define/
s/On some/Some/


especially latest server chips might have more than 4 redistributors.


I would add a comma after 'chips'.

NIT: s/redistributors/Redistributors/


Either we have to increase MAX_RDIST_COUNT to a bigger number or
allocate memory based on number of redistributors that are found in


s/based on number/based on the number/


MADT table. In the worst case scenario, the macro MAX_RDIST_COUNT
should be equal to CONFIG_NR_CPUS in order to support per CPU
Redistributors.

Increasing MAX_RDIST_COUNT has side effect, it blows 'struct domain'


s/has side/has a/


size and hits BUILD_BUG_ON() in domain build code path.

struct domain *alloc_domain_struct(void)
{
 struct domain *d;
 BUILD_BUG_ON(sizeof(*d) > PAGE_SIZE);
 d = alloc_xenheap_pages(0, 0);
 if ( d == NULL )
 return NULL;
...

This patch uses the second approach to fix the BUILD_BUG().

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
   Keep 'struct vgic_rdist_region' definition inside 'struct

arch_domain'.


  xen/arch/arm/vgic-v2.c   |  6 ++
  xen/arch/arm/vgic-v3.c   | 22 +++---
  xen/arch/arm/vgic.c  |  1 +
  xen/include/asm-arm/domain.h |  2 +-
  xen/include/asm-arm/vgic.h   |  2 ++
  5 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 9adb4a9..f5778e6 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -699,9 +699,15 @@ static int vgic_v2_domain_init(struct domain *d)
  return 0;
  }

+static void vgic_v2_domain_free(struct domain *d)
+{
+/* Nothing to be cleanup for this driver */
+}
+
  static const struct vgic_ops vgic_v2_ops = {
  .vcpu_init   = vgic_v2_vcpu_init,
  .domain_init = vgic_v2_domain_init,
+.domain_free = vgic_v2_domain_free,
  .max_vcpus = 8,
  };

diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index b37a7c0..e877e9e 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1393,7 +1393,19 @@ static int vgic_v3_vcpu_init(struct vcpu *v)

  static int vgic_v3_domain_init(struct domain *d)
  {
-int i;
+struct vgic_rdist_region *rdist_regions;
+int rdist_count, i;
+
+/* Allocate memory for Re-distributor regions */
+rdist_count = is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
+   GUEST_GICV3_RDIST_REGIONS;


I would directly introduce the inline helper in this patch, rather 
than in patch #10.



Okay, I'll add a helper function as part of this patch.


+
+rdist_regions = xzalloc_array(struct vgic_rdist_region,

rdist_count);

+if ( !rdist_regions )
+return -ENOMEM;
+
+d->arch.vgic.nr_regions = rdist_count;
+d->arch.vgic.rdist_regions = rdist_regions;

  /*
   * Domain 0 gets the hardware address.


[...]


diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index a2fccc0..fbb763a 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -128,6 +128,8 @@ struct vgic_ops {
  int (*vcpu_init)(struct vcpu *v);
  /* Domain specific initialization of vGIC */
  int (*domain_init)(struct domain *d);
+/* Release resources that are allocated by domain_init */


s/are/were/


+void (*domain_free)(struct domain *d);
  /* vGIC sysreg emulation */
  int (*emulate_sysreg)(struct cpu_user_regs *regs, union hsr hsr);
  /* Maximum number of vCPU supported */



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 04/10] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 06:47 AM, Julien Grall wrote:

Hi Shanker,

On 26/06/16 18:48, Shanker Donthineni wrote:

The redistributor address can be specified either as part of GICC or
GICR subtable depending on the power domain. The current driver
doesn't support parsing redistributor entry that is defined in GICC
subtable. The GIC CPU subtable entry holds the associated Redistributor
base address if it is not on always-on power domain.

The per CPU Redistributor size is not defined in ACPI specification.
Set it's size to SZ_256K if the GIC hardware is capable of Direct


s/it's/its/, although I would use "the".


Virtual LPI Injection feature otherwise SZ_128K.


"Set the size to SZ_256K if the GIC hardware is supporting Direct 
Virtual LPI injection, SZ_128K otherwise".




This patch adds necessary code to handle both types of Redistributors
base addresses.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
   Edited commit text and fixed white spaces.
   Added a new function for parsing per CPU Redistributor entry.

  xen/arch/arm/gic-v3.c | 84

++-

  xen/include/asm-arm/gic.h |  1 +
  xen/include/asm-arm/gic_v3_defs.h |  1 +
  3 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 0471fea..3977244 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -659,6 +659,10 @@ static int __init gicv3_populate_rdist(void)
  smp_processor_id(), i, ptr);
  return 0;
  }
+
+if ( gicv3.rdist_regions[i].single_rdist )
+break;
+
  if ( gicv3.rdist_stride )
  ptr += gicv3.rdist_stride;
  else
@@ -1282,14 +1286,21 @@ static int gicv3_iomem_deny_access(const struct

domain *d)

  }

  #ifdef CONFIG_ACPI
-static void __init gic_acpi_add_rdist_region(u64 base_addr, u32 size)
+static void __init
+gic_acpi_add_rdist_region(u64 base_addr, u32 size, bool single_rdist)
  {
  unsigned int idx = gicv3.rdist_count++;

+gicv3.rdist_regions[idx].single_rdist = single_rdist;
  gicv3.rdist_regions[idx].base = base_addr;
  gicv3.rdist_regions[idx].size = size;
  }

+static inline bool gic_dist_supports_dvis(void)
+{
+return !!(readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_DVIS);
+}
+
  static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
  {
  struct acpi_subtable_header *header;
@@ -1397,6 +1408,42 @@ gic_acpi_parse_madt_distributor(struct

acpi_subtable_header *header,

  }

  static int __init
+gic_acpi_parse_cpu_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *processor;
+u32 size;
+
+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(processor, end) )
+return -EINVAL;
+
+if ( !processor->gicr_base_address )
+return -EINVAL;


You already check it in gic_acpi_get_madt_cpu_num, so there is no 
reason to do it again.


Other function just finds the number of valid cpu interfaces. I would  
prefer to keep the validation check here.



+
+if ( processor->flags & ACPI_MADT_ENABLED )
+{
+size = gic_dist_supports_dvis() ? 4 * SZ_64K : 2 * SZ_64K;
+ gic_acpi_add_rdist_region(processor->gicr_base_address, size,

true);

+}


I would revert the condition to avoid one level of indentation. I.e



I'll do.


if ( !(processor->flags & ACPI_MADT_ENABLED) )
  return 0;

size = 
gic_acpi_add...

return 0;

However, it looks like that the other function that parses GICC within 
gic-v3.c (see gic_acpi_parse_madt_cpu) does not check if the CPU is

usable.



Disabled GICC entries should be skipped because its Redistributor region 
is not always-on power domain. Please look at my review comment to your 
KVM-ACPI patch http://www.gossamer-threads.com/lists/linux/kernel/2413670.



I think we need to have the same parsing behavior on every function.


+
+return 0;
+}
+
+static int __init
+gic_acpi_get_madt_cpu_num(struct acpi_subtable_header *header,
+const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *cpuif;
+
+cpuif = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(cpuif, end) || !cpuif->gicr_base_address )
+return -EINVAL;
+
+return 0;
+}
+
+static int __init
  gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
const unsigned long end)
  {
@@ -1409,7 +1456,7 @@ gic_acpi_parse_madt_redistributor(struct

acpi_subtable_header *header,

  if ( !rdist->base_address || !rdist->length )
  return -EINVAL;

-gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+gic_acpi_add_rdist_region(rdist->base_address, rdist-

Re: [Xen-devel] [PATCH V2 03/10] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 06:26 AM, Julien Grall wrote:

Hi Shanker,

Title: I think you want to say "Move GICR..." rather than "Fold GICR...".

On 26/06/16 18:48, Shanker Donthineni wrote:

Add a new function for parsing GICR subtable and move the code


Add a new function to parse GICR...


that is specific to GICR table to new function without changing


to a new function


the function gicv3_acpi_init() behavior.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
   Removed the unnecessary GICR ioremap operation inside GICR table

parse code.


  xen/arch/arm/gic-v3.c | 61

---

  1 file changed, 39 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 542c4f3..0471fea 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1282,6 +1282,14 @@ static int gicv3_iomem_deny_access(const struct

domain *d)

  }

  #ifdef CONFIG_ACPI
+static void __init gic_acpi_add_rdist_region(u64 base_addr, u32 size)


Please use paddr_t for both parameter. Also the suffix _addr is 
pointless.




I'll fix.

+{
+unsigned int idx = gicv3.rdist_count++;
+
+gicv3.rdist_regions[idx].base = base_addr;
+gicv3.rdist_regions[idx].size = size;
+}
+
  static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
  {
  struct acpi_subtable_header *header;
@@ -1387,6 +1395,25 @@ gic_acpi_parse_madt_distributor(struct

acpi_subtable_header *header,


  return 0;
  }
+
+static int __init
+gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_redistributor *rdist;
+
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
+
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;


In the commit message you said that the behavior is unchanged, however 
this check is not part of the previous code.


Anyway, I don't think this check is necessary.



Sure, I'll remove the validation check from here.


+
+gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+
+return 0;
+}
+
  static int __init
  gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header

*header,

const unsigned long end)
@@ -1402,7 +1429,7 @@ static void __init gicv3_acpi_init(void)
  struct acpi_table_header *table;
  struct rdist_region *rdist_regs;
  acpi_status status;
-int count, i;
+int count;

  status = acpi_get_table(ACPI_SIG_MADT, 0, );

@@ -1433,37 +1460,27 @@ static void __init gicv3_acpi_init(void)
  if ( count <= 0 )
  panic("GICv3: No valid GICR entries exists");

-gicv3.rdist_count = count;
-
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
+if ( count > MAX_RDIST_COUNT )
  panic("GICv3: Number of redistributor regions is more than"
"%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);

-rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
+rdist_regs = xzalloc_array(struct rdist_region, count);
  if ( !rdist_regs )
  panic("GICv3: Failed to allocate memory for rdist regions\n");

-for ( i = 0; i < gicv3.rdist_count; i++ )
-{
-struct acpi_subtable_header *header;
-struct acpi_madt_generic_redistributor *gic_rdist;
-
-header =

acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,

- i);
-if ( !header )
-panic("GICv3: Can't get GICR entry");
-
-gic_rdist =
-   container_of(header, struct acpi_madt_generic_redistributor,

header);

-rdist_regs[i].base = gic_rdist->base_address;
-rdist_regs[i].size = gic_rdist->length;
-}
+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+ gic_acpi_parse_madt_redistributor,

table,

+ ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,

count);

Please use acpi_table_parse_madt here.



Sure.


+if ( count <= 0 )
+panic("GICv3: Can't get Redistributor entry");

  /* The vGIC code requires the region to be sorted */
  sort(rdist_regs, gicv3.rdist_count, sizeof(*rdist_regs),

cmp_rdist, NULL);


-gicv3.rdist_regions= rdist_regs;
-
  /* Collect CPU base addresses */
  count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct

acpi_table_madt),

gic_acpi_parse_madt_cpu, table,



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2 01/10] arm/gic-v3: Fix bug in function cmp_rdist()

2016-06-27 Thread Shanker Donthineni



On 06/27/2016 06:03 AM, Julien Grall wrote:

Hi Shanker,

On 26/06/16 18:48, Shanker Donthineni wrote:

The cmp_rdist() is always returning value zero irrespective of the
input Redistributor base addresses. Both the local variables 'l' and
'r' are pointing to the first argument 'a' causing the logical
expression 'l->base < r->base' always evaluated as false which is
wrong.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
  xen/arch/arm/gic-v3.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 8d3f149..b89c608 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1133,7 +1133,7 @@ static const hw_irq_controller

gicv3_guest_irq_type = {


  static int __init cmp_rdist(const void *a, const void *b)
  {
-const struct rdist_region *l = a, *r = a;
+const struct rdist_region *l = a, *r = b;


Thank you for spotting the error. The sorting was required because of 
the way the vGIC emulated the re-distributors. However, this code has 
been reworked and sorted array is not necessary anymore.


So I would directly drop the sorting here.


Thanks, I'll drop this patch in patchset-v3.



  /* We assume that re-distributor regions can never overlap */
  return ( l->base < r->base) ? -1 : 0;



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 00/10] Add support for parsing per CPU Redistributor entry

2016-06-26 Thread Shanker Donthineni
The current driver doesn't support parsing Redistributor entries that
are described in the MADT GICC table. Not all the GIC implementors
places the Redistributor regions in the always-on power domain. On
systems, the UEFI firmware should describe Redistributor base address
in the associated GIC CPU Interface (GICC) instead of GIC Redistributor
(GICR) table.

The maximum number of mmio handlers and struct vgic_rdist_region
that holds Redistributor addresses are allocated through a static
array with hardcoded size. I don't think this is the right approach
and is not scalable for implementing features like this. I have
decided to convert static to dynamic allocation based on comments
from the below link.

Patches #1 fixes the bug in the current driver.

Patches #2, #3 and #4 adds support for parsing not always-on power
domain Redistributor regions.

Patches #5, #6, #7, #8 and #10 refactors the code and allocates the
memory for mmio handlers and vgic_rdist_region based on the number of
Redistributors required for dom0/domU instead of hardcoded values.

Patch #9 changes the linear to binary search to avoid lookup overhead.

This pacthset is created on tip of Julien's branch 
http://xenbits.xen.org/gitweb/?p=people/julieng/xen-unstable.git;a=shortlog;h=refs/heads/irq-routing-acpi-rfc

Shanker Donthineni (10):
  arm/gic-v3: Fix bug in function cmp_rdist()
  arm/gic-v3: Do early GICD ioremap and clean up
  arm/gic-v3: Fold GICR subtable parsing into a new function
  arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable
  xen/arm: vgic: Use dynamic memory allocation for vgic_rdist_region
  arm/gic-v3: Remove an unused macro MAX_RDIST_COUNT
  arm: vgic: Split vgic_domain_init() functionality into two functions
  arm/io: Use separate memory allocation for mmio handlers
  xen/arm: io: Use binary search for mmio handler lookup
  arm/vgic: Change fixed number of mmio handlers to variable number

 xen/arch/arm/domain.c |  13 +++-
 xen/arch/arm/gic-v3.c | 158 --
 xen/arch/arm/io.c |  64 +++
 xen/arch/arm/vgic-v2.c|   7 ++
 xen/arch/arm/vgic-v3.c|  30 +++-
 xen/arch/arm/vgic.c   |  30 +---
 xen/include/asm-arm/domain.h  |   3 +-
 xen/include/asm-arm/gic.h |   2 +-
 xen/include/asm-arm/gic_v3_defs.h |   1 +
 xen/include/asm-arm/mmio.h|   6 +-
 xen/include/asm-arm/vgic.h|   3 +
 11 files changed, 241 insertions(+), 76 deletions(-)

-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 07/10] arm: vgic: Split vgic_domain_init() functionality into two functions

2016-06-26 Thread Shanker Donthineni
Separate the code logic that does the registration of vgic_v3/v2 ops
to a new fucntion domain_vgic_register(). The intention of this
separation is to record the required mmio count in vgic_v3/v2_init()
and pass it to function domain_io_init() in the later patch.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
  Moved registration of vgic_v3/v2 functionality to a new 
domain_vgic_register().

 xen/arch/arm/vgic.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 5df5f01..7627eff 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,19 +88,8 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-int domain_vgic_init(struct domain *d, unsigned int nr_spis)
+static int domain_vgic_register(struct domain *d)
 {
-int i;
-int ret;
-
-d->arch.vgic.ctlr = 0;
-
-/* Limit the number of virtual SPIs supported to (1020 - 32) = 988  */
-if ( nr_spis > (1020 - NR_LOCAL_IRQS) )
-return -EINVAL;
-
-d->arch.vgic.nr_spis = nr_spis;
-
 switch ( d->arch.vgic.version )
 {
 #ifdef CONFIG_HAS_GICV3
@@ -119,6 +108,26 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 return -ENODEV;
 }
 
+return 0;
+}
+
+int domain_vgic_init(struct domain *d, unsigned int nr_spis)
+{
+int i;
+int ret;
+
+d->arch.vgic.ctlr = 0;
+
+/* Limit the number of virtual SPIs supported to (1020 - 32) = 988  */
+if ( nr_spis > (1020 - NR_LOCAL_IRQS) )
+return -EINVAL;
+
+d->arch.vgic.nr_spis = nr_spis;
+
+ret = domain_vgic_register(d);
+if ( ret < 0)
+return ret;
+
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 10/10] arm/vgic: Change fixed number of mmio handlers to variable number

2016-06-26 Thread Shanker Donthineni
Record the number of mmio handlers that are required for vGICv3/2
in variable 'arch_domain.vgic.mmio_count' in vgic_v3/v2_init().
Augment this variable number to a fixed number MAX_IO_HANDLER and
pass it to domain_io_init() to allocate enough memory for handlers.

New code path:
 domain_vgic_register()
   count = MAX_IO_HANDLER + d->arch.vgic.mmio_count;
   domain_io_init(count)
 domain_vgic_init()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c| 11 +++
 xen/arch/arm/vgic-v2.c   |  1 +
 xen/arch/arm/vgic-v3.c   | 12 ++--
 xen/arch/arm/vgic.c  |  6 +-
 xen/include/asm-arm/domain.h |  1 +
 xen/include/asm-arm/vgic.h   |  1 +
 6 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 4010ff2..ebc12ac 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -550,10 +550,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -590,6 +586,13 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 goto fail;
 }
 
+if ( (rc = domain_vgic_register(d)) != 0 )
+goto fail;
+
+count = MAX_IO_HANDLER + d->arch.vgic.mmio_count;
+if ( (rc = domain_io_init(d, count)) != 0 )
+goto fail;
+
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index f5778e6..d5367b3 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -721,6 +721,7 @@ int vgic_v2_init(struct domain *d)
 return -ENODEV;
 }
 
+d->arch.vgic.mmio_count = 1; /* Only GICD region */
 register_vgic_ops(d, _v2_ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index e877e9e..472deac 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1391,14 +1391,19 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
 return 0;
 }
 
+static inline unsigned int vgic_v3_rdist_count(struct domain *d)
+{
+return is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
+   GUEST_GICV3_RDIST_REGIONS;
+}
+
 static int vgic_v3_domain_init(struct domain *d)
 {
 struct vgic_rdist_region *rdist_regions;
 int rdist_count, i;
 
 /* Allocate memory for Re-distributor regions */
-rdist_count = is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
-   GUEST_GICV3_RDIST_REGIONS;
+rdist_count = vgic_v3_rdist_count(d);
 
 rdist_regions = xzalloc_array(struct vgic_rdist_region, rdist_count);
 if ( !rdist_regions )
@@ -1504,6 +1509,9 @@ int vgic_v3_init(struct domain *d)
 return -ENODEV;
 }
 
+/* GICD region + number of Re-distributors */
+d->arch.vgic.mmio_count = vgic_v3_rdist_count(d) + 1;
+
 register_vgic_ops(d, _ops);
 
 return 0;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 7627eff..0658bfc 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,7 +88,7 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
-static int domain_vgic_register(struct domain *d)
+int domain_vgic_register(struct domain *d)
 {
 switch ( d->arch.vgic.version )
 {
@@ -124,10 +124,6 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 
 d->arch.vgic.nr_spis = nr_spis;
 
-ret = domain_vgic_register(d);
-if ( ret < 0)
-return ret;
-
 spin_lock_init(>arch.vgic.lock);
 
 d->arch.vgic.shared_irqs =
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 29346c6..b205461 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -111,6 +111,7 @@ struct arch_domain
 int nr_regions; /* Number of rdist regions */
 uint32_t rdist_stride;  /* Re-Distributor stride */
 #endif
+uint32_t mmio_count;/* Number of mmio handlers */
 } vgic;
 
 struct vuart {
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index fbb763a..1ce441c 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -307,6 +307,7 @@ extern void register_vgic_ops(struct domain *d, const 
struct vgic_ops *ops);
 int vgic_v2_init(struct domain *d);
 int vgic_v3_init(struct domain *d);
 
+extern int domain_vgic_register(struct domain *d);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Cen

[Xen-devel] [PATCH V2 03/10] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-26 Thread Shanker Donthineni
Add a new function for parsing GICR subtable and move the code
that is specific to GICR table to new function without changing
the function gicv3_acpi_init() behavior.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
  Removed the unnecessary GICR ioremap operation inside GICR table parse code.

 xen/arch/arm/gic-v3.c | 61 ---
 1 file changed, 39 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 542c4f3..0471fea 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1282,6 +1282,14 @@ static int gicv3_iomem_deny_access(const struct domain 
*d)
 }
 
 #ifdef CONFIG_ACPI
+static void __init gic_acpi_add_rdist_region(u64 base_addr, u32 size)
+{
+unsigned int idx = gicv3.rdist_count++;
+
+gicv3.rdist_regions[idx].base = base_addr;
+gicv3.rdist_regions[idx].size = size;
+}
+
 static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
 {
 struct acpi_subtable_header *header;
@@ -1387,6 +1395,25 @@ gic_acpi_parse_madt_distributor(struct 
acpi_subtable_header *header,
 
 return 0;
 }
+
+static int __init
+gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_redistributor *rdist;
+
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
+
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;
+
+gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+
+return 0;
+}
+
 static int __init
 gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header *header,
 const unsigned long end)
@@ -1402,7 +1429,7 @@ static void __init gicv3_acpi_init(void)
 struct acpi_table_header *table;
 struct rdist_region *rdist_regs;
 acpi_status status;
-int count, i;
+int count;
 
 status = acpi_get_table(ACPI_SIG_MADT, 0, );
 
@@ -1433,37 +1460,27 @@ static void __init gicv3_acpi_init(void)
 if ( count <= 0 )
 panic("GICv3: No valid GICR entries exists");
 
-gicv3.rdist_count = count;
-
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
+if ( count > MAX_RDIST_COUNT )
 panic("GICv3: Number of redistributor regions is more than"
   "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
 
-rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
+rdist_regs = xzalloc_array(struct rdist_region, count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
 
-for ( i = 0; i < gicv3.rdist_count; i++ )
-{
-struct acpi_subtable_header *header;
-struct acpi_madt_generic_redistributor *gic_rdist;
-
-header = 
acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
-   i);
-if ( !header )
-panic("GICv3: Can't get GICR entry");
-
-gic_rdist =
-   container_of(header, struct acpi_madt_generic_redistributor, 
header);
-rdist_regs[i].base = gic_rdist->base_address;
-rdist_regs[i].size = gic_rdist->length;
-}
+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+   gic_acpi_parse_madt_redistributor, table,
+   ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, count);
+if ( count <= 0 )
+panic("GICv3: Can't get Redistributor entry");
 
 /* The vGIC code requires the region to be sorted */
 sort(rdist_regs, gicv3.rdist_count, sizeof(*rdist_regs), cmp_rdist, NULL);
 
-gicv3.rdist_regions= rdist_regs;
-
 /* Collect CPU base addresses */
 count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
gic_acpi_parse_madt_cpu, table,
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 05/10] xen/arm: vgic: Use dynamic memory allocation for vgic_rdist_region

2016-06-26 Thread Shanker Donthineni
The number of Re-distributor regions allowed for dom0 is hardcoded
to a compile time macro MAX_RDIST_COUNT which is 4. On some systems,
especially latest server chips might have more than 4 redistributors.
Either we have to increase MAX_RDIST_COUNT to a bigger number or
allocate memory based on number of redistributors that are found in
MADT table. In the worst case scenario, the macro MAX_RDIST_COUNT
should be equal to CONFIG_NR_CPUS in order to support per CPU
Redistributors.

Increasing MAX_RDIST_COUNT has side effect, it blows 'struct domain'
size and hits BUILD_BUG_ON() in domain build code path.

struct domain *alloc_domain_struct(void)
{
struct domain *d;
BUILD_BUG_ON(sizeof(*d) > PAGE_SIZE);
d = alloc_xenheap_pages(0, 0);
if ( d == NULL )
return NULL;
...

This patch uses the second approach to fix the BUILD_BUG().

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
  Keep 'struct vgic_rdist_region' definition inside 'struct arch_domain'.

 xen/arch/arm/vgic-v2.c   |  6 ++
 xen/arch/arm/vgic-v3.c   | 22 +++---
 xen/arch/arm/vgic.c  |  1 +
 xen/include/asm-arm/domain.h |  2 +-
 xen/include/asm-arm/vgic.h   |  2 ++
 5 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 9adb4a9..f5778e6 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -699,9 +699,15 @@ static int vgic_v2_domain_init(struct domain *d)
 return 0;
 }
 
+static void vgic_v2_domain_free(struct domain *d)
+{
+/* Nothing to be cleanup for this driver */
+}
+
 static const struct vgic_ops vgic_v2_ops = {
 .vcpu_init   = vgic_v2_vcpu_init,
 .domain_init = vgic_v2_domain_init,
+.domain_free = vgic_v2_domain_free,
 .max_vcpus = 8,
 };
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index b37a7c0..e877e9e 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1393,7 +1393,19 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
 
 static int vgic_v3_domain_init(struct domain *d)
 {
-int i;
+struct vgic_rdist_region *rdist_regions;
+int rdist_count, i;
+
+/* Allocate memory for Re-distributor regions */
+rdist_count = is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
+   GUEST_GICV3_RDIST_REGIONS;
+
+rdist_regions = xzalloc_array(struct vgic_rdist_region, rdist_count);
+if ( !rdist_regions )
+return -ENOMEM;
+
+d->arch.vgic.nr_regions = rdist_count;
+d->arch.vgic.rdist_regions = rdist_regions;
 
 /*
  * Domain 0 gets the hardware address.
@@ -1426,7 +1438,6 @@ static int vgic_v3_domain_init(struct domain *d)
 
 first_cpu += size / d->arch.vgic.rdist_stride;
 }
-d->arch.vgic.nr_regions = vgic_v3_hw.nr_rdist_regions;
 }
 else
 {
@@ -1435,7 +1446,6 @@ static int vgic_v3_domain_init(struct domain *d)
 /* XXX: Only one Re-distributor region mapped for the guest */
 BUILD_BUG_ON(GUEST_GICV3_RDIST_REGIONS != 1);
 
-d->arch.vgic.nr_regions = GUEST_GICV3_RDIST_REGIONS;
 d->arch.vgic.rdist_stride = GUEST_GICV3_RDIST_STRIDE;
 
 /* The first redistributor should contain enough space for all CPUs */
@@ -1467,9 +1477,15 @@ static int vgic_v3_domain_init(struct domain *d)
 return 0;
 }
 
+static void vgic_v3_domain_free(struct domain *d)
+{
+xfree(d->arch.vgic.rdist_regions);
+}
+
 static const struct vgic_ops v3_ops = {
 .vcpu_init   = vgic_v3_vcpu_init,
 .domain_init = vgic_v3_domain_init,
+.domain_free = vgic_v3_domain_free,
 .emulate_sysreg  = vgic_v3_emulate_sysreg,
 /*
  * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 3e1c572..5df5f01 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -177,6 +177,7 @@ void domain_vgic_free(struct domain *d)
 }
 }
 
+d->arch.vgic.handler->domain_free(d);
 xfree(d->arch.vgic.shared_irqs);
 xfree(d->arch.vgic.pending_irqs);
 xfree(d->arch.vgic.allocated_irqs);
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 370cdeb..29346c6 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -107,7 +107,7 @@ struct arch_domain
 paddr_t base;   /* Base address */
 paddr_t size;   /* Size */
 unsigned int first_cpu; /* First CPU handled */
-} rdist_regions[MAX_RDIST_COUNT];
+} *rdist_regions;
 int nr_regions; /* Number of rdist regions */
 uint32_t rdist_stride;  /* Re-Distributor stride */
 #endif
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index a2fccc0..fbb763a 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -128,6 +128,8 @@ struct

[Xen-devel] [PATCH V2 04/10] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-26 Thread Shanker Donthineni
The redistributor address can be specified either as part of GICC or
GICR subtable depending on the power domain. The current driver
doesn't support parsing redistributor entry that is defined in GICC
subtable. The GIC CPU subtable entry holds the associated Redistributor
base address if it is not on always-on power domain.

The per CPU Redistributor size is not defined in ACPI specification.
Set it's size to SZ_256K if the GIC hardware is capable of Direct
Virtual LPI Injection feature otherwise SZ_128K.

This patch adds necessary code to handle both types of Redistributors
base addresses.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes since v1:
  Edited commit text and fixed white spaces.
  Added a new function for parsing per CPU Redistributor entry.

 xen/arch/arm/gic-v3.c | 84 ++-
 xen/include/asm-arm/gic.h |  1 +
 xen/include/asm-arm/gic_v3_defs.h |  1 +
 3 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 0471fea..3977244 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -659,6 +659,10 @@ static int __init gicv3_populate_rdist(void)
 smp_processor_id(), i, ptr);
 return 0;
 }
+
+if ( gicv3.rdist_regions[i].single_rdist )
+break;
+
 if ( gicv3.rdist_stride )
 ptr += gicv3.rdist_stride;
 else
@@ -1282,14 +1286,21 @@ static int gicv3_iomem_deny_access(const struct domain 
*d)
 }
 
 #ifdef CONFIG_ACPI
-static void __init gic_acpi_add_rdist_region(u64 base_addr, u32 size)
+static void __init
+gic_acpi_add_rdist_region(u64 base_addr, u32 size, bool single_rdist)
 {
 unsigned int idx = gicv3.rdist_count++;
 
+gicv3.rdist_regions[idx].single_rdist = single_rdist;
 gicv3.rdist_regions[idx].base = base_addr;
 gicv3.rdist_regions[idx].size = size;
 }
 
+static inline bool gic_dist_supports_dvis(void)
+{
+return !!(readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_DVIS);
+}
+
 static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
 {
 struct acpi_subtable_header *header;
@@ -1397,6 +1408,42 @@ gic_acpi_parse_madt_distributor(struct 
acpi_subtable_header *header,
 }
 
 static int __init
+gic_acpi_parse_cpu_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *processor;
+u32 size;
+
+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(processor, end) )
+return -EINVAL;
+
+if ( !processor->gicr_base_address )
+return -EINVAL;
+
+if ( processor->flags & ACPI_MADT_ENABLED )
+{
+size = gic_dist_supports_dvis() ? 4 * SZ_64K : 2 * SZ_64K;
+gic_acpi_add_rdist_region(processor->gicr_base_address, size, true);
+}
+
+return 0;
+}
+
+static int __init
+gic_acpi_get_madt_cpu_num(struct acpi_subtable_header *header,
+const unsigned long end)
+{
+struct acpi_madt_generic_interrupt *cpuif;
+
+cpuif = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(cpuif, end) || !cpuif->gicr_base_address )
+return -EINVAL;
+
+return 0;
+}
+
+static int __init
 gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
   const unsigned long end)
 {
@@ -1409,7 +1456,7 @@ gic_acpi_parse_madt_redistributor(struct 
acpi_subtable_header *header,
 if ( !rdist->base_address || !rdist->length )
 return -EINVAL;
 
-gic_acpi_add_rdist_region(rdist->base_address, rdist->length);
+gic_acpi_add_rdist_region(rdist->base_address, rdist->length, false);
 
 return 0;
 }
@@ -1428,6 +1475,7 @@ static void __init gicv3_acpi_init(void)
 {
 struct acpi_table_header *table;
 struct rdist_region *rdist_regs;
+bool gicr_table = true;
 acpi_status status;
 int count;
 
@@ -1457,8 +1505,18 @@ static void __init gicv3_acpi_init(void)
 count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
gic_acpi_get_madt_redistributor_num, table,
ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0);
-if ( count <= 0 )
-panic("GICv3: No valid GICR entries exists");
+
+/* Count the total number of CPU interface entries */
+if (count <= 0) {
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+   gic_acpi_get_madt_cpu_num,
+   table, ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
+if (count <= 0)
+panic("GICv3: No valid GICR entries exists");
+
+gicr_table = false;
+}
 
 if ( count > MAX_RDIST

[Xen-devel] [PATCH V2 09/10] xen/arm: io: Use binary search for mmio handler lookup

2016-06-26 Thread Shanker Donthineni
As the number of I/O handlers increase, the overhead associated with
linear lookup also increases. The system might have maximum of 144
(assuming CONFIG_NR_CPUS=128) mmio handlers. In worst case scenario,
it would require 144 iterations for finding a matching handler. Now
it is time for us to change from linear (complexity O(n)) to a binary
search (complexity O(log n) for reducing mmio handler lookup overhead.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/io.c | 50 +++---
 1 file changed, 39 insertions(+), 11 deletions(-)

diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index a5b2c2d..abf49fb 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -70,23 +71,38 @@ static int handle_write(const struct mmio_handler *handler, 
struct vcpu *v,
handler->priv);
 }
 
-int handle_mmio(mmio_info_t *info)
+const struct mmio_handler *find_mmio_handler(struct vcpu *v, paddr_t addr)
 {
-struct vcpu *v = current;
-int i;
-const struct mmio_handler *handler = NULL;
 const struct vmmio *vmmio = >domain->arch.vmmio;
+const struct mmio_handler *handler = vmmio->handlers;
+unsigned int eidx = vmmio->num_entries;
+unsigned int midx = eidx / 2;
+unsigned int sidx = 0;
 
-for ( i = 0; i < vmmio->num_entries; i++ )
+/* Do binary search for matching mmio handler */
+while ( sidx != midx )
 {
-handler = >handlers[i];
-
-if ( (info->gpa >= handler->addr) &&
- (info->gpa < (handler->addr + handler->size)) )
-break;
+if ( addr < handler[midx].addr )
+eidx = midx;
+else
+sidx = midx;
+midx = sidx + (eidx - sidx) / 2;
 }
 
-if ( i == vmmio->num_entries )
+if ( (addr >= handler[sidx].addr) &&
+ (addr < (handler[sidx].addr + handler[sidx].size)) )
+return handler + sidx;
+
+return NULL;
+}
+
+int handle_mmio(mmio_info_t *info)
+{
+const struct mmio_handler *handler;
+struct vcpu *v = current;
+
+handler = find_mmio_handler(v, info->gpa);
+if ( !handler )
 return 0;
 
 if ( info->dabt.write )
@@ -95,6 +111,14 @@ int handle_mmio(mmio_info_t *info)
 return handle_read(handler, v, info);
 }
 
+static int cmp_mmio_handler(const void *key, const void *elem)
+{
+const struct mmio_handler *handler0 = key;
+const struct mmio_handler *handler1 = elem;
+
+return (handler0->addr < handler1->addr) ? -1 : 0;
+}
+
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv)
@@ -122,6 +146,10 @@ void register_mmio_handler(struct domain *d,
 
 vmmio->num_entries++;
 
+/* Sort mmio handlers in ascending order based on base address */
+sort(vmmio->handlers, vmmio->num_entries, sizeof(struct mmio_handler),
+ cmp_mmio_handler, NULL);
+
 spin_unlock(>lock);
 }
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 06/10] arm/gic-v3: Remove an unused macro MAX_RDIST_COUNT

2016-06-26 Thread Shanker Donthineni
The macro MAX_RDIST_COUNT is not being used after converting code
to handle number of redistributor dynamically. So remove it from
header file and the two other panic() messages that are not valid
anymore.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/gic-v3.c | 8 
 xen/include/asm-arm/gic.h | 1 -
 2 files changed, 9 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 3977244..87f4ecf 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1200,10 +1200,6 @@ static void __init gicv3_dt_init(void)
 _count) )
 gicv3.rdist_count = 1;
 
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
-panic("GICv3: Number of redistributor regions is more than"
-  "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
-
 rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
@@ -1518,10 +1514,6 @@ static void __init gicv3_acpi_init(void)
 gicr_table = false;
 }
 
-if ( count > MAX_RDIST_COUNT )
-panic("GICv3: Number of redistributor regions is more than"
-  "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
-
 rdist_regs = xzalloc_array(struct rdist_region, count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index fedf1fa..db7b2d0 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -20,7 +20,6 @@
 
 #define NR_GIC_LOCAL_IRQS  NR_LOCAL_IRQS
 #define NR_GIC_SGI 16
-#define MAX_RDIST_COUNT4
 
 #define GICD_CTLR   (0x000)
 #define GICD_TYPER  (0x004)
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 08/10] arm/io: Use separate memory allocation for mmio handlers

2016-06-26 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 14 --
 xen/include/asm-arm/mmio.h |  6 --
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 1365b4a..4010ff2 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -527,7 +527,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -550,7 +550,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -644,6 +645,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 0156755..a5b2c2d 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -102,7 +102,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 spin_lock(>lock);
 
@@ -125,14 +125,24 @@ void register_mmio_handler(struct domain *d,
 spin_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
spin_lock_init(>arch.vmmio.lock);
d->arch.vmmio.num_entries = 0;
 
+   d->arch.vmmio.max_num_entries = max_count;
+   d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+   if ( !d->arch.vmmio.handlers )
+   return -ENOMEM;
+
return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index da1cc2e..276b263 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -51,15 +51,17 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 spinlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 01/10] arm/gic-v3: Fix bug in function cmp_rdist()

2016-06-26 Thread Shanker Donthineni
The cmp_rdist() is always returning value zero irrespective of the
input Redistributor base addresses. Both the local variables 'l' and
'r' are pointing to the first argument 'a' causing the logical
expression 'l->base < r->base' always evaluated as false which is
wrong.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/gic-v3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 8d3f149..b89c608 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1133,7 +1133,7 @@ static const hw_irq_controller gicv3_guest_irq_type = {
 
 static int __init cmp_rdist(const void *a, const void *b)
 {
-const struct rdist_region *l = a, *r = a;
+const struct rdist_region *l = a, *r = b;
 
 /* We assume that re-distributor regions can never overlap */
 return ( l->base < r->base) ? -1 : 0;
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V2 02/10] arm/gic-v3: Do early GICD ioremap and clean up

2016-06-26 Thread Shanker Donthineni
For ACPI based XEN boot, the GICD region needs to be accessed inside
the function gicv3_acpi_init() in later pacth. There is a duplicate
panic() message, one in the DTS probe and second one in the ACPI probe
path. For these two reasons, move the code that validates the GICD base
address and does the region ioremap to a separate function. The
following pacth accesses the GICD region inside gicv3_acpi_init() for
finding per CPU Redistributor size.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
Changes sicne v1:
  Edited commit text.

 xen/arch/arm/gic-v3.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index b89c608..542c4f3 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1169,6 +1169,17 @@ static void __init gicv3_init_v2(void)
 vgic_v2_setup_hw(dbase, cbase, csize, vbase, 0);
 }
 
+static void __init gicv3_ioremap_distributor(paddr_t dist_paddr)
+{
+if ( dist_paddr & ~PAGE_MASK )
+panic("GICv3:  Found unaligned distributor address %"PRIpaddr"",
+  dbase);
+
+gicv3.map_dbase = ioremap_nocache(dist_paddr, SZ_64K);
+if ( !gicv3.map_dbase )
+panic("GICv3: Failed to ioremap for GIC distributor\n");
+}
+
 static void __init gicv3_dt_init(void)
 {
 struct rdist_region *rdist_regs;
@@ -1179,9 +1190,7 @@ static void __init gicv3_dt_init(void)
 if ( res )
 panic("GICv3: Cannot find a valid distributor address");
 
-if ( (dbase & ~PAGE_MASK) )
-panic("GICv3:  Found unaligned distributor address %"PRIpaddr"",
-  dbase);
+gicv3_ioremap_distributor(dbase);
 
 if ( !dt_property_read_u32(node, "#redistributor-regions",
 _count) )
@@ -1415,9 +1424,7 @@ static void __init gicv3_acpi_init(void)
 if ( count <= 0 )
 panic("GICv3: No valid GICD entries exists");
 
-if ( (dbase & ~PAGE_MASK) )
-panic("GICv3: Found unaligned distributor address %"PRIpaddr"",
-  dbase);
+gicv3_ioremap_distributor(dbase);
 
 /* Get number of redistributor */
 count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
@@ -1491,10 +1498,6 @@ static int __init gicv3_init(void)
 else
 gicv3_acpi_init();
 
-gicv3.map_dbase = ioremap_nocache(dbase, SZ_64K);
-if ( !gicv3.map_dbase )
-panic("GICv3: Failed to ioremap for GIC distributor\n");
-
 reg = readl_relaxed(GICD + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
 if ( reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4 )
  panic("GICv3: no distributor detected\n");
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 6/8] arm: vgic: Split vgic_domain_init() functionality into two functions

2016-06-21 Thread Shanker Donthineni

Hi Julien,

On 06/21/2016 09:48 AM, Julien Grall wrote:



On 21/06/16 15:36, Shanker Donthineni wrote:



On 06/21/2016 05:49 AM, Julien Grall wrote:

Hello Shanker,

On 19/06/16 00:45, Shanker Donthineni wrote:

Split code that installs mmio handlers for GICD and Re-distributor
regions to a new function. The intension of this separation is to 
defer

steps that registers vgic_v2/v3 mmio handlers.


Looking at this patch and the follow-up ones, I don't think this is
the right way to go. You differ the registration of the IO handlers
just because you are unable to find the size of the handlers array.


Is there any better approach?


Possibly using a different data structure.


I am wondering if the array for the handlers is the best solution
here. On another side, it would be possible to find the maximum of
handlers before hand.


The purpose of this change is to limit size of 'struct domain' less than
PAGE_SIZE. I can think of second approach split vgic_init() into two
stages, one for vgic registration and the second one for vgic_init().
This also requires a few lines of code changes to vgic_v2/v3_init() and
vgic_init().


I am fine as long as vgic_register_ does not do more than counting the 
number of IO handlers. You could re-use vgic_init_v{2,3} for this 
purpose.


The way we are doing vgic_init() initialization has to be cleaned-up and 
rearrange a few lines of code for retrieving the number mmio handlers 
that are required dom0/domU domain.



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 6/8] arm: vgic: Split vgic_domain_init() functionality into two functions

2016-06-21 Thread Shanker Donthineni



On 06/21/2016 05:49 AM, Julien Grall wrote:

Hello Shanker,

On 19/06/16 00:45, Shanker Donthineni wrote:

Split code that installs mmio handlers for GICD and Re-distributor
regions to a new function. The intension of this separation is to defer
steps that registers vgic_v2/v3 mmio handlers.


Looking at this patch and the follow-up ones, I don't think this is 
the right way to go. You differ the registration of the IO handlers 
just because you are unable to find the size of the handlers array.



Is there any better approach?

I am wondering if the array for the handlers is the best solution 
here. On another side, it would be possible to find the maximum of 
handlers before hand.


The purpose of this change is to limit size of 'struct domain' less than 
PAGE_SIZE. I can think of second approach split vgic_init() into two 
stages, one for vgic registration and the second one for vgic_init(). 
This also requires a few lines of code changes to vgic_v2/v3_init() and 
vgic_init().


int arch_domain_create(struct domain *d, unsigned int domcr_flags,
   struct xen_arch_domainconfig *config)
   ...
   domain_vgic_register(d));

   domain_io_init(d, mmio_count);

   domain_vgic_init(d, config->nr_spis));


diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 5df5f01..5b39e0d 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -151,9 +151,12 @@ int domain_vgic_init(struct domain *d, unsigned int

nr_spis)

  for ( i = 0; i < NR_GIC_SGI; i++ )
  set_bit(i, d->arch.vgic.allocated_irqs);

+d->arch.vgic.handler->domain_register_mmio(d);
+
  return 0;
  }

+


Spurious change.


  void register_vgic_ops(struct domain *d, const struct vgic_ops *ops)
  {
 d->arch.vgic.handler = ops;
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index fbb763a..8fe65b4 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -132,6 +132,8 @@ struct vgic_ops {
  void (*domain_free)(struct domain *d);
  /* vGIC sysreg emulation */
  int (*emulate_sysreg)(struct cpu_user_regs *regs, union hsr hsr);
+/* Register mmio handlers */
+void (*domain_register_mmio)(struct domain *d);
  /* Maximum number of vCPU supported */
  const unsigned int max_vcpus;
  };



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 0/8] Add support for parsing per CPU Redistributor entry

2016-06-21 Thread Shanker Donthineni



On 06/21/2016 08:50 AM, Julien Grall wrote:



On 21/06/16 14:37, Shanker Donthineni wrote:

On 06/21/2016 04:28 AM, Julien Grall wrote:

On 19/06/16 00:45, Shanker Donthineni wrote:

The current driver doesn't support parsing Redistributor entries that
are described in the MADT GICC table. Not all the GIC implementors
places the Redistributor regions in the always-on power domain. On
systems, the UEFI firmware should describe Redistributor base address
in the associated GIC CPU Interface (GICC) instead of GIC

Redistributor

(GICR) table.

The maximum number of mmio handlers and struct vgic_rdist_region
that holds Redistributor addresses are allocated through a static
array with hardcoded size. I don't think this is the right approach
and is not scalable for implementing features like this. I have
decided to convert static to dynamic allocation based on comments
from the below link.

https://patchwork.kernel.org/patch/9163435/


You addressed only one part of my comment. This series increases the
number of I/O handlers but the lookup is still linear (see handle_mmio
in arch/arm/io.c).


I agree with you, we need to bring binary search algorithm similar to
Linux KVM code. I want to keep it this change outside of this patchset.


This should be a prerequisite of this series then, not a follow-up.

For the  functionality and correctness purpose we don't need this change 
immediately.
We are not able to boot XEN on Qualcomm Technologies because of not 
supporting

GICC table parsing for GICR address.

I am okay to wait for my patchset if someone adding bseach look ups for 
mmio handlers.



Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 2/8] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-21 Thread Shanker Donthineni



On 06/21/2016 05:17 AM, Julien Grall wrote:

Hello Shanker,

On 19/06/16 00:45, Shanker Donthineni wrote:

Add a new function for parsing GICR subtable and move the code
that is specific to GICR table to new function without changing
the function gicv3_acpi_init() behavior.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
  xen/arch/arm/gic-v3.c | 64

+--

  1 file changed, 42 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index ab1f380..af12ebc 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1387,6 +1387,36 @@ gic_acpi_parse_madt_distributor(struct

acpi_subtable_header *header,


  return 0;
  }
+
+static int __init
+gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_redistributor *rdist;
+struct rdist_region *region;
+
+region = gicv3.rdist_regions + gicv3.rdist_count;
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
+
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;
+
+region->base = rdist->base_address;
+region->size = rdist->length;
+
+region->map_base = ioremap_nocache(region->base, region->size);


In the commit message you said there is no functional change, however 
the remapping is not part of gicv3_acpi_init. So why did you add this 
line here?


Thanks for catching coding bug, it was my mistake and this code should 
not be here.

+if ( !region->map_base )
+{
+printk("Unable to map GICR registers\n");
+return -ENOMEM;
+}
+gicv3.rdist_count++;
+
+return 0;
+}
+


[...]

Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 3/8] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-21 Thread Shanker Donthineni



On 06/21/2016 05:16 AM, Julien Grall wrote:

Hello Shanker,

On 19/06/16 00:45, Shanker Donthineni wrote:

The redistributor address can be specified either as part of GICC or
GICR subtable depending on the power domain. The current driver
doesn't support parsing redistributor entry that is defined in GICC
subtable. The GIC CPU subtable entry holds the associated Redistributor
base address if it is not on always-on power domain.

This patch adds necessary code to handle both types of Redistributors
base addresses.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
  xen/arch/arm/gic-v3.c | 97

---

  xen/include/asm-arm/gic.h |  2 +
  xen/include/asm-arm/gic_v3_defs.h |  1 +
  3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index af12ebc..42cf848 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -659,6 +659,10 @@ static int __init gicv3_populate_rdist(void)
  smp_processor_id(), i, ptr);
  return 0;
  }
+
+if ( gicv3.rdist_regions[i].single_rdist )
+break;
+
  if ( gicv3.rdist_stride )
  ptr += gicv3.rdist_stride;
  else
@@ -1282,6 +1286,11 @@ static int gicv3_iomem_deny_access(const struct

domain *d)

  }

  #ifdef CONFIG_ACPI
+static bool gic_dist_supports_dvis(void)


static inline and please use bool_t here.


Still learning XEN coding style, I'll fix it.

+{
+return !!(readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_DVIS);
+}
+
  static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
  {
  struct acpi_subtable_header *header;
@@ -1393,18 +1402,39 @@ gic_acpi_parse_madt_redistributor(struct

acpi_subtable_header *header,

const unsigned long end)
  {
  struct acpi_madt_generic_redistributor *rdist;
+struct acpi_madt_generic_interrupt *processor;
  struct rdist_region *region;

  region = gicv3.rdist_regions + gicv3.rdist_count;
-rdist = (struct acpi_madt_generic_redistributor *)header;
-if ( BAD_MADT_ENTRY(rdist, end) )
-return -EINVAL;
+if ( header->type == ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR )
+{
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;

-if ( !rdist->base_address || !rdist->length )
-return -EINVAL;
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;
+
+region->base = rdist->base_address;
+region->size = rdist->length;
+}
+else if ( header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT )
+{


Parsing the GICC and the redistributor is quite different. I would 
much prefer a function for parsing each table and an helper to add a 
new redistributor.



 I'll do.

+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(processor, end) )
+return -EINVAL;
+
+if ( !(processor->flags & ACPI_MADT_ENABLED) )
+return 0;
+
+if ( !processor->gicr_base_address )
+return -EINVAL;
+
+region->base = processor->gicr_base_address;
+region->size = gic_dist_supports_dvis() ? SZ_256K : SZ_128K;


Please explain in the commit message how you find the size. I would 
also prefer if you use (4 x SZ_64K) and (2 * SZ_64K) as we do in

populate_rdist.


+region->single_rdist = true;


The indentation looks wrong.


+   }





-region->base = rdist->base_address;
-region->size = rdist->length;

  region->map_base = ioremap_nocache(region->base, region->size);
  if ( !region->map_base )
@@ -1412,6 +1442,7 @@ gic_acpi_parse_madt_redistributor(struct

acpi_subtable_header *header,

  printk("Unable to map GICR registers\n");
  return -ENOMEM;
  }
+


Spurious change.


  gicv3.rdist_count++;

  return 0;
@@ -1421,9 +1452,22 @@ static int __init
  gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header

*header,

const unsigned long end)
  {
-/* Nothing to do here since it only wants to get the number of GIC
- * redistributors.
- */
+struct acpi_madt_generic_redistributor *rdist;
+struct acpi_madt_generic_interrupt *cpuif;
+
+if ( header->type == ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR )
+{
+ rdist = (struct acpi_madt_generic_redistributor *)header;
+ if ( BAD_MADT_ENTRY(rdist, end) || !rdist->base_address )
+ return -EINVAL;
+}
+else if ( header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT )
+{
+ cpuif = (struct acpi_madt_generic_interrupt *)header;
+ if ( BAD_MADT_ENTRY(cpuif, end) || !cpuif->gicr_base_address )
+ return -EINVAL;
+}
+


Ditto for the parsing.


   

Re: [Xen-devel] [PATCH 0/8] Add support for parsing per CPU Redistributor entry

2016-06-21 Thread Shanker Donthineni



On 06/21/2016 04:28 AM, Julien Grall wrote:

Hello Shanker,

On 19/06/16 00:45, Shanker Donthineni wrote:

The current driver doesn't support parsing Redistributor entries that
are described in the MADT GICC table. Not all the GIC implementors
places the Redistributor regions in the always-on power domain. On
systems, the UEFI firmware should describe Redistributor base address
in the associated GIC CPU Interface (GICC) instead of GIC Redistributor
(GICR) table.

The maximum number of mmio handlers and struct vgic_rdist_region
that holds Redistributor addresses are allocated through a static
array with hardcoded size. I don't think this is the right approach
and is not scalable for implementing features like this. I have
decided to convert static to dynamic allocation based on comments
from the below link.

https://patchwork.kernel.org/patch/9163435/


You addressed only one part of my comment. This series increases the 
number of I/O handlers but the lookup is still linear (see handle_mmio 
in arch/arm/io.c).


I agree with you, we need to bring binary search algorithm similar to 
Linux KVM code. I want to keep it this change outside of this patchset.
After this series, the maximum number of I/O handlers is 160. So in 
the worst case, we have to do 160 iterations before finding an handler 
or concluding the I/O cannot be emulated.


Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 2/8] arm/gic-v3: Fold GICR subtable parsing into a new function

2016-06-18 Thread Shanker Donthineni
Add a new function for parsing GICR subtable and move the code
that is specific to GICR table to new function without changing
the function gicv3_acpi_init() behavior.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/gic-v3.c | 64 +--
 1 file changed, 42 insertions(+), 22 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index ab1f380..af12ebc 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1387,6 +1387,36 @@ gic_acpi_parse_madt_distributor(struct 
acpi_subtable_header *header,
 
 return 0;
 }
+
+static int __init
+gic_acpi_parse_madt_redistributor(struct acpi_subtable_header *header,
+  const unsigned long end)
+{
+struct acpi_madt_generic_redistributor *rdist;
+struct rdist_region *region;
+
+region = gicv3.rdist_regions + gicv3.rdist_count;
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
+
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;
+
+region->base = rdist->base_address;
+region->size = rdist->length;
+
+region->map_base = ioremap_nocache(region->base, region->size);
+if ( !region->map_base )
+{
+printk("Unable to map GICR registers\n");
+return -ENOMEM;
+}
+gicv3.rdist_count++;
+
+return 0;
+}
+
 static int __init
 gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header *header,
 const unsigned long end)
@@ -1402,7 +1432,7 @@ static void __init gicv3_acpi_init(void)
 struct acpi_table_header *table;
 struct rdist_region *rdist_regs;
 acpi_status status;
-int count, i;
+int count;
 
 status = acpi_get_table(ACPI_SIG_MADT, 0, );
 
@@ -1433,37 +1463,27 @@ static void __init gicv3_acpi_init(void)
 if ( count <= 0 )
 panic("GICv3: No valid GICR entries exists");
 
-gicv3.rdist_count = count;
-
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
+if ( count > MAX_RDIST_COUNT )
 panic("GICv3: Number of redistributor regions is more than"
   "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
 
-rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
+rdist_regs = xzalloc_array(struct rdist_region, count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
 
-for ( i = 0; i < gicv3.rdist_count; i++ )
-{
-struct acpi_subtable_header *header;
-struct acpi_madt_generic_redistributor *gic_rdist;
-
-header = 
acpi_table_get_entry_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
-   i);
-if ( !header )
-panic("GICv3: Can't get GICR entry");
-
-gic_rdist =
-   container_of(header, struct acpi_madt_generic_redistributor, 
header);
-rdist_regs[i].base = gic_rdist->base_address;
-rdist_regs[i].size = gic_rdist->length;
-}
+gicv3.rdist_regions = rdist_regs;
+
+/* Parse always-on power domain Re-distributor entries */
+count = acpi_parse_entries(ACPI_SIG_MADT,
+   sizeof(struct acpi_table_madt),
+   gic_acpi_parse_madt_redistributor, table,
+   ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, count);
+if ( count <= 0 )
+panic("GICv3: Can't get Redistributor entry");
 
 /* The vGIC code requires the region to be sorted */
 sort(rdist_regs, gicv3.rdist_count, sizeof(*rdist_regs), cmp_rdist, NULL);
 
-gicv3.rdist_regions= rdist_regs;
-
 /* Collect CPU base addresses */
 count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
gic_acpi_parse_madt_cpu, table,
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 6/8] arm: vgic: Split vgic_domain_init() functionality into two functions

2016-06-18 Thread Shanker Donthineni
Split code that installs mmio handlers for GICD and Re-distributor
regions to a new function. The intension of this separation is to defer
steps that registers vgic_v2/v3 mmio handlers.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/vgic-v2.c | 10 +++---
 xen/arch/arm/vgic-v3.c | 40 +++-
 xen/arch/arm/vgic.c|  3 +++
 xen/include/asm-arm/vgic.h |  2 ++
 4 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index f5778e6..d42b408 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -645,6 +645,12 @@ static int vgic_v2_vcpu_init(struct vcpu *v)
 return 0;
 }
 
+static void vgic_v2_domain_register_mmio(struct domain *d)
+{
+register_mmio_handler(d, _v2_distr_mmio_handler, d->arch.vgic.dbase,
+ PAGE_SIZE, NULL);
+}
+
 static int vgic_v2_domain_init(struct domain *d)
 {
 int ret;
@@ -693,9 +699,6 @@ static int vgic_v2_domain_init(struct domain *d)
 if ( ret )
 return ret;
 
-register_mmio_handler(d, _v2_distr_mmio_handler, d->arch.vgic.dbase,
-  PAGE_SIZE, NULL);
-
 return 0;
 }
 
@@ -708,6 +711,7 @@ static const struct vgic_ops vgic_v2_ops = {
 .vcpu_init   = vgic_v2_vcpu_init,
 .domain_init = vgic_v2_domain_init,
 .domain_free = vgic_v2_domain_free,
+.domain_register_mmio = vgic_v2_domain_register_mmio,
 .max_vcpus = 8,
 };
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index e877e9e..3a5aeb6 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1391,6 +1391,28 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
 return 0;
 }
 
+static void vgic_v3_domain_register_mmio(struct domain *d)
+{
+int i;
+
+/* Register mmio handle for the Distributor */
+register_mmio_handler(d, _distr_mmio_handler, d->arch.vgic.dbase,
+ SZ_64K, NULL);
+
+/*
+ * Register mmio handler per contiguous region occupied by the
+ * redistributors. The handler will take care to choose which
+ * redistributor is targeted.
+ */
+for ( i = 0; i < d->arch.vgic.nr_regions; i++ )
+{
+struct vgic_rdist_region *region = >arch.vgic.rdist_regions[i];
+
+register_mmio_handler(d, _rdistr_mmio_handler,
+ region->base, region->size, region);
+}
+}
+
 static int vgic_v3_domain_init(struct domain *d)
 {
 struct vgic_rdist_region *rdist_regions;
@@ -1455,23 +1477,6 @@ static int vgic_v3_domain_init(struct domain *d)
 d->arch.vgic.rdist_regions[0].first_cpu = 0;
 }
 
-/* Register mmio handle for the Distributor */
-register_mmio_handler(d, _distr_mmio_handler, d->arch.vgic.dbase,
-  SZ_64K, NULL);
-
-/*
- * Register mmio handler per contiguous region occupied by the
- * redistributors. The handler will take care to choose which
- * redistributor is targeted.
- */
-for ( i = 0; i < d->arch.vgic.nr_regions; i++ )
-{
-struct vgic_rdist_region *region = >arch.vgic.rdist_regions[i];
-
-register_mmio_handler(d, _rdistr_mmio_handler,
-  region->base, region->size, region);
-}
-
 d->arch.vgic.ctlr = VGICD_CTLR_DEFAULT;
 
 return 0;
@@ -1487,6 +1492,7 @@ static const struct vgic_ops v3_ops = {
 .domain_init = vgic_v3_domain_init,
 .domain_free = vgic_v3_domain_free,
 .emulate_sysreg  = vgic_v3_emulate_sysreg,
+.domain_register_mmio = vgic_v3_domain_register_mmio,
 /*
  * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU
  * that can be supported is up to 4096(==256*16) in theory.
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 5df5f01..5b39e0d 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -151,9 +151,12 @@ int domain_vgic_init(struct domain *d, unsigned int 
nr_spis)
 for ( i = 0; i < NR_GIC_SGI; i++ )
 set_bit(i, d->arch.vgic.allocated_irqs);
 
+d->arch.vgic.handler->domain_register_mmio(d);
+
 return 0;
 }
 
+
 void register_vgic_ops(struct domain *d, const struct vgic_ops *ops)
 {
d->arch.vgic.handler = ops;
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index fbb763a..8fe65b4 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -132,6 +132,8 @@ struct vgic_ops {
 void (*domain_free)(struct domain *d);
 /* vGIC sysreg emulation */
 int (*emulate_sysreg)(struct cpu_user_regs *regs, union hsr hsr);
+/* Register mmio handlers */
+void (*domain_register_mmio)(struct domain *d);
 /* Maximum number of vCPU supported */
 const unsigned int max_vcpus;
 };
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a m

[Xen-devel] [PATCH 4/8] xen/arm: vgic: Use dynamic memory allocation for vgic_rdist_region

2016-06-18 Thread Shanker Donthineni
The number of Re-distributor regions allowed for dom0 is hardcoded
to a compile time macro MAX_RDIST_COUNT which is 4. On some systems,
especially latest server chips might have more than 4 redistributors.
Either we have to increase MAX_RDIST_COUNT to a bigger number or
allocate memory based on number of redistributors that are found in
MADT table. In the worst case scenario, the macro MAX_RDIST_COUNT
should be equal to CONFIG_NR_CPUS in order to support per CPU
Redistributors.

Increasing MAX_RDIST_COUNT has side effect, it blows 'struct domain'
size and hits BUILD_BUG_ON() in domain build code path.

struct domain *alloc_domain_struct(void)
{
struct domain *d;
BUILD_BUG_ON(sizeof(*d) > PAGE_SIZE);
d = alloc_xenheap_pages(0, 0);
if ( d == NULL )
return NULL;
...

This patch uses the second approach to fix the BUILD_BUG().

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/vgic-v2.c   |  6 ++
 xen/arch/arm/vgic-v3.c   | 22 +++---
 xen/arch/arm/vgic.c  |  1 +
 xen/include/asm-arm/domain.h | 12 +++-
 xen/include/asm-arm/vgic.h   |  2 ++
 5 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 9adb4a9..f5778e6 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -699,9 +699,15 @@ static int vgic_v2_domain_init(struct domain *d)
 return 0;
 }
 
+static void vgic_v2_domain_free(struct domain *d)
+{
+/* Nothing to be cleanup for this driver */
+}
+
 static const struct vgic_ops vgic_v2_ops = {
 .vcpu_init   = vgic_v2_vcpu_init,
 .domain_init = vgic_v2_domain_init,
+.domain_free = vgic_v2_domain_free,
 .max_vcpus = 8,
 };
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index b37a7c0..e877e9e 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1393,7 +1393,19 @@ static int vgic_v3_vcpu_init(struct vcpu *v)
 
 static int vgic_v3_domain_init(struct domain *d)
 {
-int i;
+struct vgic_rdist_region *rdist_regions;
+int rdist_count, i;
+
+/* Allocate memory for Re-distributor regions */
+rdist_count = is_hardware_domain(d) ? vgic_v3_hw.nr_rdist_regions :
+   GUEST_GICV3_RDIST_REGIONS;
+
+rdist_regions = xzalloc_array(struct vgic_rdist_region, rdist_count);
+if ( !rdist_regions )
+return -ENOMEM;
+
+d->arch.vgic.nr_regions = rdist_count;
+d->arch.vgic.rdist_regions = rdist_regions;
 
 /*
  * Domain 0 gets the hardware address.
@@ -1426,7 +1438,6 @@ static int vgic_v3_domain_init(struct domain *d)
 
 first_cpu += size / d->arch.vgic.rdist_stride;
 }
-d->arch.vgic.nr_regions = vgic_v3_hw.nr_rdist_regions;
 }
 else
 {
@@ -1435,7 +1446,6 @@ static int vgic_v3_domain_init(struct domain *d)
 /* XXX: Only one Re-distributor region mapped for the guest */
 BUILD_BUG_ON(GUEST_GICV3_RDIST_REGIONS != 1);
 
-d->arch.vgic.nr_regions = GUEST_GICV3_RDIST_REGIONS;
 d->arch.vgic.rdist_stride = GUEST_GICV3_RDIST_STRIDE;
 
 /* The first redistributor should contain enough space for all CPUs */
@@ -1467,9 +1477,15 @@ static int vgic_v3_domain_init(struct domain *d)
 return 0;
 }
 
+static void vgic_v3_domain_free(struct domain *d)
+{
+xfree(d->arch.vgic.rdist_regions);
+}
+
 static const struct vgic_ops v3_ops = {
 .vcpu_init   = vgic_v3_vcpu_init,
 .domain_init = vgic_v3_domain_init,
+.domain_free = vgic_v3_domain_free,
 .emulate_sysreg  = vgic_v3_emulate_sysreg,
 /*
  * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 3e1c572..5df5f01 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -177,6 +177,7 @@ void domain_vgic_free(struct domain *d)
 }
 }
 
+d->arch.vgic.handler->domain_free(d);
 xfree(d->arch.vgic.shared_irqs);
 xfree(d->arch.vgic.pending_irqs);
 xfree(d->arch.vgic.allocated_irqs);
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 370cdeb..9492727 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -40,6 +40,12 @@ struct vtimer {
 uint64_t cval;
 };
 
+struct vgic_rdist_region {
+paddr_t base;  /* Base address */
+paddr_t size;  /* Size */
+unsigned int first_cpu;/* First CPU handled */
+};
+
 struct arch_domain
 {
 #ifdef CONFIG_ARM_64
@@ -103,11 +109,7 @@ struct arch_domain
 #ifdef CONFIG_HAS_GICV3
 /* GIC V3 addressing */
 /* List of contiguous occupied by the redistributors */
-struct vgic_rdist_region {
-paddr_t base;   /* Base address */
-paddr_t size;   /* Size */
-unsigned int first_cpu; /* First CPU handled */
-} rdist_regions[MAX_RD

[Xen-devel] [PATCH 7/8] arm/mmio: Use separate memory allocation for mmio handlers

2016-06-18 Thread Shanker Donthineni
The number of mmio handlers are limited to a compile time macro
MAX_IO_HANDLER which is 16. This number is not at all sufficient
to support per CPU distributor regions. Either it needs to be
increased to a bigger number, at least CONFIG_NR_CPUS+16, or
allocate a separate memory for mmio handlers dynamically during
domain build.

This patch uses the dynamic allocation strategy to reduce memory
footprint for 'struct domain' instead of static allocation.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c  |  6 --
 xen/arch/arm/io.c  | 14 --
 xen/include/asm-arm/mmio.h |  6 --
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 1365b4a..4010ff2 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -527,7 +527,7 @@ void vcpu_destroy(struct vcpu *v)
 int arch_domain_create(struct domain *d, unsigned int domcr_flags,
struct xen_arch_domainconfig *config)
 {
-int rc;
+int rc, count;
 
 d->arch.relmem = RELMEM_not_started;
 
@@ -550,7 +550,8 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-if ( (rc = domain_io_init(d)) != 0 )
+count = MAX_IO_HANDLER;
+if ( (rc = domain_io_init(d, count)) != 0 )
 goto fail;
 
 if ( (rc = p2m_alloc_table(d)) != 0 )
@@ -644,6 +645,7 @@ void arch_domain_destroy(struct domain *d)
 free_xenheap_pages(d->arch.efi_acpi_table,
get_order_from_bytes(d->arch.efi_acpi_len));
 #endif
+domain_io_free(d);
 }
 
 void arch_domain_shutdown(struct domain *d)
diff --git a/xen/arch/arm/io.c b/xen/arch/arm/io.c
index 0156755..a5b2c2d 100644
--- a/xen/arch/arm/io.c
+++ b/xen/arch/arm/io.c
@@ -102,7 +102,7 @@ void register_mmio_handler(struct domain *d,
 struct vmmio *vmmio = >arch.vmmio;
 struct mmio_handler *handler;
 
-BUG_ON(vmmio->num_entries >= MAX_IO_HANDLER);
+BUG_ON(vmmio->num_entries >= vmmio->max_num_entries);
 
 spin_lock(>lock);
 
@@ -125,14 +125,24 @@ void register_mmio_handler(struct domain *d,
 spin_unlock(>lock);
 }
 
-int domain_io_init(struct domain *d)
+int domain_io_init(struct domain *d, int max_count)
 {
spin_lock_init(>arch.vmmio.lock);
d->arch.vmmio.num_entries = 0;
 
+   d->arch.vmmio.max_num_entries = max_count;
+   d->arch.vmmio.handlers = xzalloc_array(struct mmio_handler, max_count);
+   if ( !d->arch.vmmio.handlers )
+   return -ENOMEM;
+
return 0;
 }
 
+void domain_io_free(struct domain *d)
+{
+xfree(d->arch.vmmio.handlers);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/asm-arm/mmio.h b/xen/include/asm-arm/mmio.h
index da1cc2e..276b263 100644
--- a/xen/include/asm-arm/mmio.h
+++ b/xen/include/asm-arm/mmio.h
@@ -51,15 +51,17 @@ struct mmio_handler {
 
 struct vmmio {
 int num_entries;
+int max_num_entries;
 spinlock_t lock;
-struct mmio_handler handlers[MAX_IO_HANDLER];
+struct mmio_handler *handlers;
 };
 
 extern int handle_mmio(mmio_info_t *info);
 void register_mmio_handler(struct domain *d,
const struct mmio_handler_ops *ops,
paddr_t addr, paddr_t size, void *priv);
-int domain_io_init(struct domain *d);
+int domain_io_init(struct domain *d, int max_count);
+void domain_io_free(struct domain *d);
 
 #endif  /* __ASM_ARM_MMIO_H__ */
 
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 5/8] arm/gic-v3: Remove an unused macro MAX_RDIST_COUNT

2016-06-18 Thread Shanker Donthineni
The macro MAX_RDIST_COUNT is not being used after converting code
to handle number of redistributor dynamically. So remove it from
header file and the two other panic() messages that are not valid
anymore.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/gic-v3.c | 8 
 xen/include/asm-arm/gic.h | 1 -
 2 files changed, 9 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 42cf848..28c00cf 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1200,10 +1200,6 @@ static void __init gicv3_dt_init(void)
 _count) )
 gicv3.rdist_count = 1;
 
-if ( gicv3.rdist_count > MAX_RDIST_COUNT )
-panic("GICv3: Number of redistributor regions is more than"
-  "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
-
 rdist_regs = xzalloc_array(struct rdist_region, gicv3.rdist_count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
@@ -1518,10 +1514,6 @@ static void __init gicv3_acpi_init(void)
 gicr_table = false;
 }
 
-if ( count > MAX_RDIST_COUNT )
-panic("GICv3: Number of redistributor regions is more than"
-  "%d (Increase MAX_RDIST_COUNT!!)\n", MAX_RDIST_COUNT);
-
 rdist_regs = xzalloc_array(struct rdist_region, count);
 if ( !rdist_regs )
 panic("GICv3: Failed to allocate memory for rdist regions\n");
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 7f9ad86..3694e07 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -20,7 +20,6 @@
 
 #define NR_GIC_LOCAL_IRQS  NR_LOCAL_IRQS
 #define NR_GIC_SGI 16
-#define MAX_RDIST_COUNT4
 
 #define GICD_CTLR   (0x000)
 #define GICD_TYPER  (0x004)
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 0/8] Add support for parsing per CPU Redistributor entry

2016-06-18 Thread Shanker Donthineni
The current driver doesn't support parsing Redistributor entries that
are described in the MADT GICC table. Not all the GIC implementors
places the Redistributor regions in the always-on power domain. On
systems, the UEFI firmware should describe Redistributor base address
in the associated GIC CPU Interface (GICC) instead of GIC Redistributor
(GICR) table.

The maximum number of mmio handlers and struct vgic_rdist_region
that holds Redistributor addresses are allocated through a static
array with hardcoded size. I don't think this is the right approach
and is not scalable for implementing features like this. I have
decided to convert static to dynamic allocation based on comments
from the below link.

https://patchwork.kernel.org/patch/9163435/

Patches #1, #2 and #3 adds support for parsing not always-on power
domain Redistributor regions.

Patches #4, #5, #6, #7 and #8 refactors the code and allocates the
memory for mmio handlers and vgic_rdist_region based on the number of
Redistributors required for dom0/domU instead of hardcoded values.

This pacthset is created on tip of Julien's branch 
http://xenbits.xen.org/gitweb/?p=people/julieng/xen-unstable.git;a=shortlog;h=refs/heads/irq-routing-acpi-rfc
  
Shanker Donthineni (8):
  arm/gic-v3: Add a separate function for mapping GICD region
  arm/gic-v3: Fold GICR subtable parsing into a new function
  arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable
  xen/arm: vgic: Use dynamic memory allocation for vgic_rdist_region
  arm/gic-v3: Remove an unused macro MAX_RDIST_COUNT
  arm: vgic: Split vgic_domain_init() functionality into two functions
  arm/mmio: Use separate memory allocation for mmio handlers
  arm/vgic: Change fixed number of mmio handlers to variable number

 xen/arch/arm/domain.c |  12 ++-
 xen/arch/arm/gic-v3.c | 162 --
 xen/arch/arm/io.c |  14 +++-
 xen/arch/arm/vgic-v2.c|  16 +++-
 xen/arch/arm/vgic-v3.c|  65 ++-
 xen/arch/arm/vgic.c   |   7 ++
 xen/include/asm-arm/domain.h  |  13 +--
 xen/include/asm-arm/gic.h |   3 +-
 xen/include/asm-arm/gic_v3_defs.h |   1 +
 xen/include/asm-arm/mmio.h|   6 +-
 xen/include/asm-arm/vgic.h|   5 ++
 11 files changed, 226 insertions(+), 78 deletions(-)

-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH 3/8] arm/gic-v3: Parse per-cpu redistributor entry in GICC subtable

2016-06-18 Thread Shanker Donthineni
The redistributor address can be specified either as part of GICC or
GICR subtable depending on the power domain. The current driver
doesn't support parsing redistributor entry that is defined in GICC
subtable. The GIC CPU subtable entry holds the associated Redistributor
base address if it is not on always-on power domain.

This patch adds necessary code to handle both types of Redistributors
base addresses.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/gic-v3.c | 97 ---
 xen/include/asm-arm/gic.h |  2 +
 xen/include/asm-arm/gic_v3_defs.h |  1 +
 3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index af12ebc..42cf848 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -659,6 +659,10 @@ static int __init gicv3_populate_rdist(void)
 smp_processor_id(), i, ptr);
 return 0;
 }
+
+if ( gicv3.rdist_regions[i].single_rdist )
+break;
+
 if ( gicv3.rdist_stride )
 ptr += gicv3.rdist_stride;
 else
@@ -1282,6 +1286,11 @@ static int gicv3_iomem_deny_access(const struct domain 
*d)
 }
 
 #ifdef CONFIG_ACPI
+static bool gic_dist_supports_dvis(void)
+{
+return !!(readl_relaxed(GICD + GICD_TYPER) & GICD_TYPER_DVIS);
+}
+
 static int gicv3_make_hwdom_madt(const struct domain *d, u32 offset)
 {
 struct acpi_subtable_header *header;
@@ -1393,18 +1402,39 @@ gic_acpi_parse_madt_redistributor(struct 
acpi_subtable_header *header,
   const unsigned long end)
 {
 struct acpi_madt_generic_redistributor *rdist;
+struct acpi_madt_generic_interrupt *processor;
 struct rdist_region *region;
 
 region = gicv3.rdist_regions + gicv3.rdist_count;
-rdist = (struct acpi_madt_generic_redistributor *)header;
-if ( BAD_MADT_ENTRY(rdist, end) )
-return -EINVAL;
+if ( header->type == ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR )
+{
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) )
+return -EINVAL;
 
-if ( !rdist->base_address || !rdist->length )
-return -EINVAL;
+if ( !rdist->base_address || !rdist->length )
+return -EINVAL;
+
+region->base = rdist->base_address;
+region->size = rdist->length;
+}
+else if ( header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT )
+{
+processor = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(processor, end) )
+return -EINVAL;
+
+if ( !(processor->flags & ACPI_MADT_ENABLED) )
+return 0;
+
+if ( !processor->gicr_base_address )
+return -EINVAL;
+
+region->base = processor->gicr_base_address;
+region->size = gic_dist_supports_dvis() ? SZ_256K : SZ_128K;
+   region->single_rdist = true;
+   }
 
-region->base = rdist->base_address;
-region->size = rdist->length;
 
 region->map_base = ioremap_nocache(region->base, region->size);
 if ( !region->map_base )
@@ -1412,6 +1442,7 @@ gic_acpi_parse_madt_redistributor(struct 
acpi_subtable_header *header,
 printk("Unable to map GICR registers\n");
 return -ENOMEM;
 }
+
 gicv3.rdist_count++;
 
 return 0;
@@ -1421,9 +1452,22 @@ static int __init
 gic_acpi_get_madt_redistributor_num(struct acpi_subtable_header *header,
 const unsigned long end)
 {
-/* Nothing to do here since it only wants to get the number of GIC
- * redistributors.
- */
+struct acpi_madt_generic_redistributor *rdist;
+struct acpi_madt_generic_interrupt *cpuif;
+
+if ( header->type == ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR )
+{
+rdist = (struct acpi_madt_generic_redistributor *)header;
+if ( BAD_MADT_ENTRY(rdist, end) || !rdist->base_address )
+return -EINVAL;
+}
+else if ( header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT )
+{
+cpuif = (struct acpi_madt_generic_interrupt *)header;
+if ( BAD_MADT_ENTRY(cpuif, end) || !cpuif->gicr_base_address )
+return -EINVAL;
+}
+
 return 0;
 }
 
@@ -1431,6 +1475,7 @@ static void __init gicv3_acpi_init(void)
 {
 struct acpi_table_header *table;
 struct rdist_region *rdist_regs;
+bool gicr_table = true;
 acpi_status status;
 int count;
 
@@ -1460,8 +1505,18 @@ static void __init gicv3_acpi_init(void)
 count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
gic_acpi_get_madt_redistributor_num, table,
ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0);
-if ( count <= 0 )
-panic("GICv3: No valid GICR 

[Xen-devel] [PATCH 8/8] arm/vgic: Change fixed number of mmio handlers to variable number

2016-06-18 Thread Shanker Donthineni
Record the number of mmio handlers that are required for vGICv3/2
in variable 'arch_domain.vgic.mmio_count' in vgic_domain_init().
Augment this variable number to a fixed number MAX_IO_HANDLER and
pass it to domain_io_init() to allocate enough memory for handlers.

New code path:
 domain_vgic_init()
   count = MAX_IO_HANDLER + d->arch.vgic.mmio_count;
   domain_io_init(count)
 domain_vgic_register_mmio()

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
---
 xen/arch/arm/domain.c| 10 ++
 xen/arch/arm/vgic-v2.c   |  2 ++
 xen/arch/arm/vgic-v3.c   |  3 +++
 xen/arch/arm/vgic.c  |  7 +--
 xen/include/asm-arm/domain.h |  1 +
 xen/include/asm-arm/vgic.h   |  1 +
 6 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 4010ff2..ef567c8 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -550,10 +550,6 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 share_xen_page_with_guest(
 virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-count = MAX_IO_HANDLER;
-if ( (rc = domain_io_init(d, count)) != 0 )
-goto fail;
-
 if ( (rc = p2m_alloc_table(d)) != 0 )
 goto fail;
 
@@ -593,6 +589,12 @@ int arch_domain_create(struct domain *d, unsigned int 
domcr_flags,
 if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
 goto fail;
 
+count = MAX_IO_HANDLER + d->arch.vgic.mmio_count;
+if ( (rc = domain_io_init(d, count)) != 0 )
+goto fail;
+
+domain_vgic_register_mmio(d);
+
 if ( (rc = domain_vtimer_init(d, config)) != 0 )
 goto fail;
 
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index d42b408..7ed7d32 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -699,6 +699,8 @@ static int vgic_v2_domain_init(struct domain *d)
 if ( ret )
 return ret;
 
+d->arch.vgic.mmio_count = 1; /* Only GICD region */
+
 return 0;
 }
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 3a5aeb6..6a5f333 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1479,6 +1479,9 @@ static int vgic_v3_domain_init(struct domain *d)
 
 d->arch.vgic.ctlr = VGICD_CTLR_DEFAULT;
 
+/* GICD region + number of Re-distributors */
+d->arch.vgic.mmio_count = d->arch.vgic.nr_regions + 1;
+
 return 0;
 }
 
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 5b39e0d..7d34942 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -88,6 +88,11 @@ static void vgic_rank_init(struct vgic_irq_rank *rank, 
uint8_t index,
 rank->vcpu[i] = vcpu;
 }
 
+void domain_vgic_register_mmio(struct domain *d)
+{
+d->arch.vgic.handler->domain_register_mmio(d);
+}
+
 int domain_vgic_init(struct domain *d, unsigned int nr_spis)
 {
 int i;
@@ -151,8 +156,6 @@ int domain_vgic_init(struct domain *d, unsigned int nr_spis)
 for ( i = 0; i < NR_GIC_SGI; i++ )
 set_bit(i, d->arch.vgic.allocated_irqs);
 
-d->arch.vgic.handler->domain_register_mmio(d);
-
 return 0;
 }
 
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 9492727..974cf93 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -113,6 +113,7 @@ struct arch_domain
 int nr_regions; /* Number of rdist regions */
 uint32_t rdist_stride;  /* Re-Distributor stride */
 #endif
+uint32_t mmio_count;   /* Number of mmio handlers */
 } vgic;
 
 struct vuart {
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 8fe65b4..0032633 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -309,6 +309,7 @@ extern void register_vgic_ops(struct domain *d, const 
struct vgic_ops *ops);
 int vgic_v2_init(struct domain *d);
 int vgic_v3_init(struct domain *d);
 
+extern void domain_vgic_register_mmio(struct domain *d);
 extern int vcpu_vgic_free(struct vcpu *v);
 extern int vgic_to_sgi(struct vcpu *v, register_t sgir,
enum gic_sgi_mode irqmode, int virq,
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V9 2/3] drivers/pl011: Use combination of UARTRIS and UARTMSC instead of UARTMIS

2016-06-13 Thread Shanker Donthineni



On 06/13/2016 05:30 AM, Stefano Stabellini wrote:

On Thu, 9 Jun 2016, Shanker Donthineni wrote:

The Masked interrupt status register (UARTMIS) is not described in ARM
SBSA 2.x document. Anding of two registers UARTMSC and UARTRIS values
gives the same information as register UARTMIS.

UARTRIS, UARTMSC and UARTMIS definitions are found in PrimeCell UART
PL011 (Revision: r1p4).
  - 3.3.10 Interrupt mask set/clear register, UARTIMSC
  - 3.3.11 Raw interrupt status register, UARTRIS
  - 3.3.12 Masked interrupt status register, UARTMIS

This change is necessary for driver to be SBSA compliant v2.x without
affecting the current driver functionality.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Reviewed-by: Julien Grall <julien.gr...@arm.com>

Changes since v8:
  Fixed white spaces.

Changes since v7:
  Moved comment 'To compatible with SBSA v2.x document, all accesses

should be 32-bit' to #3

Changes since v1:
  Added a new function to return an interrupt status.

  xen/drivers/char/pl011.c | 10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 6a3c21b..7e19c4a 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -53,11 +53,17 @@ static struct pl011 {
  #define pl011_read(uart, off)   readl((uart)->regs + (off))
  #define pl011_write(uart, off,val)  writel((val), (uart)->regs +

(off))
  
+static unsigned int pl011_intr_status(struct pl011 *uart)

Maybe this should be static inline?

In any case the series is good, I am happy to queue it up for 4.8.
Nice discussion on usage of keyword 'inline', 
https://www.kernel.org/doc/local/inline.html.


--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC 0/8] xen/arm: acpi: Support SPIs routing

2016-06-13 Thread Shanker Donthineni

Julien,

The problem that was reported earlier related to our platform drivers in 
domn0 kernel. I have verified your patches and works fine without any 
dead-lock.



On 06/13/2016 06:42 AM, Julien Grall wrote:



On 08/06/16 13:34, Julien Grall wrote:

On 08/06/16 13:11, Shanker Donthineni wrote:

I don't know exactly which of the patch causing the issue. I have
noticed a couple of drivers are not receiving SPI interrupts in DOM0.
I need to digest your patches before tracing/investigate the problem
to get more details.

FYI, our system uses both the EDGE and LEVEL interrupts, any major
change in your patches?


The routing is done when DOM0 is built and the interrupt configuration
is deferred.

It might be possible to the wrong type is retrieve by 
__vgic_get_virq_type.


I looked at my code again today and add some printk. The IRQ will 
always be configured correctly with the correct type.


It would be good to know if the problem only happen with edge or level 
interrupts.


Regards,



--
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux 
Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V9 3/3] arm/acpi: Add Server Base System Architecture UART support

2016-06-09 Thread Shanker Donthineni
The ARM Server Base System Architecture describes a generic UART
interface. It doesn't support clock control registers, modem
control, DMA and hardware flow control features. So, extend the
driver probe() to handle SBSA interface and skip the accessing
PL011 registers that are not described in SBSA document
(ARM-DEN-0029 Version 3.0, 6 APPENDIX B: GENERIC UART).

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Reviewed-by: Julien Grall <julien.gr...@arm.com>
---
Changes sicne v8:
   Simplified condition 'if (spcr->interface_type == ACPI_DBG2_SBSA) || '.

Changes sicne v7:
   Moved comment 'To compatible with SBSA v2.x document, all accesses should be 
32-bit' from #2.

Changes since v3:
  Moved non-SBSA related changes to patches 1/3 and 2/3.

changes since v2:
  Edited commit text to include SBSA document version.
  Remove setting baudrate code completely as per Julien's suggestion.
  Support both the SBSA interface types ACPI_DBG2_SBSA & ACPI_DBG2_SBSA_32.
  Replace MIS references with combination of RIS & IMSC.

Changes since v1:
  Don't access UART registers that are not part of SBSA document.
  Move setting baudrate function to a separate function.

 xen/drivers/char/pl011.c | 54 ++--
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 7e19c4a..ab22f7f 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -41,6 +41,7 @@ static struct pl011 {
 /* struct timer timer; */
 /* unsigned int timeout_ms; */
 /* bool_t probing, intr_works; */
+bool sbsa;  /* ARM SBSA generic interface */
 } pl011_com = {0};
 
 /* These parity settings can be ORed directly into the LCR. */
@@ -50,6 +51,7 @@ static struct pl011 {
 #define PARITY_MARK  (PEN|SPS)
 #define PARITY_SPACE (PEN|EPS|SPS)
 
+/* SBSA v2.x document requires, all reads/writes must be 32-bit accesses */
 #define pl011_read(uart, off)   readl((uart)->regs + (off))
 #define pl011_write(uart, off,val)  writel((val), (uart)->regs + (off))
 
@@ -95,14 +97,17 @@ static void __init pl011_init_preirq(struct serial_port 
*port)
 /* No interrupts, please. */
 pl011_write(uart, IMSC, 0);
 
-/* Definitely no DMA */
-pl011_write(uart, DMACR, 0x0);
-
-/* This write must follow FBRD and IBRD writes. */
-pl011_write(uart, LCR_H, (uart->data_bits - 5) << 5
-| FEN
-| ((uart->stop_bits - 1) << 3)
-| uart->parity);
+if ( !uart->sbsa )
+{
+/* Definitely no DMA */
+pl011_write(uart, DMACR, 0x0);
+
+/* This write must follow FBRD and IBRD writes. */
+pl011_write(uart, LCR_H, (uart->data_bits - 5) << 5
+| FEN
+| ((uart->stop_bits - 1) << 3)
+| uart->parity);
+}
 /* Clear errors */
 pl011_write(uart, RSR, 0);
 
@@ -110,10 +115,13 @@ static void __init pl011_init_preirq(struct serial_port 
*port)
 pl011_write(uart, IMSC, 0);
 pl011_write(uart, ICR, ALLI);
 
-/* Enable the UART for RX and TX; keep RTS and DTR */
-cr = pl011_read(uart, CR);
-cr &= RTS | DTR;
-pl011_write(uart, CR, cr | RXE | TXE | UARTEN);
+if ( !uart->sbsa )
+{
+/* Enable the UART for RX and TX; keep RTS and DTR */
+cr = pl011_read(uart, CR);
+cr &= RTS | DTR;
+pl011_write(uart, CR, cr | RXE | TXE | UARTEN);
+}
 }
 
 static void __init pl011_init_postirq(struct serial_port *port)
@@ -215,7 +223,7 @@ static struct uart_driver __read_mostly pl011_driver = {
 .vuart_info   = pl011_vuart,
 };
 
-static int __init pl011_uart_init(int irq, u64 addr, u64 size)
+static int __init pl011_uart_init(int irq, u64 addr, u64 size, bool sbsa)
 {
 struct pl011 *uart;
 
@@ -224,6 +232,7 @@ static int __init pl011_uart_init(int irq, u64 addr, u64 
size)
 uart->data_bits = 8;
 uart->parity= PARITY_NONE;
 uart->stop_bits = 1;
+uart->sbsa  = sbsa;
 
 uart->regs = ioremap_nocache(addr, size);
 if ( !uart->regs )
@@ -272,7 +281,7 @@ static int __init pl011_dt_uart_init(struct dt_device_node 
*dev,
 return -EINVAL;
 }
 
-res = pl011_uart_init(res, addr, size);
+res = pl011_uart_init(res, addr, size, false);
 if ( res < 0 )
 {
 printk("pl011: Unable to initialize\n");
@@ -303,6 +312,7 @@ static int __init pl011_acpi_uart_init(const void *data)
 acpi_status status;
 struct acpi_table_spcr *spcr = NULL;
 int res;
+bool sbsa;
 
 status = acpi_get_table(ACPI_SIG_SPCR, 0,
 (struct acpi_table_header **));
@@ -313,11 +323,14 @@ static int __init pl011_acpi_uart_init(const void *data)
 return -EINVAL;
  

[Xen-devel] [PATCH V9 1/3] drivers/pl011: Don't configure baudrate

2016-06-09 Thread Shanker Donthineni
The default baud and clock_hz configuration parameters are hardcoded
(commit 60ff980995008caf) for Versatile Express. Other platforms,
these default values may not be valid and might cause problems by
programming registers IBRD and FBRD incorrectly.

So, removing driver logic that sets the baudrate to fix the problem.
The behavior is unchanged because the driver was already relying on
the boot firmware for setting the correct baudrate.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Reviewed-by: Julien Grall <julien.gr...@arm.com>
---
Changes since v1:
  Edited commit text.

 xen/drivers/char/pl011.c | 21 +
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 1212d5c..6a3c21b 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -31,7 +31,7 @@
 #include 
 
 static struct pl011 {
-unsigned int baud, clock_hz, data_bits, parity, stop_bits;
+unsigned int data_bits, parity, stop_bits;
 unsigned int irq;
 void __iomem *regs;
 /* UART with IRQ line: interrupt-driven I/O. */
@@ -84,7 +84,6 @@ static void pl011_interrupt(int irq, void *data, struct 
cpu_user_regs *regs)
 static void __init pl011_init_preirq(struct serial_port *port)
 {
 struct pl011 *uart = port->uart;
-unsigned int divisor;
 unsigned int cr;
 
 /* No interrupts, please. */
@@ -93,22 +92,6 @@ static void __init pl011_init_preirq(struct serial_port 
*port)
 /* Definitely no DMA */
 pl011_write(uart, DMACR, 0x0);
 
-/* Line control and baud-rate generator. */
-if ( uart->baud != BAUD_AUTO )
-{
-/* Baud rate specified: program it into the divisor latch. */
-divisor = (uart->clock_hz << 2) / uart->baud; /* clk << 6 / bd << 4 */
-pl011_write(uart, FBRD, divisor & 0x3f);
-pl011_write(uart, IBRD, divisor >> 6);
-}
-else
-{
-/* Baud rate already set: read it out from the divisor latch. */
-divisor = (pl011_read(uart, IBRD) << 6) | (pl011_read(uart, FBRD));
-if (!divisor)
-panic("pl011: No Baud rate configured\n");
-uart->baud = (uart->clock_hz << 2) / divisor;
-}
 /* This write must follow FBRD and IBRD writes. */
 pl011_write(uart, LCR_H, (uart->data_bits - 5) << 5
 | FEN
@@ -232,8 +215,6 @@ static int __init pl011_uart_init(int irq, u64 addr, u64 
size)
 
 uart = _com;
 uart->irq   = irq;
-uart->clock_hz  = 0x16e3600;
-uart->baud  = BAUD_AUTO;
 uart->data_bits = 8;
 uart->parity= PARITY_NONE;
 uart->stop_bits = 1;
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [PATCH V9 2/3] drivers/pl011: Use combination of UARTRIS and UARTMSC instead of UARTMIS

2016-06-09 Thread Shanker Donthineni
The Masked interrupt status register (UARTMIS) is not described in ARM
SBSA 2.x document. Anding of two registers UARTMSC and UARTRIS values
gives the same information as register UARTMIS.

UARTRIS, UARTMSC and UARTMIS definitions are found in PrimeCell UART
PL011 (Revision: r1p4).
 - 3.3.10 Interrupt mask set/clear register, UARTIMSC
 - 3.3.11 Raw interrupt status register, UARTRIS
 - 3.3.12 Masked interrupt status register, UARTMIS

This change is necessary for driver to be SBSA compliant v2.x without
affecting the current driver functionality.

Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
Reviewed-by: Julien Grall <julien.gr...@arm.com>
---
Changes since v8:
 Fixed white spaces.

Changes since v7:
 Moved comment 'To compatible with SBSA v2.x document, all accesses should be 
32-bit' to #3

Changes since v1:
 Added a new function to return an interrupt status.

 xen/drivers/char/pl011.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 6a3c21b..7e19c4a 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -53,11 +53,17 @@ static struct pl011 {
 #define pl011_read(uart, off)   readl((uart)->regs + (off))
 #define pl011_write(uart, off,val)  writel((val), (uart)->regs + (off))
 
+static unsigned int pl011_intr_status(struct pl011 *uart)
+{
+/* UARTMIS is not documented in SBSA v2.x, so use UARTRIS/UARTIMSC. */
+return (pl011_read(uart, RIS) & pl011_read(uart, IMSC));
+}
+
 static void pl011_interrupt(int irq, void *data, struct cpu_user_regs *regs)
 {
 struct serial_port *port = data;
 struct pl011 *uart = port->uart;
-unsigned int status = pl011_read(uart, MIS);
+unsigned int status = pl011_intr_status(uart);
 
 if ( status )
 {
@@ -76,7 +82,7 @@ static void pl011_interrupt(int irq, void *data, struct 
cpu_user_regs *regs)
 if ( status & (TXI) )
 serial_tx_interrupt(port, regs);
 
-status = pl011_read(uart, MIS);
+status = pl011_intr_status(uart);
 } while (status != 0);
 }
 }
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


  1   2   >