Hi Marc,

On 10/07/2017 07:59 AM, Shanker Donthineni wrote:
> Hi Marc, 
> 
> Thanks for your quick review comments.
> 
> On 10/07/2017 04:58 AM, Marc Zyngier wrote:
>> On Sat, Oct 07 2017 at 12:13:24 am BST, Shanker Donthineni 
>> <shank...@codeaurora.org> wrote:
>>> The current ITS driver works fine as long as normal memory and GICR
>>> regions are located within the lower 48bit (>=0 && <2^48) physical
>>> address space. Some of the registers GICR_PEND/PROP, GICR_VPEND/VPROP
>>> and GITS_CBASER are handled properly but not all when configuring
>>> the hardware with 52bit physical address.
>>>
>>> This patch does the following changes to support 52bit PA.
>>>   -Handle 52bit PA in GITS_BASERn.
>>>   -Fix ITT_addr width to 52bits, bits[51:8].
>>>   -Fix RDbase width to 52bits, bits[51:16].
>>>   -Fix VPT_addr width to 52bits, bits[51:16].
>>>
>>> Definition of the GITS_BASERn register when ITS PageSize is 64KB:
>>>  -Bits[47:16] of the register provide bits[47:16] of the table PA.
>>>  -Bits[15:12] of the register provide bits[51:48] of the table PA.
>>>  -Bits[15:00] of the base physical address are 0.
>>>
>>> Signed-off-by: Shanker Donthineni <shank...@codeaurora.org>
>>> ---
>>>  drivers/irqchip/irq-gic-v3-its.c   | 24 +++++++++++++++++++-----
>>>  include/linux/irqchip/arm-gic-v3.h |  3 +++
>>>  2 files changed, 22 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>>> b/drivers/irqchip/irq-gic-v3-its.c
>>> index e8d8934..e52c0da 100644
>>> --- a/drivers/irqchip/irq-gic-v3-its.c
>>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>>> @@ -308,7 +308,7 @@ static void its_encode_size(struct its_cmd_block *cmd, 
>>> u8 size)
>>>  
>>>  static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
>>>  {
>>> -   its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 50, 8);
>>> +   its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8);
>>>  }
>>>  
>>>  static void its_encode_valid(struct its_cmd_block *cmd, int valid)
>>> @@ -318,7 +318,7 @@ static void its_encode_valid(struct its_cmd_block *cmd, 
>>> int valid)
>>>  
>>>  static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
>>>  {
>>> -   its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 50, 16);
>>> +   its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16);
>>>  }
>>>  
>>>  static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
>>> @@ -358,7 +358,7 @@ static void its_encode_its_list(struct its_cmd_block 
>>> *cmd, u16 its_list)
>>>  
>>>  static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa)
>>>  {
>>> -   its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 50, 16);
>>> +   its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 51, 16);
>>>  }
>>>  
>>>  static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size)
>>> @@ -1478,9 +1478,9 @@ static int its_setup_baser(struct its_node *its, 
>>> struct its_baser *baser,
>>>     u64 val = its_read_baser(its, baser);
>>>     u64 esz = GITS_BASER_ENTRY_SIZE(val);
>>>     u64 type = GITS_BASER_TYPE(val);
>>> +   u64 baser_phys, tmp;
>>>     u32 alloc_pages;
>>>     void *base;
>>> -   u64 tmp;
>>>  
>>>  retry_alloc_baser:
>>>     alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
>>> @@ -1496,8 +1496,22 @@ static int its_setup_baser(struct its_node *its, 
>>> struct its_baser *baser,
>>>     if (!base)
>>>             return -ENOMEM;
>>>  
>>> +   baser_phys = virt_to_phys(base);
>>> +
>>> +   /* Check if the physical address of the memory is above 48bits */
>>> +   if (baser_phys & (~GITS_BASER_PHYS_MASK)) {
>>> +           /* 52bit PA is supported only when PageSize=64K */
>>> +           if (psz != SZ_64K) {
>>> +                   free_pages((unsigned long)base, order);
>>> +                   return -EFAULT;
>>> +           }
>>> +
>>> +           /* Convert 52bit PA to 48bit field */
>>> +           baser_phys = GITS_BASER_64K_PHYS(baser_phys);
>>> +   }
>>
>> I'm not sure this is completely right. What guarantees that the memory
>> you get is 64kB aligned? Your initial masking will do the wrong thing on
>> a system with 16kB pages, and everything will break from that point on,
>> as you're confusing the ITS page size with the CPU page size.
>>
> 
> The first is check right, and the intention was to find out the upper bits
> of the PA (bits[51:12]) have non-zero value irrespective of PS 64K/16K/4KB.
> 
> #define GITS_BASER_PHYS_MASK          GENMASK_ULL(47, 12)    
> 
> (baser_phys & (~GITS_BASER_PHYS_MASK)) becomes (baser_phys & 0xFFFF 0000 0000 
> 0000)
> 
> We program GITS_BASERn PageSize based on 'psz' value.
> 
> However the current code has a hidden bug, we assume memory allocation is 
> aligned
> on 64K/16K when the ITS PageSize (variable of 'psz') is 64K/16K. We have two 
> options
> to solve the problem.
> 
>  -fall-baclk to a lower ITS PageSize if the memory size is lower than 'psz'.
>  -allocate minimum of 64K for all BASERn tables.
> 
> 
>  Something like using the second method.
> 
>   retry_alloc_baser:
>      alloc_pages = (min(PAGE_ORDER_TO_SIZE(order), 64K) / psz);
> 
>   ....
> 
>      baser_phys = virt_to_phys(base);
>  
>      /* Check if the physical address of the memory is above 48bits */
>      if (baser_phys & (~GITS_BASER_PHYS_MASK)) {
>          /* 52bit PA is supported only when PageSize=64K */
>          if (psz != SZ_64K) {
>               free_pages((unsigned long)base, order);
>               return -EFAULT;
>          }
>  
>          /* Convert 52bit PA to 48bit field */
>          baser_phys = GITS_BASER_64K_PHYS(baser_phys);
>      }
> 
>

I've included your suggestion in v2 patch 
https://patchwork.kernel.org/patch/9991405/ even though
it's not really required. But it helps to understand the code changes better 
and I also added a
warning message in case of not supporting 52bit PA. Please comment on v2 patch 
if any thing I missed.


-- 
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.

Reply via email to