Skip to content

Commit c91fe5f

Browse files
russell-islamliuw
authored andcommitted
mshv: Extend create partition ioctl to support cpu features
The existing mshv create partition ioctl does not provide a way to specify which cpu features are enabled in the guest. Instead, it attempts to enable all features and those that are not supported are silently disabled by the hypervisor. This was done to reduce unnecessary complexity and is sufficient for many cases. However, new scenarios require fine-grained control over these features. Define a new mshv_create_partition_v2 structure which supports passing the disabled processor and xsave feature bits through to the create partition hypercall directly. Introduce a new flag MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES which enables the new structure. If unset, the original mshv_create_partition struct is used, with the old behavior of enabling all features. Co-developed-by: Jinank Jain <jinankjain@microsoft.com> Signed-off-by: Jinank Jain <jinankjain@microsoft.com> Signed-off-by: Muminul Islam <muislam@microsoft.com> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com> Reviewed-by: Michael Kelley <mhklinux@outlook.com> Signed-off-by: Wei Liu <wei.liu@kernel.org>
1 parent f91bc8f commit c91fe5f

2 files changed

Lines changed: 131 additions & 21 deletions

File tree

drivers/hv/mshv_root_main.c

Lines changed: 97 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,43 +1855,119 @@ add_partition(struct mshv_partition *partition)
18551855
return 0;
18561856
}
18571857

1858-
static long
1859-
mshv_ioctl_create_partition(void __user *user_arg, struct device *module_dev)
1858+
static_assert(MSHV_NUM_CPU_FEATURES_BANKS ==
1859+
HV_PARTITION_PROCESSOR_FEATURES_BANKS);
1860+
1861+
static long mshv_ioctl_process_pt_flags(void __user *user_arg, u64 *pt_flags,
1862+
struct hv_partition_creation_properties *cr_props,
1863+
union hv_partition_isolation_properties *isol_props)
18601864
{
1861-
struct mshv_create_partition args;
1862-
u64 creation_flags;
1863-
struct hv_partition_creation_properties creation_properties = {};
1864-
union hv_partition_isolation_properties isolation_properties = {};
1865-
struct mshv_partition *partition;
1866-
struct file *file;
1867-
int fd;
1868-
long ret;
1865+
int i;
1866+
struct mshv_create_partition_v2 args;
1867+
union hv_partition_processor_features *disabled_procs;
1868+
union hv_partition_processor_xsave_features *disabled_xsave;
18691869

1870-
if (copy_from_user(&args, user_arg, sizeof(args)))
1870+
/* First, copy v1 struct in case user is on previous versions */
1871+
if (copy_from_user(&args, user_arg,
1872+
sizeof(struct mshv_create_partition)))
18711873
return -EFAULT;
18721874

18731875
if ((args.pt_flags & ~MSHV_PT_FLAGS_MASK) ||
18741876
args.pt_isolation >= MSHV_PT_ISOLATION_COUNT)
18751877
return -EINVAL;
18761878

1879+
disabled_procs = &cr_props->disabled_processor_features;
1880+
disabled_xsave = &cr_props->disabled_processor_xsave_features;
1881+
1882+
/* Check if user provided newer struct with feature fields */
1883+
if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES)) {
1884+
if (copy_from_user(&args, user_arg, sizeof(args)))
1885+
return -EFAULT;
1886+
1887+
/* Re-validate v1 fields after second copy_from_user() */
1888+
if ((args.pt_flags & ~MSHV_PT_FLAGS_MASK) ||
1889+
args.pt_isolation >= MSHV_PT_ISOLATION_COUNT)
1890+
return -EINVAL;
1891+
1892+
if (args.pt_num_cpu_fbanks != MSHV_NUM_CPU_FEATURES_BANKS ||
1893+
mshv_field_nonzero(args, pt_rsvd) ||
1894+
mshv_field_nonzero(args, pt_rsvd1))
1895+
return -EINVAL;
1896+
1897+
/*
1898+
* Note this assumes MSHV_NUM_CPU_FEATURES_BANKS will never
1899+
* change and equals HV_PARTITION_PROCESSOR_FEATURES_BANKS
1900+
* (i.e. 2).
1901+
*
1902+
* Further banks (index >= 2) will be modifiable as 'early'
1903+
* properties via the set partition property hypercall.
1904+
*/
1905+
for (i = 0; i < HV_PARTITION_PROCESSOR_FEATURES_BANKS; i++)
1906+
disabled_procs->as_uint64[i] = args.pt_cpu_fbanks[i];
1907+
1908+
#if IS_ENABLED(CONFIG_X86_64)
1909+
disabled_xsave->as_uint64 = args.pt_disabled_xsave;
1910+
#else
1911+
/*
1912+
* In practice this field is ignored on arm64, but safer to
1913+
* zero it in case it is ever used.
1914+
*/
1915+
disabled_xsave->as_uint64 = 0;
1916+
1917+
if (mshv_field_nonzero(args, pt_rsvd2))
1918+
return -EINVAL;
1919+
#endif
1920+
} else {
1921+
/*
1922+
* v1 behavior: try to enable everything. The hypervisor will
1923+
* disable features that are not supported. The banks can be
1924+
* queried via the get partition property hypercall.
1925+
*/
1926+
for (i = 0; i < HV_PARTITION_PROCESSOR_FEATURES_BANKS; i++)
1927+
disabled_procs->as_uint64[i] = 0;
1928+
1929+
disabled_xsave->as_uint64 = 0;
1930+
}
1931+
18771932
/* Only support EXO partitions */
1878-
creation_flags = HV_PARTITION_CREATION_FLAG_EXO_PARTITION |
1879-
HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED;
1933+
*pt_flags = HV_PARTITION_CREATION_FLAG_EXO_PARTITION |
1934+
HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED;
1935+
1936+
if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_LAPIC))
1937+
*pt_flags |= HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED;
1938+
if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_X2APIC))
1939+
*pt_flags |= HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE;
1940+
if (args.pt_flags & BIT_ULL(MSHV_PT_BIT_GPA_SUPER_PAGES))
1941+
*pt_flags |= HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED;
18801942

