diff mbox series

[20/25] spapr: add device tree support for the XIVE interrupt mode

Message ID 20171123132955.1261-21-clg@kaod.org
State New
Headers show
Series spapr: Guest exploitation of the XIVE interrupt controller (POWER9) | expand

Commit Message

Cédric Le Goater Nov. 23, 2017, 1:29 p.m. UTC
The XIVE interface for the guest is described in the device tree under
the "interrupt-controller" node. A couple of new properties are
specific to XIVE :

 - "reg"

   contains the base address and size of the thread interrupt
   managnement areas (TIMA), also called rings, for the User level and
   for the Guest OS level. Only the Guest OS level is taken into
   account today.

 - "ibm,xive-eq-sizes"

   the size of the event queues. One cell per size supported, contains
   log2 of size, in ascending order.

 - "ibm,xive-lisn-ranges"

   the interrupt numbers ranges assigned to the guest. These are
   allocated using a simple bitmap.

and also under the root node :

 - "ibm,plat-res-int-priorities"

   contains a list of priorities that the hypervisor has reserved for
   its own use. Simulate ranges as defined by the PowerVM Hypervisor.

When the XIVE interrupt mode is activated after the CAS negotiation,
the machine will perform a reboot to rebuild the device tree.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/intc/spapr_xive_hcall.c  | 50 +++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/spapr.c              |  7 ++++++-
 hw/ppc/spapr_hcall.c        |  6 ++++++
 include/hw/ppc/spapr_xive.h |  2 ++
 4 files changed, 64 insertions(+), 1 deletion(-)

Comments

David Gibson Dec. 4, 2017, 7:49 a.m. UTC | #1
On Thu, Nov 23, 2017 at 02:29:50PM +0100, Cédric Le Goater wrote:
> The XIVE interface for the guest is described in the device tree under
> the "interrupt-controller" node. A couple of new properties are
> specific to XIVE :
> 
>  - "reg"
> 
>    contains the base address and size of the thread interrupt
>    managnement areas (TIMA), also called rings, for the User level and
>    for the Guest OS level. Only the Guest OS level is taken into
>    account today.
> 
>  - "ibm,xive-eq-sizes"
> 
>    the size of the event queues. One cell per size supported, contains
>    log2 of size, in ascending order.
> 
>  - "ibm,xive-lisn-ranges"
> 
>    the interrupt numbers ranges assigned to the guest. These are
>    allocated using a simple bitmap.
> 
> and also under the root node :
> 
>  - "ibm,plat-res-int-priorities"
> 
>    contains a list of priorities that the hypervisor has reserved for
>    its own use. Simulate ranges as defined by the PowerVM Hypervisor.
> 
> When the XIVE interrupt mode is activated after the CAS negotiation,
> the machine will perform a reboot to rebuild the device tree.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/intc/spapr_xive_hcall.c  | 50 +++++++++++++++++++++++++++++++++++++++++++++
>  hw/ppc/spapr.c              |  7 ++++++-
>  hw/ppc/spapr_hcall.c        |  6 ++++++
>  include/hw/ppc/spapr_xive.h |  2 ++
>  4 files changed, 64 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c
> index 676fe0e2d5c7..60c6c9f4be8f 100644
> --- a/hw/intc/spapr_xive_hcall.c
> +++ b/hw/intc/spapr_xive_hcall.c
> @@ -883,3 +883,53 @@ void spapr_xive_hcall_init(sPAPRMachineState *spapr)
>      spapr_register_hypercall(H_INT_SYNC, h_int_sync);
>      spapr_register_hypercall(H_INT_RESET, h_int_reset);
>  }
> +
> +void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers,
> +                         void *fdt, uint32_t phandle)

Call it spapr_dt_xive() please, I'm trying to standardize on that
pattern for functions creating DT pieces.

