diff mbox series

[RESEND,08/15] ppc: spapr: Implement nested PAPR hcall - H_GUEST_CREATE

Message ID 20230906043333.448244-9-harshpb@linux.ibm.com
State New
Headers show
Series Nested PAPR API (KVM on PowerVM) | expand

Commit Message

Harsh Prateek Bora Sept. 6, 2023, 4:33 a.m. UTC
This hcall is used by L1 to indicate to L0 that a new nested guest needs
to be created and therefore necessary resource allocation shall be made.
The L0 uses a hash table for nested guest specific resource management.
This data structure is further utilized by other hcalls to operate on
related members during entire life cycle of the nested guest.

Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
---
 hw/ppc/spapr_nested.c         | 75 +++++++++++++++++++++++++++++++++++
 include/hw/ppc/spapr_nested.h |  3 ++
 2 files changed, 78 insertions(+)

Comments

Nicholas Piggin Sept. 7, 2023, 2:28 a.m. UTC | #1
On Wed Sep 6, 2023 at 2:33 PM AEST, Harsh Prateek Bora wrote:
> This hcall is used by L1 to indicate to L0 that a new nested guest needs
> to be created and therefore necessary resource allocation shall be made.
> The L0 uses a hash table for nested guest specific resource management.
> This data structure is further utilized by other hcalls to operate on
> related members during entire life cycle of the nested guest.

Similar comment for changelog re detail. Detailed specification of API
and implementation could go in comments or documentation if useful.

>
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
> Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
> ---
>  hw/ppc/spapr_nested.c         | 75 +++++++++++++++++++++++++++++++++++
>  include/hw/ppc/spapr_nested.h |  3 ++
>  2 files changed, 78 insertions(+)
>
> diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c
> index 9af65f257f..09bbbfb341 100644
> --- a/hw/ppc/spapr_nested.c
> +++ b/hw/ppc/spapr_nested.c
> @@ -444,6 +444,80 @@ static target_ulong h_guest_set_capabilities(PowerPCCPU *cpu,
>      return H_SUCCESS;
>  }
>  
> +static void
> +destroy_guest_helper(gpointer value)
> +{
> +    struct SpaprMachineStateNestedGuest *guest = value;
> +    g_free(guest);
> +}
> +
> +static target_ulong h_guest_create(PowerPCCPU *cpu,
> +                                   SpaprMachineState *spapr,
> +                                   target_ulong opcode,
> +                                   target_ulong *args)
> +{
> +    CPUPPCState *env = &cpu->env;
> +    target_ulong flags = args[0];
> +    target_ulong continue_token = args[1];
> +    uint64_t lpid;
> +    int nguests = 0;
> +    struct SpaprMachineStateNestedGuest *guest;
> +
> +    if (flags) { /* don't handle any flags for now */
> +        return H_UNSUPPORTED_FLAG;
> +    }
> +
> +    if (continue_token != -1) {
> +        return H_P2;
> +    }
> +
> +    if (!spapr_get_cap(spapr, SPAPR_CAP_NESTED_PAPR)) {
> +        return H_FUNCTION;
> +    }
> +
> +    if (!spapr->nested.capabilities_set) {
> +        return H_STATE;
> +    }
> +
> +    if (!spapr->nested.guests) {
> +        spapr->nested.lpid_max = NESTED_GUEST_MAX;
> +        spapr->nested.guests = g_hash_table_new_full(NULL,
> +                                                     NULL,
> +                                                     NULL,
> +                                                     destroy_guest_helper);

Is lpid_max only used by create? Probably no need to have it in spapr
then->nested then. Also, do we even need to have a limit?

> +    }
> +
> +    nguests = g_hash_table_size(spapr->nested.guests);
> +
> +    if (nguests == spapr->nested.lpid_max) {
> +        return H_NO_MEM;
> +    }
> +
> +    /* Lookup for available lpid */
> +    for (lpid = 1; lpid < spapr->nested.lpid_max; lpid++) {

PAPR API calls it "guest ID" I think. Should change all references to
lpid to that.

> +        if (!(g_hash_table_lookup(spapr->nested.guests,
> +                                  GINT_TO_POINTER(lpid)))) {
> +            break;
> +        }
> +    }
> +    if (lpid == spapr->nested.lpid_max) {
> +        return H_NO_MEM;
> +    }
> +
> +    guest = g_try_new0(struct SpaprMachineStateNestedGuest, 1);
> +    if (!guest) {
> +        return H_NO_MEM;
> +    }
> +
> +    guest->pvr_logical = spapr->nested.pvr_base;
> +
> +    g_hash_table_insert(spapr->nested.guests, GINT_TO_POINTER(lpid), guest);
> +    printf("%s: lpid: %lu (MAX: %i)\n", __func__, lpid, spapr->nested.lpid_max);

Remove printf.

> +
> +    env->gpr[4] = lpid;
> +    return H_SUCCESS;
> +}
> +
>  void spapr_register_nested(void)
>  {
>      spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl);
> @@ -456,6 +530,7 @@ void spapr_register_nested_phyp(void)
>  {
>      spapr_register_hypercall(H_GUEST_GET_CAPABILITIES, h_guest_get_capabilities);
>      spapr_register_hypercall(H_GUEST_SET_CAPABILITIES, h_guest_set_capabilities);
> +    spapr_register_hypercall(H_GUEST_CREATE          , h_guest_create);
>  }
>  
>  #else
> diff --git a/include/hw/ppc/spapr_nested.h b/include/hw/ppc/spapr_nested.h
> index a7996251cb..7841027df8 100644
> --- a/include/hw/ppc/spapr_nested.h
> +++ b/include/hw/ppc/spapr_nested.h
> @@ -197,6 +197,9 @@
>  #define H_GUEST_CAP_P9_MODE_BMAP    1
>  #define H_GUEST_CAP_P10_MODE_BMAP   2
>  
> +/* Nested PAPR API macros */
> +#define NESTED_GUEST_MAX 4096

