Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdb45b6bc7 | ||
|
|
def1fde011 | ||
|
|
dd89259952 | ||
|
|
5fc7cda4f9 | ||
|
|
d0483caf73 | ||
|
|
c9739c0fff | ||
|
|
9cbb077f8d | ||
|
|
4e40ef62ee | ||
|
|
11bf1a7d96 | ||
|
|
f3b55e5bca | ||
|
|
ba25bac1e0 | ||
|
|
0ff0d40dda | ||
|
|
8f3d9f4bb5 | ||
|
|
56b7374fc4 | ||
|
|
6af901cc45 | ||
|
|
4b6eb20f62 | ||
|
|
d184686860 | ||
|
|
85ede6aae9 | ||
|
|
26fb3d29e0 | ||
|
|
4f88bce684 |
No files matched your search
@@ -150,7 +150,7 @@ test build).
|
||||
When using a downloaded tarball, simply run
|
||||
|
||||
tar -cf vmmon.tar vmmon-only
|
||||
tar -cf vmnet.tar vmmon-only
|
||||
tar -cf vmnet.tar vmnet-only
|
||||
|
||||
to create the tarballs. In this case, there is no protection against
|
||||
unwanted local changes.
|
||||
|
||||
@@ -251,6 +251,7 @@ static INLINE ub8 hash2(register const ub8 *k, /* the key */
|
||||
{
|
||||
/* c is reserved for the length */
|
||||
case 2: b+=k[1];
|
||||
/* fall through */
|
||||
case 1: a+=k[0];
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
|
||||
+107
-220
@@ -47,13 +47,16 @@
|
||||
#include <asm/asm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/irq_vectors.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/taskstats_kern.h> // For linux/sched/signal.h without version check
|
||||
#include <linux/eventfd.h>
|
||||
|
||||
#include "vmware.h"
|
||||
#include "x86apic.h"
|
||||
@@ -116,13 +119,7 @@
|
||||
*/
|
||||
#define LOCKED_PAGE_SLACK 10000
|
||||
|
||||
static struct {
|
||||
Atomic_uint64 uptimeBase;
|
||||
VersionedAtomic version;
|
||||
uint64 monotimeBase;
|
||||
unsigned long jiffiesBase;
|
||||
struct timer_list timer;
|
||||
} uptimeState;
|
||||
u64 uptime_base;
|
||||
|
||||
/*
|
||||
* First Page Locking strategy
|
||||
@@ -190,17 +187,6 @@ static unsigned long compat_totalram_pages(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) && defined(VERIFY_WRITE)
|
||||
#define write_access_ok(addr, size) access_ok(VERIFY_WRITE, addr, size)
|
||||
#else
|
||||
@@ -620,6 +606,15 @@ HostIF_FastClockUnlock(int callerID) // IN
|
||||
MutexUnlock(&fastClockMutex, callerID);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
|
||||
static int crosspage_set_exec(pte_t *pte, unsigned long addr, void *data)
|
||||
{
|
||||
struct page *p = data;
|
||||
|
||||
set_pte(pte, mk_pte(p, VM_PAGE_KERNEL_EXEC));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -640,7 +635,29 @@ HostIF_FastClockUnlock(int callerID) // IN
|
||||
static void *
|
||||
MapCrossPage(struct page *p) // IN:
|
||||
{
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0)
|
||||
return vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC);
|
||||
#else
|
||||
void *addr;
|
||||
|
||||
addr = vmap(&p, 1, VM_MAP, VM_PAGE_KERNEL_EXEC);
|
||||
if (!addr)
|
||||
return NULL;
|
||||
|
||||
/* Starting with 5.8, vmap() always sets the NX bit, but the cross
|
||||
* page needs to be executable. */
|
||||
if (apply_to_page_range(current->mm, (unsigned long)addr, PAGE_SIZE,
|
||||
crosspage_set_exec, p)) {
|
||||
vunmap(addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
__flush_tlb_all();
|
||||
preempt_enable();
|
||||
|
||||
return addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1546,8 +1563,11 @@ HostIF_EstimateLockedPageLimit(const VMDriver* vm, // IN
|
||||
#else
|
||||
lockedPages += global_page_state(NR_PAGETABLE);
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||
/* NR_SLAB_* converted to byte counters in 5.9 */
|
||||
lockedPages += global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B);
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||
/* NR_SLAB_* moved from zone to node in 4.13. */
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
|
||||
lockedPages += global_node_page_state(NR_SLAB_UNRECLAIMABLE);
|
||||
#else
|
||||
lockedPages += global_page_state(NR_SLAB_UNRECLAIMABLE);
|
||||
@@ -1619,143 +1639,6 @@ HostIF_WaitForFreePages(unsigned int timeoutMs) // IN:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* HostIFReadUptimeWork --
|
||||
*
|
||||
* Reads the current uptime. The uptime is based on getimeofday,
|
||||
* which provides the needed high resolution. However, we don't
|
||||
* want uptime to be warped by e.g. calls to settimeofday. So, we
|
||||
* use a jiffies based monotonic clock to sanity check the uptime.
|
||||
* If the uptime is more than one second from the monotonic time,
|
||||
* we assume that the time of day has been set, and recalculate the
|
||||
* uptime base to get uptime back on track with monotonic time. On
|
||||
* the other hand, we do expect jiffies based monotonic time and
|
||||
* timeofday to have small drift (due to NTP rate correction, etc).
|
||||
* We handle this by rebasing the jiffies based monotonic clock
|
||||
* every second (see HostIFUptimeResyncMono).
|
||||
*
|
||||
* Results:
|
||||
* The uptime, in units of UPTIME_FREQ. Also returns the jiffies
|
||||
* value that was used in the monotonic time calculation.
|
||||
*
|
||||
* Side effects:
|
||||
* May reset the uptime base in the case gettimeofday warp was
|
||||
* detected.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static uint64
|
||||
HostIFReadUptimeWork(unsigned long *j) // OUT: current jiffies
|
||||
{
|
||||
struct timeval tv;
|
||||
uint64 monotime, uptime, upBase, monoBase;
|
||||
int64 diff;
|
||||
uint32 version;
|
||||
unsigned long jifs, jifBase;
|
||||
unsigned int attempts = 0;
|
||||
|
||||
retry:
|
||||
do {
|
||||
version = VersionedAtomic_BeginTryRead(&uptimeState.version);
|
||||
jifs = jiffies;
|
||||
jifBase = uptimeState.jiffiesBase;
|
||||
monoBase = uptimeState.monotimeBase;
|
||||
} while (!VersionedAtomic_EndTryRead(&uptimeState.version, version));
|
||||
|
||||
do_gettimeofday(&tv);
|
||||
upBase = Atomic_Read64(&uptimeState.uptimeBase);
|
||||
|
||||
monotime = (uint64)(jifs - jifBase) * (UPTIME_FREQ / HZ);
|
||||
monotime += monoBase;
|
||||
|
||||
uptime = tv.tv_usec * (UPTIME_FREQ / 1000000) + tv.tv_sec * UPTIME_FREQ;
|
||||
uptime += upBase;
|
||||
|
||||
/*
|
||||
* Use the jiffies based monotonic time to sanity check gettimeofday.
|
||||
* If they differ by more than one second, assume the time of day has
|
||||
* been warped, and use the jiffies time to undo (most of) the warp.
|
||||
*/
|
||||
|
||||
diff = uptime - monotime;
|
||||
if (UNLIKELY(diff < -UPTIME_FREQ || diff > UPTIME_FREQ)) {
|
||||
/* Compute a new uptimeBase to get uptime back on track. */
|
||||
uint64 newUpBase = monotime - (uptime - upBase);
|
||||
|
||||
attempts++;
|
||||
if (!Atomic_CMPXCHG64(&uptimeState.uptimeBase, upBase, newUpBase) &&
|
||||
attempts < 5) {
|
||||
/* Another thread updated uptimeBase. Recalculate uptime. */
|
||||
goto retry;
|
||||
}
|
||||
uptime = monotime;
|
||||
|
||||
Log("%s: detected settimeofday: fixed uptimeBase old %"FMT64"u "
|
||||
"new %"FMT64"u attempts %u\n", __func__,
|
||||
upBase, newUpBase, attempts);
|
||||
}
|
||||
*j = jifs;
|
||||
|
||||
return uptime;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* HostIFUptimeResyncMono --
|
||||
*
|
||||
* Timer that fires ever second to resynchronize the jiffies based
|
||||
* monotonic time with the uptime.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* Resets the monotonic time bases so that jiffies based monotonic
|
||||
* time does not drift from gettimeofday over the long term.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
HostIFUptimeResyncMono(struct timer_list *timer) // IN: ignored
|
||||
{
|
||||
unsigned long jifs;
|
||||
uintptr_t flags;
|
||||
|
||||
/*
|
||||
* Read the uptime and the corresponding jiffies value. This will
|
||||
* also correct the uptime (which is based on time of day) if needed
|
||||
* before we rebase monotonic time (which is based on jiffies).
|
||||
*/
|
||||
|
||||
uint64 uptime = HostIFReadUptimeWork(&jifs);
|
||||
|
||||
/*
|
||||
* Every second, recalculate monoBase and jiffiesBase to squash small
|
||||
* drift between gettimeofday and jiffies. Also, this prevents
|
||||
* (jiffies - jiffiesBase) wrap on 32-bits.
|
||||
*/
|
||||
|
||||
SAVE_FLAGS(flags);
|
||||
CLEAR_INTERRUPTS();
|
||||
VersionedAtomic_BeginWrite(&uptimeState.version);
|
||||
|
||||
uptimeState.monotimeBase = uptime;
|
||||
uptimeState.jiffiesBase = jifs;
|
||||
|
||||
VersionedAtomic_EndWrite(&uptimeState.version);
|
||||
RESTORE_FLAGS(flags);
|
||||
|
||||
/* Reschedule this timer to expire in one second. */
|
||||
mod_timer(&uptimeState.timer, jifs + HZ);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -1767,8 +1650,7 @@ HostIFUptimeResyncMono(struct timer_list *timer) // IN: ignored
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the initial values for the uptime state, and schedules
|
||||
* the uptime timer.
|
||||
* Sets the initial value for the uptime base.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1776,22 +1658,7 @@ HostIFUptimeResyncMono(struct timer_list *timer) // IN: ignored
|
||||
void
|
||||
HostIF_InitUptime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
uptimeState.jiffiesBase = jiffies;
|
||||
do_gettimeofday(&tv);
|
||||
Atomic_Write64(&uptimeState.uptimeBase,
|
||||
-(tv.tv_usec * (UPTIME_FREQ / 1000000) +
|
||||
tv.tv_sec * UPTIME_FREQ));
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) && !defined(timer_setup)
|
||||
init_timer(&uptimeState.timer);
|
||||
uptimeState.timer.function = (void *)HostIFUptimeResyncMono;
|
||||
uptimeState.timer.data = (unsigned long)&uptimeState.timer;
|
||||
#else
|
||||
timer_setup(&uptimeState.timer, HostIFUptimeResyncMono, 0);
|
||||
#endif
|
||||
mod_timer(&uptimeState.timer, jiffies + HZ);
|
||||
uptime_base = ktime_get_ns();
|
||||
}
|
||||
|
||||
|
||||
@@ -1800,13 +1667,13 @@ HostIF_InitUptime(void)
|
||||
*
|
||||
* HostIF_CleanupUptime --
|
||||
*
|
||||
* Cleanup uptime state, called at module unloading time.
|
||||
* No-op, left for backward compatibility.
|
||||
*
|
||||
* Results:
|
||||
* None
|
||||
*
|
||||
* Side effects:
|
||||
* Deschedule the uptime timer.
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1814,7 +1681,6 @@ HostIF_InitUptime(void)
|
||||
void
|
||||
HostIF_CleanupUptime(void)
|
||||
{
|
||||
del_timer_sync(&uptimeState.timer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1838,9 +1704,10 @@ HostIF_CleanupUptime(void)
|
||||
uint64
|
||||
HostIF_ReadUptime(void)
|
||||
{
|
||||
unsigned long jifs;
|
||||
u64 tm;
|
||||
|
||||
return HostIFReadUptimeWork(&jifs);
|
||||
tm = ktime_get_ns();
|
||||
return (tm - uptime_base) / (NSEC_PER_SEC / UPTIME_FREQ);
|
||||
}
|
||||
|
||||
|
||||
@@ -2160,6 +2027,27 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN
|
||||
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_X86_UP_IOAPIC) || \
|
||||
defined(CONFIG_X86_UP_APIC) || defined(CONFIG_X86_LOCAL_APIC)
|
||||
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 8, 0)
|
||||
static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
long ret;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
ret = HostIF_CopyFromUser(dst, src, size);
|
||||
set_fs(old_fs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static long compat_copy_from_kernel_nofault(void *dst, VA src, size_t size)
|
||||
{
|
||||
return copy_from_kernel_nofault(dst, (const void *)src, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -2179,15 +2067,11 @@ HostIF_VMLockIsHeld(VMDriver *vm) // IN
|
||||
static Bool
|
||||
isVAReadable(VA r) // IN:
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
uint32 dummy;
|
||||
int ret;
|
||||
long ret;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
r = APICR_TO_ADDR(r, APICR_VERSION);
|
||||
ret = HostIF_CopyFromUser(&dummy, r, sizeof dummy);
|
||||
set_fs(old_fs);
|
||||
ret = compat_copy_from_kernel_nofault(&dummy, r, sizeof(dummy));
|
||||
|
||||
return ret == 0;
|
||||
}
|
||||
@@ -2217,7 +2101,7 @@ SetVMAPICAddr(VMDriver *vm, // IN/OUT: driver state
|
||||
volatile void *hostapic;
|
||||
|
||||
ASSERT_ON_COMPILE(APICR_SIZE <= PAGE_SIZE);
|
||||
hostapic = (volatile void *) ioremap_nocache(ma, PAGE_SIZE);
|
||||
hostapic = (volatile void *) ioremap(ma, PAGE_SIZE);
|
||||
if (hostapic) {
|
||||
if ((APIC_VERSIONREG(hostapic) & 0xF0) == 0x10) {
|
||||
vm->hostAPIC.base = (volatile uint32 (*)[4]) hostapic;
|
||||
@@ -2373,44 +2257,41 @@ 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;
|
||||
|
||||
file = vmware_fget(waitFD);
|
||||
if (file == NULL) {
|
||||
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.
|
||||
*/
|
||||
|
||||
res = file->f_op->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 = kernel_read(file, &value, sizeof value, &file->f_pos);
|
||||
#endif
|
||||
if (res == sizeof value) {
|
||||
res = MX_WAITNORMAL;
|
||||
} else {
|
||||
@@ -2419,7 +2300,6 @@ HostIF_SemaphoreWait(VMDriver *vm, // IN:
|
||||
}
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
fput(file);
|
||||
|
||||
/*
|
||||
@@ -2502,8 +2382,8 @@ HostIF_SemaphoreForceWakeup(VMDriver *vm, // IN:
|
||||
int
|
||||
HostIF_SemaphoreSignal(uint64 *args) // IN:
|
||||
{
|
||||
struct eventfd_ctx *eventfd;
|
||||
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
|
||||
@@ -2513,22 +2393,34 @@ HostIF_SemaphoreSignal(uint64 *args) // IN:
|
||||
return MX_WAITERROR;
|
||||
}
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
/*
|
||||
* If it's eventfd, use specific eventfd interface as kernel writes
|
||||
* to eventfd may not be allowed in kernel 5.10 and later.
|
||||
*/
|
||||
eventfd = eventfd_ctx_fileget(file);
|
||||
if (!IS_ERR(eventfd)) {
|
||||
eventfd_signal(eventfd, 1);
|
||||
fput(file);
|
||||
return MX_WAITNORMAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
res = file->f_op->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 = kernel_write(file, &value, sizeof value, &file->f_pos);
|
||||
#endif
|
||||
|
||||
if (res == sizeof value) {
|
||||
res = MX_WAITNORMAL;
|
||||
}
|
||||
|
||||
set_fs(old_fs);
|
||||
fput(file);
|
||||
|
||||
/*
|
||||
@@ -3047,12 +2939,9 @@ static int
|
||||
HostIFFastClockThread(void *unused) // IN:
|
||||
{
|
||||
int res;
|
||||
mm_segment_t oldFS;
|
||||
unsigned int rate = 0;
|
||||
unsigned int prevRate = 0;
|
||||
|
||||
oldFS = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
allow_signal(SIGKILL);
|
||||
|
||||
while ((rate = linuxState.fastClockRate) > MIN_RATE) {
|
||||
@@ -3075,8 +2964,6 @@ HostIFFastClockThread(void *unused) // IN:
|
||||
}
|
||||
|
||||
out:
|
||||
set_fs(oldFS);
|
||||
|
||||
/*
|
||||
* Do not exit thread until we are told to do so.
|
||||
*/
|
||||
@@ -3174,7 +3061,7 @@ HostIF_SetFastClockRate(unsigned int rate) // IN: Frequency in Hz.
|
||||
}
|
||||
} else {
|
||||
if (linuxState.fastClockThread) {
|
||||
force_sig(SIGKILL, linuxState.fastClockThread);
|
||||
send_sig(SIGKILL, linuxState.fastClockThread, 1);
|
||||
kthread_stop(linuxState.fastClockThread);
|
||||
|
||||
linuxState.fastClockThread = NULL;
|
||||
|
||||
+6
-7
@@ -66,7 +66,7 @@
|
||||
#endif
|
||||
|
||||
#if LOGLEVEL >= 4
|
||||
static struct timeval vnetTime;
|
||||
static u64 vnetTime;
|
||||
#endif
|
||||
|
||||
typedef struct VNetBridge VNetBridge;
|
||||
@@ -693,7 +693,7 @@ VNetBridgeReceiveFromVNet(VNetJack *this, // IN: jack
|
||||
|
||||
netif_rx_ni(clone);
|
||||
# if LOGLEVEL >= 4
|
||||
do_gettimeofday(&vnetTime);
|
||||
vnetTime = ktime_get_ns();
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -1490,12 +1490,11 @@ VNetBridgeReceiveFromDev(struct sk_buff *skb, // IN: packet to receive
|
||||
|
||||
# if LOGLEVEL >= 4
|
||||
{
|
||||
struct timeval now;
|
||||
do_gettimeofday(&now);
|
||||
u64 now;
|
||||
|
||||
now = ktime_get_ns();
|
||||
LOG(3, (KERN_DEBUG "bridge-%s: time %d\n",
|
||||
bridge->name,
|
||||
(int)((now.tv_sec * 1000000 + now.tv_usec)
|
||||
- (vnetTime.tv_sec * 1000000 + vnetTime.tv_usec))));
|
||||
bridge->name, (int)((now - vnetTime) / NSEC_PER_USEC)));
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
@@ -161,6 +161,14 @@ VNetProcOpen(struct inode *inode, // IN:
|
||||
}
|
||||
|
||||
/* Our procfs callbacks. We only need to specialize open. */
|
||||
#ifdef DEFINE_PROC_SHOW_ATTRIBUTE
|
||||
static const struct proc_ops fops = {
|
||||
.proc_open = VNetProcOpen,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
};
|
||||
#else
|
||||
static struct file_operations fops = {
|
||||
.open = VNetProcOpen,
|
||||
.read = seq_read,
|
||||
@@ -168,6 +176,7 @@ static struct file_operations fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
+53
-18
@@ -78,19 +78,57 @@ 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
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) && defined(VERIFY_WRITE)
|
||||
#define write_access_ok(addr, size) access_ok(VERIFY_WRITE, addr, size)
|
||||
#else
|
||||
#define write_access_ok(addr, size) access_ok(addr, size)
|
||||
#endif
|
||||
|
||||
#if COMPAT_LINUX_VERSION_CHECK_LT(5, 10, 0)
|
||||
static inline
|
||||
__wsum compat_csum_and_copy_to_user(const void *src, void __user *dst, int len)
|
||||
{
|
||||
int err;
|
||||
__wsum ret;
|
||||
|
||||
ret = csum_and_copy_to_user(src, dst, len, 0, &err);
|
||||
return err ? 0 : ret;
|
||||
}
|
||||
#else
|
||||
static inline
|
||||
__wsum compat_csum_and_copy_to_user(const void *src, void __user *dst, int len)
|
||||
{
|
||||
return csum_and_copy_to_user(src, dst, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
@@ -543,7 +581,6 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
|
||||
char *buf) // OUT: where to copy data
|
||||
{
|
||||
unsigned int csum;
|
||||
int err = 0;
|
||||
int len = skb_headlen(skb) - offset;
|
||||
char *curr = buf;
|
||||
const skb_frag_t *frag;
|
||||
@@ -556,29 +593,27 @@ VNetCsumCopyDatagram(const struct sk_buff *skb, // IN: skb to copy
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
csum = csum_and_copy_to_user(skb->data + offset, curr, len, 0, &err);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
csum = compat_csum_and_copy_to_user(skb->data + offset, curr, len);
|
||||
if (!csum)
|
||||
return -EFAULT;
|
||||
curr += len;
|
||||
|
||||
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 = compat_csum_and_copy_to_user(vaddr + compat_skb_frag_off(frag),
|
||||
curr, compat_skb_frag_size(frag));
|
||||
compat_kunmap_frag(frag);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (!tmpCsum)
|
||||
return -EFAULT;
|
||||
csum = csum_block_add(csum, tmpCsum, curr - buf);
|
||||
curr += frag->size;
|
||||
curr += compat_skb_frag_size(frag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user