> +{
> +    sPAPRXive *xive = spapr->xive;
> +    int node;
> +    uint64_t timas[2 * 2];
> +    uint32_t lisn_ranges[] = {
> +        cpu_to_be32(0),
> +        cpu_to_be32(nr_servers),
> +    };
> +    uint32_t eq_sizes[] = {
> +        cpu_to_be32(12), /* 4K */
> +        cpu_to_be32(16), /* 64K */
> +        cpu_to_be32(21), /* 2M */
> +        cpu_to_be32(24), /* 16M */
> +    };
> +    uint32_t plat_res_int_priorities[ARRAY_SIZE(reserved_priorities)];
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(plat_res_int_priorities); i++) {
> +        plat_res_int_priorities[i] = cpu_to_be32(reserved_priorities[i]);
> +    }
> +
> +    /* Thread Interrupt Management Areas : User and OS */
> +    for (i = 0; i < 2; i++) {
> +        timas[i * 2] = cpu_to_be64(xive->tm_base + i * (1 << xive->tm_shift));
> +        timas[i * 2 + 1] = cpu_to_be64(1 << xive->tm_shift);
> +    }
> +
> +    _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));

You need a unit address here matching the reg property.

> +
> +    _FDT(fdt_setprop_string(fdt, node, "name", "interrupt-controller"));

You don't need to set name properties explicitly for flattened trees.

> +    _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
> +    _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
> +
> +    _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe"));
> +    _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes,
> +                     sizeof(eq_sizes)));
> +    _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges,
> +                     sizeof(lisn_ranges)));
> +
> +    /* For SLOF */
> +    _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
> +    _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
> +
> +    /* top properties */
> +    _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities",
> +                     plat_res_int_priorities, sizeof(plat_res_int_priorities)));
> +}
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 8b15c0b500d0..3a62369883cc 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1127,7 +1127,12 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
>      _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
>  
>      /* /interrupt controller */
> -    spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
> +    if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> +        spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
> +    } else {
> +        /* Populate device tree for XIVE */
> +        spapr_xive_populate(spapr, xics_max_server_number(), fdt, PHANDLE_XICP);
> +    }
>  
>      ret = spapr_populate_memory(spapr, fdt);
>      if (ret < 0) {
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index be22a6b2895f..e2a1665beee9 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -1646,6 +1646,12 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>              (spapr_h_cas_compose_response(spapr, args[1], args[2],
>                                            ov5_updates) != 0);
>      }
> +
> +    /* We need to rebuild the device tree for XIVE, generate a reset */
> +    if (!spapr->cas_reboot) {
> +        spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT);
> +    }
> +
>      spapr_ovec_cleanup(ov5_updates);
>  
>      if (spapr->cas_reboot) {
> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
> index 3f822220647f..f6d4bf26e06a 100644
> --- a/include/hw/ppc/spapr_xive.h
> +++ b/include/hw/ppc/spapr_xive.h
> @@ -82,5 +82,7 @@ void spapr_xive_icp_pic_print_info(sPAPRXiveICP *xicp, Monitor *mon);
>  typedef struct sPAPRMachineState sPAPRMachineState;
>  
>  void spapr_xive_hcall_init(sPAPRMachineState *spapr);
> +void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers, void *fdt,
> +                         uint32_t phandle);
>  
>  #endif /* PPC_SPAPR_XIVE_H */
Cédric Le Goater Dec. 4, 2017, 4:19 p.m. UTC | #2
On 12/04/2017 08:49 AM, David Gibson wrote:
> On Thu, Nov 23, 2017 at 02:29:50PM +0100, Cédric Le Goater wrote:
>> The XIVE interface for the guest is described in the device tree under
>> the "interrupt-controller" node. A couple of new properties are
>> specific to XIVE :
>>
>>  - "reg"
>>
>>    contains the base address and size of the thread interrupt
>>    managnement areas (TIMA), also called rings, for the User level and
>>    for the Guest OS level. Only the Guest OS level is taken into
>>    account today.
>>
>>  - "ibm,xive-eq-sizes"
>>
>>    the size of the event queues. One cell per size supported, contains
>>    log2 of size, in ascending order.
>>
>>  - "ibm,xive-lisn-ranges"
>>
>>    the interrupt numbers ranges assigned to the guest. These are
>>    allocated using a simple bitmap.
>>
>> and also under the root node :
>>
>>  - "ibm,plat-res-int-priorities"
>>
>>    contains a list of priorities that the hypervisor has reserved for
>>    its own use. Simulate ranges as defined by the PowerVM Hypervisor.
>>
>> When the XIVE interrupt mode is activated after the CAS negotiation,
>> the machine will perform a reboot to rebuild the device tree.
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/intc/spapr_xive_hcall.c  | 50 +++++++++++++++++++++++++++++++++++++++++++++
>>  hw/ppc/spapr.c              |  7 ++++++-
>>  hw/ppc/spapr_hcall.c        |  6 ++++++
>>  include/hw/ppc/spapr_xive.h |  2 ++
>>  4 files changed, 64 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c
>> index 676fe0e2d5c7..60c6c9f4be8f 100644
>> --- a/hw/intc/spapr_xive_hcall.c
>> +++ b/hw/intc/spapr_xive_hcall.c
>> @@ -883,3 +883,53 @@ void spapr_xive_hcall_init(sPAPRMachineState *spapr)
>>      spapr_register_hypercall(H_INT_SYNC, h_int_sync);
>>      spapr_register_hypercall(H_INT_RESET, h_int_reset);
>>  }
>> +
>> +void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers,
>> +                         void *fdt, uint32_t phandle)
> 
> Call it spapr_dt_xive() please, I'm trying to standardize on that
> pattern for functions creating DT pieces.

