Compare commits

...
Author SHA1 Message Date
Michal Kubecek 41bfaa9de7 vmnet: work around skb_frag_t build failure for SLE15-SP2 and openSUSE-15.2
The kernels used in (upcoming) SLE15 SP2 and openSUSE Leap 15.2 are based
on upstream version 5.3 but have a backport of the skb_frag_t conversion to
bio_vec which reached mainline in v5.4-rc1. As we cannot easily check
availability compat_skb_frag_off() (which was also added in v5.4-rc1) and
have to resort to version check, add an exception for SLE15-SP2 and
openSUSE-15.2 kernels.
2019-11-25 08:19:03 +01:00
Michal Kubecek 50d6105ced vmnet: handle switch of skb_frag_t to bio_vec
The switch from custom skb_frag_t implementation to bio_vec in v5.4-rc1 is
mostly transparent for modules which use accessor for skb_frag_t members.
Unfortunately many users access the members directly and function
VNetCsumCopyDatagram() in vmnet is one of those.

Use accessors everywhere so that vmnet code is compatible with kernel 5.4
and newer. Use "compat_" prefix to avoid clashes with backports adding the
accessors to older codebase.
2019-11-14 08:06:57 +01:00
Michal Kubecek 525d443329 vmmon: use standard definition of MSR_TSX_FORCE_ABORT if available
The MSR_TSX_FORCE_ABORT macro is defined in mainline since commit
52f64909409c ("x86: Add TSX Force Abort CPUID/MSR") in v5.1-rc1.
2019-11-14 08:06:57 +01:00
Michal Kubecek ca784dc94e vmnet: bring back the do_gettimeofday() helper
The do_gettimeofday() helper was removed by commit e4b92b108c6c
("timekeeping: remove obsolete time accessors") in v5.0-rc1. Bring it back
for users in vmnet-only/bridge.c

Note that Workstation/Player 15.1.0 did in fact resolve the absence of
do_gettimeofday() in kernel 5.0 and newer but it did so only for calls in
vmmon-only/linux/hostif.c. Calls in vmnet-only/bridge.c were left in place
as those are only compiled when building with LOGLEVEL >= 4.
2019-11-14 08:06:57 +01:00
Michal Kubecek 821a4a5d76 vmmon: check presence of file_operations::poll()
Commit 11c5ad0ec441 ("eventpoll: switch to ->poll_mask") in v4.18-rc1, made
eventpoll switch from ->poll() to ->poll_mask(), resulting in a null
pointer dereference as vmmon calls the callback directly without checking
its availability.

Rather than calling the callback directly (which would result in null
pointer dereference), use vfs_poll() wrapper. As this wrapper is only
available since 4.18-rc1 cycle as well, provide a copy to use when building
against older kernels.

Note: even if the commit revealing the problem was reverted in 4.18-rc3
(and is unlikely to go back in the same form) so that vmmon no longer
crashes with 4.18 kernel, calling the callback without a check is a bad
practice so let's keep the patch in place.
2019-11-14 08:06:57 +01:00
5 changed files with 77 additions and 11 deletions

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
#ifndef __COMPAT_POLL_H__
#define __COMPAT_POLL_H__
#include <linux/poll.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0))
#ifndef __poll_t
typedef unsigned int __poll_t;
#endif
static inline __poll_t compat_vfs_poll(struct file *file,
struct poll_table_struct *pt)
{
if (unlikely(!file->f_op->poll))
return DEFAULT_POLLMASK;
return file->f_op->poll(file, pt);
}
#else
static inline __poll_t compat_vfs_poll(struct file *file,
struct poll_table_struct *pt)
{
return vfs_poll(file, pt);
}
#endif
#endif /* __COMPAT_POLL_H__ */
+2
View File
@@ -635,7 +635,9 @@ typedef enum {
#define MSR_HYPERV_GUESTOSID_OS_WINNT_DERIVATIVE 4ULL
/* MSR for forcing RTM abort to recover PMC3 (see PR 2333817) */
#ifndef MSR_TSX_FORCE_ABORT
#define MSR_TSX_FORCE_ABORT 0x0000010f
#endif
#define MSR_TSX_FORCE_ABORT_RTM_BIT_INDEX 0
/*
+2 -1
View File
@@ -74,6 +74,7 @@
#include "pgtbl.h"
#include "versioned_atomic.h"
#include "compat_poll.h"
#if !defined(CONFIG_HIGH_RES_TIMERS)
#error CONFIG_HIGH_RES_TIMERS required for acceptable performance
@@ -2575,7 +2576,7 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
poll_initwait(&table);
current->state = TASK_INTERRUPTIBLE;
mask = file->f_op->poll(file, &table.pt);
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
+12
View File
@@ -67,6 +67,18 @@
#if LOGLEVEL >= 4
static struct timeval vnetTime;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
static void do_gettimeofday(struct timeval *tv)
{
struct timespec64 now;
ktime_get_real_ts64(&now);
tv->tv_sec = now.tv_sec;
tv->tv_usec = now.tv_nsec / 1000;
}
#endif
#endif
typedef struct VNetBridge VNetBridge;
+31 -10
View File
@@ -78,13 +78,33 @@ static int VNetUserIfSetUplinkState(VNetPort *port, uint8 linkUp);
extern unsigned int vnet_max_qlen;
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
# define compat_kmap(page) kmap(page)
# define compat_kunmap(page) kunmap(page)
# define compat_kmap_frag(frag) kmap((frag)->page)
# define compat_kunmap_frag(page) kunmap((frag)->page)
#else
# define compat_kmap(page) kmap((page).p)
# define compat_kunmap(page) kunmap((page).p)
# define compat_kmap_frag(frag) kmap(skb_frag_page(frag))
# define compat_kunmap_frag(frag) kunmap(skb_frag_page(frag))
#endif
static unsigned int compat_skb_frag_size(const skb_frag_t *frag)
{
#if COMPAT_LINUX_VERSION_CHECK_LT(3, 2, 0)
return frag->size;
#else
return skb_frag_size(frag);
#endif
}
static unsigned int compat_skb_frag_off(const skb_frag_t *frag)
{
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 4, 0) && \
!(defined(CONFIG_SUSE_VERSION) && CONFIG_SUSE_VERSION == 15 && \
defined(CONFIG_SUSE_PATCHLEVEL) && CONFIG_SUSE_PATCHLEVEL >= 2)
return frag->page_offset;
#else
return skb_frag_off(frag);
#endif
}
/*
*-----------------------------------------------------------------------------
*
@@ -568,20 +588,21 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
for (frag = skb_shinfo(skb)->frags;
frag != skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
frag++) {
if (frag->size > 0) {
if (compat_skb_frag_size(frag) > 0) {
unsigned int tmpCsum;
const void *vaddr;
vaddr = compat_kmap(frag->page);
tmpCsum = csum_and_copy_to_user(vaddr + frag->page_offset,
curr, frag->size, 0, &err);
compat_kunmap(frag->page);
vaddr = compat_kmap_frag(frag);
tmpCsum = csum_and_copy_to_user(vaddr + compat_skb_frag_off(frag),
curr, compat_skb_frag_size(frag), 0,
&err);
compat_kunmap_frag(frag);
if (err) {
return err;
}
csum = csum_block_add(csum, tmpCsum, curr - buf);
curr += frag->size;
curr += compat_skb_frag_size(frag);
}
}