vmmon: avoid set_fs() in HostIF_SemaphoreWait() and HostIF_SemaphoreSignal()

The set_fs() function was dropped on x86_64 architecture by commit
47058bb54b57 ("x86: remove address space overrides using set_fs()") in
5.10-rc1. In HostIF_SemaphoreWait() it is used to allow calling read() file
op on a kernel pointer, in HostIF_SemaphoreSignal() to allow calling
write() file op on a kernel pointer. This is only the case for pre-5.8
kernels as we need to use kernel_read() and kernel_write() helpers on 5.8
and newer anyway.

Use kernel_read() and kernel_write() always, like Workstation 16.0.0 does,
so that we no longer need the set_fs(KERNEL_DS) trick. Make the code of
both functions look exactly like in Workstation 16.0.0 to make future
backports easier.
This commit is contained in:
Michal Kubecek committed 2020-12-09 09:17:59 +01:00
1 parent 51b3ade634
commit 1a90e9e8ae
1 file changed
+21 -33
+21 -33
View File
@@ -2576,11 +2576,12 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
uint64 *args) // IN:
{
struct file *file;
mm_segment_t old_fs;
int res;
int waitFD = args[0];
int timeoutms = args[2];
uint64 value;
struct poll_wqueues table;
unsigned int mask;
ASSERT(vcpuid < vm->numVCPUs);
@@ -2589,37 +2590,29 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
return MX_WAITERROR;
}
old_fs = get_fs();
set_fs(KERNEL_DS);
{
struct poll_wqueues table;
unsigned int mask;
poll_initwait(&table);
current->state = TASK_INTERRUPTIBLE;
mask = compat_vfs_poll(file, &table.pt);
if (!(mask & (POLLIN | POLLERR | POLLHUP))) {
vm->vmhost->vcpuSemaTask[vcpuid] = current;
schedule_timeout(timeoutms * HZ / 1000); // convert to Hz
vm->vmhost->vcpuSemaTask[vcpuid] = NULL;
}
current->state = TASK_RUNNING;
poll_freewait(&table);
poll_initwait(&table);
current->state = TASK_INTERRUPTIBLE;
mask = compat_vfs_poll(file, &table.pt);
if (!(mask & (POLLIN | POLLERR | POLLHUP))) {
vm->vmhost->vcpuSemaTask[vcpuid] = current;
schedule_timeout(timeoutms * HZ / 1000); // convert to Hz
vm->vmhost->vcpuSemaTask[vcpuid] = NULL;
}
current->state = TASK_RUNNING;
poll_freewait(&table);
/*
* Userland only writes in multiples of sizeof(uint64). This will allow
* the code to happily deal with a pipe or an eventfd. We only care about
* reading no bytes (EAGAIN - non blocking fd) or sizeof(uint64).
*
* Upstream Linux changed the function parameter types/ordering in 4.14.0.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
res = kernel_read(file, (char *) &value, sizeof value, &file->f_pos);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
res = kernel_read(file, file->f_pos, (char *)&value, sizeof value);
#else
res = file->f_op->read(file, (char *) &value, sizeof value, &file->f_pos);
res = kernel_read(file, &value, sizeof value, &file->f_pos);
#endif
if (res == sizeof value) {
res = MX_WAITNORMAL;
} else {
@@ -2628,7 +2621,6 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
}
}
set_fs(old_fs);
fput(file);
/*
@@ -2716,7 +2708,6 @@ int
HostIF_SemaphoreSignal(uint64 *args) // IN:
{
struct file *file;
mm_segment_t old_fs;
int res;
int signalFD = args[1];
uint64 value = 1; // make an eventfd happy should it be there
@@ -2726,26 +2717,23 @@ HostIF_SemaphoreSignal(uint64 *args) // IN:
return MX_WAITERROR;
}
old_fs = get_fs();
set_fs(KERNEL_DS);
/*
* Always write sizeof(uint64) bytes. This works fine for eventfd and
* pipes. The data written is formatted to make an eventfd happy should
* it be present.
*
* Upstream Linux changed the function parameter types/ordering in 4.14.0.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
res = kernel_write(file, (char *) &value, sizeof value, &file->f_pos);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
res = kernel_write(file, (char *)&value, sizeof value, file->f_pos);
#else
res = file->f_op->write(file, (char *) &value, sizeof value, &file->f_pos);
res = kernel_write(file, &value, sizeof value, &file->f_pos);
#endif
if (res == sizeof value) {
res = MX_WAITNORMAL;
}
set_fs(old_fs);
fput(file);
/*