OK. And what about the first argument : sPAPRMachineState *spapr 
or sPAPRXive *xive ? I tend to prefer the first option because
it's related to the interface with the guest, like the hcalls.

> 
>> +{
>> +    sPAPRXive *xive = spapr->xive;
>> +    int node;
>> +    uint64_t timas[2 * 2];
>> +    uint32_t lisn_ranges[] = {
>> +        cpu_to_be32(0),
>> +        cpu_to_be32(nr_servers),
>> +    };
>> +    uint32_t eq_sizes[] = {
>> +        cpu_to_be32(12), /* 4K */
>> +        cpu_to_be32(16), /* 64K */
>> +        cpu_to_be32(21), /* 2M */
>> +        cpu_to_be32(24), /* 16M */
>> +    };
>> +    uint32_t plat_res_int_priorities[ARRAY_SIZE(reserved_priorities)];
>> +    int i;
>> +
>> +    for (i = 0; i < ARRAY_SIZE(plat_res_int_priorities); i++) {
>> +        plat_res_int_priorities[i] = cpu_to_be32(reserved_priorities[i]);
>> +    }
>> +
>> +    /* Thread Interrupt Management Areas : User and OS */
>> +    for (i = 0; i < 2; i++) {
>> +        timas[i * 2] = cpu_to_be64(xive->tm_base + i * (1 << xive->tm_shift));
>> +        timas[i * 2 + 1] = cpu_to_be64(1 << xive->tm_shift);
>> +    }
>> +
>> +    _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
> 
> You need a unit address here matching the reg property.

Indeed. I didn't notice. Curiously it was taking the first address 
specified in the reg property of the node.

>> +
>> +    _FDT(fdt_setprop_string(fdt, node, "name", "interrupt-controller"));
> 
> You don't need to set name properties explicitly for flattened trees.

OK.

Thanks,

C. 



>> +    _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
>> +    _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
>> +
>> +    _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe"));
>> +    _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes,
>> +                     sizeof(eq_sizes)));
>> +    _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges,
>> +                     sizeof(lisn_ranges)));
>> +
>> +    /* For SLOF */
>> +    _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
>> +    _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
>> +
>> +    /* top properties */
>> +    _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities",
>> +                     plat_res_int_priorities, sizeof(plat_res_int_priorities)));
>> +}
>> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
>> index 8b15c0b500d0..3a62369883cc 100644
>> --- a/hw/ppc/spapr.c
>> +++ b/hw/ppc/spapr.c
>> @@ -1127,7 +1127,12 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
>>      _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
>>  
>>      /* /interrupt controller */
>> -    spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
>> +    if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
>> +        spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
>> +    } else {
>> +        /* Populate device tree for XIVE */
>> +        spapr_xive_populate(spapr, xics_max_server_number(), fdt, PHANDLE_XICP);
>> +    }
>>  
>>      ret = spapr_populate_memory(spapr, fdt);
>>      if (ret < 0) {
>> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
>> index be22a6b2895f..e2a1665beee9 100644
>> --- a/hw/ppc/spapr_hcall.c
>> +++ b/hw/ppc/spapr_hcall.c
>> @@ -1646,6 +1646,12 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>>              (spapr_h_cas_compose_response(spapr, args[1], args[2],
>>                                            ov5_updates) != 0);
>>      }
>> +
>> +    /* We need to rebuild the device tree for XIVE, generate a reset */
>> +    if (!spapr->cas_reboot) {
>> +        spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT);
>> +    }
>> +
>>      spapr_ovec_cleanup(ov5_updates);
>>  
>>      if (spapr->cas_reboot) {
>> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
>> index 3f822220647f..f6d4bf26e06a 100644
>> --- a/include/hw/ppc/spapr_xive.h
>> +++ b/include/hw/ppc/spapr_xive.h
>> @@ -82,5 +82,7 @@ void spapr_xive_icp_pic_print_info(sPAPRXiveICP *xicp, Monitor *mon);
>>  typedef struct sPAPRMachineState sPAPRMachineState;
>>  
>>  void spapr_xive_hcall_init(sPAPRMachineState *spapr);
>> +void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers, void *fdt,
>> +                         uint32_t phandle);
>>  
>>  #endif /* PPC_SPAPR_XIVE_H */
>
David Gibson Dec. 5, 2017, 3:38 a.m. UTC | #3
On Mon, Dec 04, 2017 at 05:19:03PM +0100, Cédric Le Goater wrote:
> On 12/04/2017 08:49 AM, David Gibson wrote:
> > On Thu, Nov 23, 2017 at 02:29:50PM +0100, Cédric Le Goater wrote:
> >> The XIVE interface for the guest is described in the device tree under
> >> the "interrupt-controller" node. A couple of new properties are
> >> specific to XIVE :
> >>
> >>  - "reg"
> >>
> >>    contains the base address and size of the thread interrupt
> >>    managnement areas (TIMA), also called rings, for the User level and
> >>    for the Guest OS level. Only the Guest OS level is taken into
> >>    account today.
> >>
> >>  - "ibm,xive-eq-sizes"
> >>
> >>    the size of the event queues. One cell per size supported, contains
> >>    log2 of size, in ascending order.
> >>
> >>  - "ibm,xive-lisn-ranges"
> >>
> >>    the interrupt numbers ranges assigned to the guest. These are
> >>    allocated using a simple bitmap.
> >>
> >> and also under the root node :
> >>
> >>  - "ibm,plat-res-int-priorities"
> >>
> >>    contains a list of priorities that the hypervisor has reserved for
> >>    its own use. Simulate ranges as defined by the PowerVM Hypervisor.
> >>
> >> When the XIVE interrupt mode is activated after the CAS negotiation,
> >> the machine will perform a reboot to rebuild the device tree.
> >>
> >> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> >> ---
> >>  hw/intc/spapr_xive_hcall.c  | 50 +++++++++++++++++++++++++++++++++++++++++++++
> >>  hw/ppc/spapr.c              |  7 ++++++-
> >>  hw/ppc/spapr_hcall.c        |  6 ++++++
> >>  include/hw/ppc/spapr_xive.h |  2 ++
> >>  4 files changed, 64 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c
> >> index 676fe0e2d5c7..60c6c9f4be8f 100644
> >> --- a/hw/intc/spapr_xive_hcall.c
> >> +++ b/hw/intc/spapr_xive_hcall.c
> >> @@ -883,3 +883,53 @@ void spapr_xive_hcall_init(sPAPRMachineState *spapr)
> >>      spapr_register_hypercall(H_INT_SYNC, h_int_sync);
> >>      spapr_register_hypercall(H_INT_RESET, h_int_reset);
> >>  }
> >> +
> >> +void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers,
> >> +                         void *fdt, uint32_t phandle)
> > 
> > Call it spapr_dt_xive() please, I'm trying to standardize on that
> > pattern for functions creating DT pieces.
> 
> OK. And what about the first argument : sPAPRMachineState *spapr 
> or sPAPRXive *xive ? I tend to prefer the first option because
> it's related to the interface with the guest, like the hcalls.

