Skip to content

Commit 37e6764

Browse files
hmynenimpe
authored andcommitted
powerpc/pseries/vas: Add VAS migration handler
Since the VAS windows belong to the VAS hardware resource, the hypervisor expects the partition to close them on source partition and reopen them after the partition migrated on the destination machine. This handler is called before pseries_suspend() to close these windows and again invoked after migration. All active windows for both default and QoS types will be closed and mark them inactive and reopened after migration with this handler. During the migration, the user space receives paste instruction failure if it issues copy/paste on these inactive windows. The current migration implementation does not freeze the user space and applications can continue to open VAS windows while migration is in progress. So when the migration_in_progress flag is set, VAS open window API returns -EBUSY. Signed-off-by: Haren Myneni <haren@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/05e45ff4f8babd2490ccb7ae923884f4aa21a7e5.camel@linux.ibm.com
1 parent 716d7a2 commit 37e6764

File tree

3 files changed

+116
-1
lines changed

3 files changed

+116
-1
lines changed

arch/powerpc/platforms/pseries/mobility.c

+5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <asm/machdep.h>
2727
#include <asm/rtas.h>
2828
#include "pseries.h"
29+
#include "vas.h" /* vas_migration_handler() */
2930
#include "../../kernel/cacheinfo.h"
3031

3132
static struct kobject *mobility_kobj;
@@ -669,12 +670,16 @@ static int pseries_migrate_partition(u64 handle)
669670
if (ret)
670671
return ret;
671672

673+
vas_migration_handler(VAS_SUSPEND);
674+
672675
ret = pseries_suspend(handle);
673676
if (ret == 0)
674677
post_mobility_fixup();
675678
else
676679
pseries_cancel_migration(handle, ret);
677680

681+
vas_migration_handler(VAS_RESUME);
682+
678683
return ret;
679684
}
680685

arch/powerpc/platforms/pseries/vas.c

+97-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static struct hv_vas_cop_feat_caps hv_cop_caps;
3030

3131
static struct vas_caps vascaps[VAS_MAX_FEAT_TYPE];
3232
static DEFINE_MUTEX(vas_pseries_mutex);
33+
static bool migration_in_progress;
3334

3435
static long hcall_return_busy_check(long rc)
3536
{
@@ -356,7 +357,10 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
356357
* same fault IRQ is not freed by the OS before.
357358
*/
358359
mutex_lock(&vas_pseries_mutex);
359-
rc = allocate_setup_window(txwin, (u64 *)&domain[0],
360+
if (migration_in_progress)
361+
rc = -EBUSY;
362+
else
363+
rc = allocate_setup_window(txwin, (u64 *)&domain[0],
360364
cop_feat_caps->win_type);
361365
mutex_unlock(&vas_pseries_mutex);
362366
if (rc)
@@ -869,6 +873,98 @@ static struct notifier_block pseries_vas_nb = {
869873
.notifier_call = pseries_vas_notifier,
870874
};
871875

876+
/*
877+
* For LPM, all windows have to be closed on the source partition
878+
* before migration and reopen them on the destination partition
879+
* after migration. So closing windows during suspend and
880+
* reopen them during resume.
881+
*/
882+
int vas_migration_handler(int action)
883+
{
884+
struct vas_cop_feat_caps *caps;
885+
int old_nr_creds, new_nr_creds = 0;
886+
struct vas_caps *vcaps;
887+
int i, rc = 0;
888+
889+
/*
890+
* NX-GZIP is not enabled. Nothing to do for migration.
891+
*/
892+
if (!copypaste_feat)
893+
return rc;
894+
895+
mutex_lock(&vas_pseries_mutex);
896+
897+
if (action == VAS_SUSPEND)
898+
migration_in_progress = true;
899+
else
900+
migration_in_progress = false;
901+
902+
for (i = 0; i < VAS_MAX_FEAT_TYPE; i++) {
903+
vcaps = &vascaps[i];
904+
caps = &vcaps->caps;
905+
old_nr_creds = atomic_read(&caps->nr_total_credits);
906+
907+
rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES,
908+
vcaps->feat,
909+
(u64)virt_to_phys(&hv_cop_caps));
910+
if (!rc) {
911+
new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds);
912+
/*
913+
* Should not happen. But incase print messages, close
914+
* all windows in the list during suspend and reopen
915+
* windows based on new lpar_creds on the destination
916+
* system.
917+
*/
918+
if (old_nr_creds != new_nr_creds) {
919+
pr_err("Target credits mismatch with the hypervisor\n");
920+
pr_err("state(%d): lpar creds: %d HV lpar creds: %d\n",
921+
action, old_nr_creds, new_nr_creds);
922+
pr_err("Used creds: %d, Active creds: %d\n",
923+
atomic_read(&caps->nr_used_credits),
924+
vcaps->nr_open_windows - vcaps->nr_close_wins);
925+
}
926+
} else {
927+
pr_err("state(%d): Get VAS capabilities failed with %d\n",
928+
action, rc);
929+
/*
930+
* We can not stop migration with the current lpm
931+
* implementation. So continue closing all windows in
932+
* the list (during suspend) and return without
933+
* opening windows (during resume) if VAS capabilities
934+
* HCALL failed.
935+
*/
936+
if (action == VAS_RESUME)
937+
goto out;
938+
}
939+
940+
switch (action) {
941+
case VAS_SUSPEND:
942+
rc = reconfig_close_windows(vcaps, vcaps->nr_open_windows,
943+
true);
944+
break;
945+
case VAS_RESUME:
946+
atomic_set(&caps->nr_total_credits, new_nr_creds);
947+
rc = reconfig_open_windows(vcaps, new_nr_creds, true);
948+
break;
949+
default:
950+
/* should not happen */
951+
pr_err("Invalid migration action %d\n", action);
952+
rc = -EINVAL;
953+
goto out;
954+
}
955+
956+
/*
957+
* Ignore errors during suspend and return for resume.
958+
*/
959+
if (rc && (action == VAS_RESUME))
960+
goto out;
961+
}
962+
963+
out:
964+
mutex_unlock(&vas_pseries_mutex);
965+
return rc;
966+
}
967+
872968
static int __init pseries_vas_init(void)
873969
{
874970
struct hv_vas_all_caps *hv_caps;

arch/powerpc/platforms/pseries/vas.h

+14
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
#define VAS_GZIP_QOS_CAPABILITIES 0x56516F73477A6970
3434
#define VAS_GZIP_DEFAULT_CAPABILITIES 0x56446566477A6970
3535

36+
enum vas_migrate_action {
37+
VAS_SUSPEND,
38+
VAS_RESUME,
39+
};
40+
3641
/*
3742
* Co-processor feature - GZIP QoS windows or GZIP default windows
3843
*/
@@ -132,4 +137,13 @@ struct pseries_vas_window {
132137
int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps);
133138
int vas_reconfig_capabilties(u8 type);
134139
int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps);
140+
141+
#ifdef CONFIG_PPC_VAS
142+
int vas_migration_handler(int action);
143+
#else
144+
static inline int vas_migration_handler(int action)
145+
{
146+
return 0;
147+
}
148+
#endif
135149
#endif /* _VAS_H */

0 commit comments

Comments
 (0)