1881-
if (args.pt_flags & BIT(MSHV_PT_BIT_LAPIC))
1882-
creation_flags |= HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED;
1883-
if (args.pt_flags & BIT(MSHV_PT_BIT_X2APIC))
1884-
creation_flags |= HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE;
1885-
if (args.pt_flags & BIT(MSHV_PT_BIT_GPA_SUPER_PAGES))
1886-
creation_flags |= HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED;
1943+
isol_props->as_uint64 = 0;
18871944

18881945
switch (args.pt_isolation) {
18891946
case MSHV_PT_ISOLATION_NONE:
1890-
isolation_properties.isolation_type =
1891-
HV_PARTITION_ISOLATION_TYPE_NONE;
1947+
isol_props->isolation_type = HV_PARTITION_ISOLATION_TYPE_NONE;
18921948
break;
18931949
}
18941950

1951+
return 0;
1952+
}
1953+
1954+
static long
1955+
mshv_ioctl_create_partition(void __user *user_arg, struct device *module_dev)
1956+
{
1957+
u64 creation_flags;
1958+
struct hv_partition_creation_properties creation_properties;
1959+
union hv_partition_isolation_properties isolation_properties;
1960+
struct mshv_partition *partition;
1961+
struct file *file;
1962+
int fd;
1963+
long ret;
1964+
1965+
ret = mshv_ioctl_process_pt_flags(user_arg, &creation_flags,
1966+
&creation_properties,
1967+
&isolation_properties);
1968+
if (ret)
1969+
return ret;
1970+
18951971
partition = kzalloc(sizeof(*partition), GFP_KERNEL);
18961972
if (!partition)
18971973
return -ENOMEM;

include/uapi/linux/mshv.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum {
2626
MSHV_PT_BIT_LAPIC,
2727
MSHV_PT_BIT_X2APIC,
2828
MSHV_PT_BIT_GPA_SUPER_PAGES,
29+
MSHV_PT_BIT_CPU_AND_XSAVE_FEATURES,
2930
MSHV_PT_BIT_COUNT,
3031
};
3132

@@ -41,6 +42,8 @@ enum {
4142
* @pt_flags: Bitmask of 1 << MSHV_PT_BIT_*
4243
* @pt_isolation: MSHV_PT_ISOLATION_*
4344
*
45+
* This is the initial/v1 version for backward compatibility.
46+
*
4447
* Returns a file descriptor to act as a handle to a guest partition.
4548
* At this point the partition is not yet initialized in the hypervisor.
4649
* Some operations must be done with the partition in this state, e.g. setting
@@ -52,6 +55,37 @@ struct mshv_create_partition {
5255
__u64 pt_isolation;
5356
};
5457

58+
#define MSHV_NUM_CPU_FEATURES_BANKS 2
59+
60+
/**
61+
* struct mshv_create_partition_v2
62+
*
63+
* This is extended version of the above initial MSHV_CREATE_PARTITION
64+
* ioctl and allows for following additional parameters:
65+
*
66+
* @pt_num_cpu_fbanks: Must be set to MSHV_NUM_CPU_FEATURES_BANKS.
67+
* @pt_cpu_fbanks: Disabled processor feature banks array.
68+
* @pt_disabled_xsave: Disabled xsave feature bits.
69+
*
70+
* pt_cpu_fbanks and pt_disabled_xsave are passed through as-is to the create
71+
* partition hypercall.
72+
*
73+
* Returns : same as above original mshv_create_partition
74+
*/
75+
struct mshv_create_partition_v2 {
76+
__u64 pt_flags;
77+
__u64 pt_isolation;
78+
__u16 pt_num_cpu_fbanks;
79+
__u8 pt_rsvd[6]; /* MBZ */
80+
__u64 pt_cpu_fbanks[MSHV_NUM_CPU_FEATURES_BANKS];
81+
__u64 pt_rsvd1[2]; /* MBZ */
82+
#if defined(__x86_64__)
83+
__u64 pt_disabled_xsave;
84+
#else
85+
__u64 pt_rsvd2; /* MBZ */
86+
#endif
87+
} __packed;
88+
5589
/* /dev/mshv */
5690
#define MSHV_CREATE_PARTITION _IOW(MSHV_IOCTL, 0x00, struct mshv_create_partition)
5791

0 commit comments

Comments
 (0)