Yes, using the MachineState as the first parameter is fine.

> 
> > 
> >> +{
> >> +    sPAPRXive *xive = spapr->xive;
> >> +    int node;
> >> +    uint64_t timas[2 * 2];
> >> +    uint32_t lisn_ranges[] = {
> >> +        cpu_to_be32(0),
> >> +        cpu_to_be32(nr_servers),
> >> +    };
> >> +    uint32_t eq_sizes[] = {
> >> +        cpu_to_be32(12), /* 4K */
> >> +        cpu_to_be32(16), /* 64K */
> >> +        cpu_to_be32(21), /* 2M */
> >> +        cpu_to_be32(24), /* 16M */
> >> +    };
> >> +    uint32_t plat_res_int_priorities[ARRAY_SIZE(reserved_priorities)];
> >> +    int i;
> >> +
> >> +    for (i = 0; i < ARRAY_SIZE(plat_res_int_priorities); i++) {
> >> +        plat_res_int_priorities[i] = cpu_to_be32(reserved_priorities[i]);
> >> +    }
> >> +
> >> +    /* Thread Interrupt Management Areas : User and OS */
> >> +    for (i = 0; i < 2; i++) {
> >> +        timas[i * 2] = cpu_to_be64(xive->tm_base + i * (1 << xive->tm_shift));
> >> +        timas[i * 2 + 1] = cpu_to_be64(1 << xive->tm_shift);
> >> +    }
> >> +
> >> +    _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
> > 
> > You need a unit address here matching the reg property.
> 
> Indeed. I didn't notice. Curiously it was taking the first address 
> specified in the reg property of the node.

I'm guessing that's SLOF's intervention.

> 
> >> +
> >> +    _FDT(fdt_setprop_string(fdt, node, "name", "interrupt-controller"));
> > 
> > You don't need to set name properties explicitly for flattened trees.
> 
> OK.
> 
> Thanks,
> 
> C. 
> 
> 
> 
> >> +    _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
> >> +    _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
> >> +
> >> +    _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe"));
> >> +    _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes,
> >> +                     sizeof(eq_sizes)));
> >> +    _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges,
> >> +                     sizeof(lisn_ranges)));
> >> +
> >> +    /* For SLOF */
> >> +    _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
> >> +    _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
> >> +
> >> +    /* top properties */
> >> +    _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities",
> >> +                     plat_res_int_priorities, sizeof(plat_res_int_priorities)));
> >> +}
> >> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> >> index 8b15c0b500d0..3a62369883cc 100644
> >> --- a/hw/ppc/spapr.c
> >> +++ b/hw/ppc/spapr.c
> >> @@ -1127,7 +1127,12 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> >>      _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
> >>  
> >>      /* /interrupt controller */
> >> -    spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
> >> +    if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
> >> +        spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
> >> +    } else {
> >> +        /* Populate device tree for XIVE */
> >> +        spapr_xive_populate(spapr, xics_max_server_number(), fdt, PHANDLE_XICP);
> >> +    }
> >>  
> >>      ret = spapr_populate_memory(spapr, fdt);
> >>      if (ret < 0) {
> >> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> >> index be22a6b2895f..e2a1665beee9 100644
> >> --- a/hw/ppc/spapr_hcall.c
> >> +++ b/hw/ppc/spapr_hcall.c
> >> @@ -1646,6 +1646,12 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
> >>              (spapr_h_cas_compose_response(spapr, args[1], args[2],
> >>                                            ov5_updates) != 0);
> >>      }
> >> +
> >> +    /* We need to rebuild the device tree for XIVE, generate a reset */
> >> +    if (!spapr->cas_reboot) {
> >> +        spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT);
> >> +    }
> >> +
> >>      spapr_ovec_cleanup(ov5_updates);
> >>  
> >>      if (spapr->cas_reboot) {
> >> diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
> >> index 3f822220647f..f6d4bf26e06a 100644
> >> --- a/include/hw/ppc/spapr_xive.h
> >> +++ b/include/hw/ppc/spapr_xive.h
> >> @@ -82,5 +82,7 @@ void spapr_xive_icp_pic_print_info(sPAPRXiveICP *xicp, Monitor *mon);
> >>  typedef struct sPAPRMachineState sPAPRMachineState;
> >>  
> >>  void spapr_xive_hcall_init(sPAPRMachineState *spapr);
> >> +void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers, void *fdt,
> >> +                         uint32_t phandle);
> >>  
> >>  #endif /* PPC_SPAPR_XIVE_H */
> > 
>
diff mbox series

