Skip to content

Commit

Permalink
spapr: nested: Introduce H_GUEST_[CREATE|DELETE] hcalls.
Browse files Browse the repository at this point in the history
Introduce the nested PAPR hcalls:
    - H_GUEST_CREATE which is used to create and allocate resources for
nested guest being created.
    - H_GUEST_DELETE which is used to delete and deallocate resources
for the nested guest being deleted. It also supports deleting all nested
guests at once using a deleteAll flag.

Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
  • Loading branch information
Harsh Prateek Bora authored and npiggin committed Mar 12, 2024
1 parent 71c33ef commit f560562
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
103 changes: 103 additions & 0 deletions hw/ppc/spapr_nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,105 @@ static target_ulong h_guest_set_capabilities(PowerPCCPU *cpu,
}
}

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 guestid;
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->nested.capabilities_set) {
return H_STATE;
}

if (!spapr->nested.guests) {
spapr->nested.guests = g_hash_table_new_full(NULL,
NULL,
NULL,
destroy_guest_helper);
}

nguests = g_hash_table_size(spapr->nested.guests);

if (nguests == PAPR_NESTED_GUEST_MAX) {
return H_NO_MEM;
}

/* Lookup for available guestid */
for (guestid = 1; guestid < PAPR_NESTED_GUEST_MAX; guestid++) {
if (!(g_hash_table_lookup(spapr->nested.guests,
GINT_TO_POINTER(guestid)))) {
break;
}
}

if (guestid == PAPR_NESTED_GUEST_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(guestid), guest);
env->gpr[4] = guestid;

return H_SUCCESS;
}

static target_ulong h_guest_delete(PowerPCCPU *cpu,
SpaprMachineState *spapr,
target_ulong opcode,
target_ulong *args)
{
target_ulong flags = args[0];
target_ulong guestid = args[1];
struct SpaprMachineStateNestedGuest *guest;

/*
* handle flag deleteAllGuests, if set:
* guestid is ignored and all guests are deleted
*
*/
if (flags & ~H_GUEST_DELETE_ALL_FLAG) {
return H_UNSUPPORTED_FLAG; /* other flag bits reserved */
} else if (flags & H_GUEST_DELETE_ALL_FLAG) {
g_hash_table_destroy(spapr->nested.guests);
return H_SUCCESS;
}

guest = g_hash_table_lookup(spapr->nested.guests, GINT_TO_POINTER(guestid));
if (!guest) {
return H_P2;
}

g_hash_table_remove(spapr->nested.guests, GINT_TO_POINTER(guestid));

return H_SUCCESS;
}

void spapr_register_nested_hv(void)
{
spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl);
Expand All @@ -543,12 +642,16 @@ void spapr_register_nested_papr(void)
h_guest_get_capabilities);
spapr_register_hypercall(H_GUEST_SET_CAPABILITIES,
h_guest_set_capabilities);
spapr_register_hypercall(H_GUEST_CREATE, h_guest_create);
spapr_register_hypercall(H_GUEST_DELETE, h_guest_delete);
}

void spapr_unregister_nested_papr(void)
{
spapr_unregister_hypercall(H_GUEST_GET_CAPABILITIES);
spapr_unregister_hypercall(H_GUEST_SET_CAPABILITIES);
spapr_unregister_hypercall(H_GUEST_CREATE);
spapr_unregister_hypercall(H_GUEST_DELETE);
}

#else
Expand Down
4 changes: 3 additions & 1 deletion include/hw/ppc/spapr.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,8 +586,10 @@ struct SpaprMachineState {
#define H_WATCHDOG 0x45C
#define H_GUEST_GET_CAPABILITIES 0x460
#define H_GUEST_SET_CAPABILITIES 0x464
#define H_GUEST_CREATE 0x470
#define H_GUEST_DELETE 0x488

#define MAX_HCALL_OPCODE H_GUEST_SET_CAPABILITIES
#define MAX_HCALL_OPCODE H_GUEST_DELETE

/* The hcalls above are standardized in PAPR and implemented by pHyp
* as well.
Expand Down
7 changes: 7 additions & 0 deletions include/hw/ppc/spapr_nested.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ typedef struct SpaprMachineStateNested {
#define NESTED_API_KVM_HV 1
bool capabilities_set;
uint32_t pvr_base;
GHashTable *guests;
} SpaprMachineStateNested;

typedef struct SpaprMachineStateNestedGuest {
uint32_t pvr_logical;
} SpaprMachineStateNestedGuest;

/* Nested PAPR API related macros */
#define H_GUEST_CAPABILITIES_COPY_MEM 0x8000000000000000
#define H_GUEST_CAPABILITIES_P9_MODE 0x4000000000000000
Expand All @@ -20,6 +25,8 @@ typedef struct SpaprMachineStateNested {
#define H_GUEST_CAP_COPY_MEM_BMAP 0
#define H_GUEST_CAP_P9_MODE_BMAP 1
#define H_GUEST_CAP_P10_MODE_BMAP 2
#define PAPR_NESTED_GUEST_MAX 4096
#define H_GUEST_DELETE_ALL_FLAG 0x8000000000000000ULL

/*
* Register state for entering a nested guest with H_ENTER_NESTED.
Expand Down

0 comments on commit f560562

Please sign in to comment.