Prefix with PAPR_?

Thanks,
Nick

> +
>  typedef struct SpaprMachineStateNestedGuest {
>      unsigned long vcpus;
>      struct SpaprMachineStateNestedGuestVcpu *vcpu;
Harsh Prateek Bora Oct. 3, 2023, 7:57 a.m. UTC | #2
On 9/7/23 07:58, Nicholas Piggin wrote:
> On Wed Sep 6, 2023 at 2:33 PM AEST, Harsh Prateek Bora wrote:
>> This hcall is used by L1 to indicate to L0 that a new nested guest needs
>> to be created and therefore necessary resource allocation shall be made.
>> The L0 uses a hash table for nested guest specific resource management.
>> This data structure is further utilized by other hcalls to operate on
>> related members during entire life cycle of the nested guest.
> 
> Similar comment for changelog re detail. Detailed specification of API
> and implementation could go in comments or documentation if useful.
> 
Sure, squashing guest create/delete together and updating commit log to 
be abstract as needed.

>>
>> Signed-off-by: Michael Neuling <mikey@neuling.org>
>> Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
>> Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
>> ---
>>   hw/ppc/spapr_nested.c         | 75 +++++++++++++++++++++++++++++++++++
>>   include/hw/ppc/spapr_nested.h |  3 ++
>>   2 files changed, 78 insertions(+)
>>
>> diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c
>> index 9af65f257f..09bbbfb341 100644
>> --- a/hw/ppc/spapr_nested.c
>> +++ b/hw/ppc/spapr_nested.c
>> @@ -444,6 +444,80 @@ static target_ulong h_guest_set_capabilities(PowerPCCPU *cpu,
>>       return H_SUCCESS;
>>   }
>>   
>> +static void
>> +destroy_guest_helper(gpointer value)
>> +{
>> +    struct SpaprMachineStateNestedGuest *guest = value;
>> +    g_free(guest);
>> +}
>> +
>> +static target_ulong h_guest_create(PowerPCCPU *cpu,
>> +                                   SpaprMachineState *spapr,
>> +                                   target_ulong opcode,
>> +                                   target_ulong *args)
>> +{
>> +    CPUPPCState *env = &cpu->env;
>> +    target_ulong flags = args[0];
>> +    target_ulong continue_token = args[1];
>> +    uint64_t lpid;
>> +    int nguests = 0;
>> +    struct SpaprMachineStateNestedGuest *guest;
>> +
>> +    if (flags) { /* don't handle any flags for now */
>> +        return H_UNSUPPORTED_FLAG;
>> +    }
>> +
>> +    if (continue_token != -1) {
>> +        return H_P2;
>> +    }
>> +
>> +    if (!spapr_get_cap(spapr, SPAPR_CAP_NESTED_PAPR)) {
>> +        return H_FUNCTION;
>> +    }
>> +
>> +    if (!spapr->nested.capabilities_set) {
>> +        return H_STATE;
>> +    }
>> +
>> +    if (!spapr->nested.guests) {
>> +        spapr->nested.lpid_max = NESTED_GUEST_MAX;
>> +        spapr->nested.guests = g_hash_table_new_full(NULL,
>> +                                                     NULL,
>> +                                                     NULL,
>> +                                                     destroy_guest_helper);
> 
> Is lpid_max only used by create? Probably no need to have it in spapr
> then->nested then. Also, do we even need to have a limit?

Yes, as of now, it is being used only by create and doesnt need to part
of spapr->nested. We can simply use the macro for max guests. Keeping it
to emulate a finite resource model.
For all practical purposes, nested guests in an TCG emulated L0
shouldn't reach that limit.

> 
>> +    }
>> +
>> +    nguests = g_hash_table_size(spapr->nested.guests);
>> +
>> +    if (nguests == spapr->nested.lpid_max) {
>> +        return H_NO_MEM;
>> +    }
>> +
>> +    /* Lookup for available lpid */
>> +    for (lpid = 1; lpid < spapr->nested.lpid_max; lpid++) {
> 
> PAPR API calls it "guest ID" I think. Should change all references to
> lpid to that.

Changing it to "guestid".

> 
>> +        if (!(g_hash_table_lookup(spapr->nested.guests,
>> +                                  GINT_TO_POINTER(lpid)))) {
>> +            break;
>> +        }
>> +    }
>> +    if (lpid == spapr->nested.lpid_max) {
>> +        return H_NO_MEM;
>> +    }
>> +
>> +    guest = g_try_new0(struct SpaprMachineStateNestedGuest, 1);
>> +    if (!guest) {
>> +        return H_NO_MEM;
>> +    }
>> +
>> +    guest->pvr_logical = spapr->nested.pvr_base;
>> +
>> +    g_hash_table_insert(spapr->nested.guests, GINT_TO_POINTER(lpid), guest);
>> +    printf("%s: lpid: %lu (MAX: %i)\n", __func__, lpid, spapr->nested.lpid_max);
> 
> Remove printf.
> 
Done.

>> +
>> +    env->gpr[4] = lpid;
>> +    return H_SUCCESS;
>> +}
>> +
>>   void spapr_register_nested(void)
>>   {
>>       spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl);
>> @@ -456,6 +530,7 @@ void spapr_register_nested_phyp(void)
>>   {
>>       spapr_register_hypercall(H_GUEST_GET_CAPABILITIES, h_guest_get_capabilities);
>>       spapr_register_hypercall(H_GUEST_SET_CAPABILITIES, h_guest_set_capabilities);
>> +    spapr_register_hypercall(H_GUEST_CREATE          , h_guest_create);
>>   }
>>   
>>   #else
>> diff --git a/include/hw/ppc/spapr_nested.h b/include/hw/ppc/spapr_nested.h
>> index a7996251cb..7841027df8 100644
>> --- a/include/hw/ppc/spapr_nested.h
>> +++ b/include/hw/ppc/spapr_nested.h
>> @@ -197,6 +197,9 @@
>>   #define H_GUEST_CAP_P9_MODE_BMAP    1
>>   #define H_GUEST_CAP_P10_MODE_BMAP   2
>>   
>> +/* Nested PAPR API macros */
>> +#define NESTED_GUEST_MAX 4096
> 
> Prefix with PAPR_?

Done.

Thanks
Harsh
> 
> Thanks,
> Nick
> 
>> +
>>   typedef struct SpaprMachineStateNestedGuest {
>>       unsigned long vcpus;
>>       struct SpaprMachineStateNestedGuestVcpu *vcpu;
>
diff mbox series

Patch

diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c
index 9af65f257f..09bbbfb341 100644
--- a/hw/ppc/spapr_nested.c
+++ b/hw/ppc/spapr_nested.c
@@ -444,6 +444,80 @@  static target_ulong h_guest_set_capabilities(PowerPCCPU *cpu,
     return H_SUCCESS;
 }
 
+static void
+destroy_guest_helper(gpointer value)
+{
+    struct SpaprMachineStateNestedGuest *guest = value;
+    g_free(guest);
+}
+
+static target_ulong h_guest_create(PowerPCCPU *cpu,
+                                   SpaprMachineState *spapr,
+                                   target_ulong opcode,
+                                   target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong continue_token = args[1];
+    uint64_t lpid;
+    int nguests = 0;
+    struct SpaprMachineStateNestedGuest *guest;
+
+    if (flags) { /* don't handle any flags for now */
+        return H_UNSUPPORTED_FLAG;
+    }
+
+    if (continue_token != -1) {
+        return H_P2;
+    }
+
+    if (!spapr_get_cap(spapr, SPAPR_CAP_NESTED_PAPR)) {
+        return H_FUNCTION;
+    }
+
+    if (!spapr->nested.capabilities_set) {
+        return H_STATE;
+    }
+
+    if (!spapr->nested.guests) {
+        spapr->nested.lpid_max = NESTED_GUEST_MAX;
+        spapr->nested.guests = g_hash_table_new_full(NULL,
+                                                     NULL,
+                                                     NULL,
+                                                     destroy_guest_helper);
+    }
+
+    nguests = g_hash_table_size(spapr->nested.guests);
+
+    if (nguests == spapr->nested.lpid_max) {
+        return H_NO_MEM;
+    }
+
+    /* Lookup for available lpid */
+    for (lpid = 1; lpid < spapr->nested.lpid_max; lpid++) {
+        if (!(g_hash_table_lookup(spapr->nested.guests,
+                                  GINT_TO_POINTER(lpid)))) {
+            break;
+        }
+    }
+    if (lpid == spapr->nested.lpid_max) {
+        return H_NO_MEM;
+    }
+
+    guest = g_try_new0(struct SpaprMachineStateNestedGuest, 1);
+    if (!guest) {
+        return H_NO_MEM;
+    }
+
+    guest->pvr_logical = spapr->nested.pvr_base;
+
+    g_hash_table_insert(spapr->nested.guests, GINT_TO_POINTER(lpid), guest);
+    printf("%s: lpid: %lu (MAX: %i)\n", __func__, lpid, spapr->nested.lpid_max);
+
+    env->gpr[4] = lpid;
+    return H_SUCCESS;
+}
+
 void spapr_register_nested(void)
 {
     spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl);
@@ -456,6 +530,7 @@  void spapr_register_nested_phyp(void)
 {
     spapr_register_hypercall(H_GUEST_GET_CAPABILITIES, h_guest_get_capabilities);
     spapr_register_hypercall(H_GUEST_SET_CAPABILITIES, h_guest_set_capabilities);
+    spapr_register_hypercall(H_GUEST_CREATE          , h_guest_create);
 }
 
 #else
diff --git a/include/hw/ppc/spapr_nested.h b/include/hw/ppc/spapr_nested.h
index a7996251cb..7841027df8 100644
--- a/include/hw/ppc/spapr_nested.h
+++ b/include/hw/ppc/spapr_nested.h
@@ -197,6 +197,9 @@ 
 #define H_GUEST_CAP_P9_MODE_BMAP    1
 #define H_GUEST_CAP_P10_MODE_BMAP   2
 
+/* Nested PAPR API macros */
+#define NESTED_GUEST_MAX 4096
+
 typedef struct SpaprMachineStateNestedGuest {
     unsigned long vcpus;
     struct SpaprMachineStateNestedGuestVcpu *vcpu;