Patch

diff --git a/hw/intc/spapr_xive_hcall.c b/hw/intc/spapr_xive_hcall.c
index 676fe0e2d5c7..60c6c9f4be8f 100644
--- a/hw/intc/spapr_xive_hcall.c
+++ b/hw/intc/spapr_xive_hcall.c
@@ -883,3 +883,53 @@  void spapr_xive_hcall_init(sPAPRMachineState *spapr)
     spapr_register_hypercall(H_INT_SYNC, h_int_sync);
     spapr_register_hypercall(H_INT_RESET, h_int_reset);
 }
+
+void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers,
+                         void *fdt, uint32_t phandle)
+{
+    sPAPRXive *xive = spapr->xive;
+    int node;
+    uint64_t timas[2 * 2];
+    uint32_t lisn_ranges[] = {
+        cpu_to_be32(0),
+        cpu_to_be32(nr_servers),
+    };
+    uint32_t eq_sizes[] = {
+        cpu_to_be32(12), /* 4K */
+        cpu_to_be32(16), /* 64K */
+        cpu_to_be32(21), /* 2M */
+        cpu_to_be32(24), /* 16M */
+    };
+    uint32_t plat_res_int_priorities[ARRAY_SIZE(reserved_priorities)];
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(plat_res_int_priorities); i++) {
+        plat_res_int_priorities[i] = cpu_to_be32(reserved_priorities[i]);
+    }
+
+    /* Thread Interrupt Management Areas : User and OS */
+    for (i = 0; i < 2; i++) {
+        timas[i * 2] = cpu_to_be64(xive->tm_base + i * (1 << xive->tm_shift));
+        timas[i * 2 + 1] = cpu_to_be64(1 << xive->tm_shift);
+    }
+
+    _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
+
+    _FDT(fdt_setprop_string(fdt, node, "name", "interrupt-controller"));
+    _FDT(fdt_setprop_string(fdt, node, "device_type", "power-ivpe"));
+    _FDT(fdt_setprop(fdt, node, "reg", timas, sizeof(timas)));
+
+    _FDT(fdt_setprop_string(fdt, node, "compatible", "ibm,power-ivpe"));
+    _FDT(fdt_setprop(fdt, node, "ibm,xive-eq-sizes", eq_sizes,
+                     sizeof(eq_sizes)));
+    _FDT(fdt_setprop(fdt, node, "ibm,xive-lisn-ranges", lisn_ranges,
+                     sizeof(lisn_ranges)));
+
+    /* For SLOF */
+    _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
+    _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
+
+    /* top properties */
+    _FDT(fdt_setprop(fdt, 0, "ibm,plat-res-int-priorities",
+                     plat_res_int_priorities, sizeof(plat_res_int_priorities)));
+}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 8b15c0b500d0..3a62369883cc 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1127,7 +1127,12 @@  static void *spapr_build_fdt(sPAPRMachineState *spapr,
     _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
 
     /* /interrupt controller */
-    spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
+    if (!spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
+        spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP);
+    } else {
+        /* Populate device tree for XIVE */
+        spapr_xive_populate(spapr, xics_max_server_number(), fdt, PHANDLE_XICP);
+    }
 
     ret = spapr_populate_memory(spapr, fdt);
     if (ret < 0) {
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index be22a6b2895f..e2a1665beee9 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1646,6 +1646,12 @@  static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
             (spapr_h_cas_compose_response(spapr, args[1], args[2],
                                           ov5_updates) != 0);
     }
+
+    /* We need to rebuild the device tree for XIVE, generate a reset */
+    if (!spapr->cas_reboot) {
+        spapr->cas_reboot = spapr_ovec_test(ov5_updates, OV5_XIVE_EXPLOIT);
+    }
+
     spapr_ovec_cleanup(ov5_updates);
 
     if (spapr->cas_reboot) {
diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h
index 3f822220647f..f6d4bf26e06a 100644
--- a/include/hw/ppc/spapr_xive.h
+++ b/include/hw/ppc/spapr_xive.h
@@ -82,5 +82,7 @@  void spapr_xive_icp_pic_print_info(sPAPRXiveICP *xicp, Monitor *mon);
 typedef struct sPAPRMachineState sPAPRMachineState;
 
 void spapr_xive_hcall_init(sPAPRMachineState *spapr);
+void spapr_xive_populate(sPAPRMachineState *spapr, int nr_servers, void *fdt,
+                         uint32_t phandle);
 
 #endif /* PPC_SPAPR_XIVE_H */