又遇到vmware不能启动了(vmware12/Deepin15.4(4.9.0kernel))

2024-01-04 03:38

本文主要是介绍又遇到vmware不能启动了(vmware12/Deepin15.4(4.9.0kernel)),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

有可能是内核从4.4升级到了4.9的缘故,原来可以工作的vmware12不能启动了,还是老样子,模块vmmon和vmnet


参考  https://communities.vmware.com/message/2604831

https://communities.vmware.com/thread/536977?start=0&tstart=0

使用脚本  https://bugfixes.promisedev.com/

但出现问题:

Starting VMware services:
   Virtual machine monitor                                            failed
   Virtual machine communication interface                             done
   VM communication interface socket family                            done
   Blocking file system                                                done
   Virtual ethernet                                                   failed
   VMware Authentication Daemon                                        done

仔细看编译过程,还是  get_user_pages 有问题,猜想有可能是因为4.9 新内核,使用 /usr/src/linux-headers-4.9.0-deepin4-common/include/linux/*.h等头文件和/usr/lib/vmware/modules/source/vmnet-only or vmmon-only/*.c 文件存在版本匹配问题

上面的参考并没有解决问题,但 http://www.jianshu.com/p/df30c0c3889b  一文提出了问题所在,就是内核更新后,同一个函数名,参数个数和形式有变化

在文件 /usr/src/linux-headers-4.9.0-deepin4-common/include/linux/mm.h 中(即新内核中)

long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
   unsigned long start, unsigned long nr_pages,
   unsigned int gup_flags, struct page **pages,
   struct vm_area_struct **vmas);
long get_user_pages(unsigned long start, unsigned long nr_pages,
   unsigned int gup_flags, struct page **pages,
   struct vm_area_struct **vmas);

在 vmnet-only/userif.c 中(即 vmware 12 的模块中)

struct page *page = NULL;
   int retval;

   down_read(&current->mm->mmap_sem);
   retval = get_user_pages(current, current->mm, addr,
  1, 1, 0, &page, NULL);

可以发现,即使把 get_user_pages 修改为 get_user_pages_remote,仍然存在参数个数不匹配的问题(get_user_pages_remote只有7个参数)

current 是宏,就是 get_current(),将返回 struct task_struct * 指针类型

仔细比对一下 4.4.0 内核中 mm.h 文件中的 get_user_pages,其形式如下:

long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
     unsigned long start, unsigned long nr_pages,
     unsigned int foll_flags, struct page **pages,
     struct vm_area_struct **vmas, int *nonblocking);
long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
   unsigned long start, unsigned long nr_pages,
   int write, int force, struct page **pages,
   struct vm_area_struct **vmas);

就是原来多一个 __get_user_pages,但没有 get_user_pages_remote,而 get_user_pages 有8个参数。怎么把8个参数中的 int write 和 int force 与7个参数中的 unsigned int gup_flags对应起来是个问题

花了不少时间,终于发现这些函数的实现在4.9内核的gup.c文件中 (参考linux内核源码  https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/mm/gup.c?h=linux-4.9.y )

long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages,
struct vm_area_struct **vmas)
{
return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
      NULL, false,
      gup_flags | FOLL_TOUCH | FOLL_REMOTE);
}

my god!其实是调用了 __get_user_pages_locked函数:

static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
struct mm_struct *mm,
unsigned long start,
unsigned long nr_pages,
struct page **pages,
struct vm_area_struct **vmas,
int *locked, bool notify_drop,
unsigned int flags)
{

.................

if (pages)
flags |= FOLL_GET;                     -------------->注意这里喽!

....................

ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
      vmas, locked);

....................

ret = __get_user_pages(tsk, mm, start, 1, flags | FOLL_TRIED,
      pages, NULL, NULL);

...............

}

继续看 __get_user_pages函数的第5个参数:

static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
unsigned int gup_flags, struct page **pages,
struct vm_area_struct **vmas, int *nonblocking)
{

.............................

VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));

if (!(gup_flags & FOLL_FORCE))
gup_flags |= FOLL_NUMA;


do {
struct page *page;
unsigned int foll_flags = gup_flags;

.............................

从这里,似乎可以看到 gup_flags 的相应位,和 FOLL_XXX 掩码定义是有关系的,特别关注 FOLL_FORCE 和 FOLL_WRITE,4.9内核的mm.h中

#define FOLL_WRITE 0x01/* check pte is writable */
#define FOLL_TOUCH 0x02/* mark page accessed */
#define FOLL_GET 0x04/* do get_page on page */
#define FOLL_DUMP 0x08/* give error on hole if it would be zero */
#define FOLL_FORCE 0x10/* get_user_pages read/write w/o permission */
#define FOLL_NOWAIT 0x20/* if a disk transfer is needed, start the IO
* and return without waiting upon it */

再去看老的内核中对应的函数

long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages, int write,
int force, struct page **pages, struct vm_area_struct **vmas)
{
return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
      pages, vmas, NULL, false, FOLL_TOUCH);
}

跟踪 __get_user_pages_locked 并关注第5\6参数 write \force

static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
struct mm_struct *mm,
unsigned long start,
unsigned long nr_pages,
int write, int force,
struct page **pages,
struct vm_area_struct **vmas,
int *locked, bool notify_drop,
unsigned int flags)
{

.....................

if (pages)
flags |= FOLL_GET;
if (write)
flags |= FOLL_WRITE;         ---------->注意这里喽!!!
if (force)
flags |= FOLL_FORCE;

在老版内核中,write/force信息是叠加到 flags参数的!所以,应该只需要按位将write/force换算到gup_flags就行了


cd /usr/lib/vmware/modules/source

sudo cp vmmon.tar  vmmon.tar.bak

sudo cp vmnet.tar  vmnet.tar.bak

sudo tar -xvf   vmmon.tar

sudo tar -xvf  vmnet.tar

需要修补的代码如下:

vmnet-only/userif.c 代码

retval = get_user_pages(current, current->mm, addr,
  1, 1, 0, &page, NULL);

修改为

retval = get_user_pages_remote(current, current->mm, addr,
  1, 1, &page, NULL);

vmmon-only/linux/hostif.c代码

retval = get_user_pages(current, current->mm, (unsigned long)uvAddr,
                           numPages, 0, 0, ppages, NULL);

修改为

retval = get_user_pages_remote(current, current->mm, (unsigned long)uvAddr,
                           numPages, 0, ppages, NULL);

重新打包

sudo rm vmmon.tar

sudo rm vmnet.tar

sudo tar  -cvf   vmnet.tar  vmnet-only

sudo tar -cvf  vmmon.tar vmmon-only


结果还是不行,参考  https://sysadmin.compxtreme.ro/vmware-modules-arch-linux-kernel-4-8-13/

vmmon-only/linux/hostif.c 修改

unsigned int anonPages = global_page_state(NR_ANON_PAGES);   --------->这句注释掉就可以了

unsigned int anonPages = global_page_state(NR_ANON_MAPPED);  


vmnet-only/netif.c 修改

dev->trans_start = jiffies;

netif_trans_update(dev);


这次老实了,根据 /tmp/vmware-root/目录下的错误日志log文件,手动修改文件并执行对应编译命令,看看会不会出错,终于,成功编译为 .ko

重复前面的步骤,重新打包为tar文件

sudo tar  -cvf   vmnet.tar  vmnet-only

sudo tar -cvf  vmmon.tar vmmon-only


yeah!!!!!!!!!!!!

这篇关于又遇到vmware不能启动了(vmware12/Deepin15.4(4.9.0kernel))的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/568048

相关文章

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

qtcreater配置opencv遇到的坑及实践记录

《qtcreater配置opencv遇到的坑及实践记录》我配置opencv不管是按照网上的教程还是deepseek发现都有些问题,下面是我的配置方法以及实践成功的心得,感兴趣的朋友跟随小编一起看看吧... 目录电脑环境下载环境变量配置qmake加入外部库测试配置我配置opencv不管是按照网上的教程还是de

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

电脑软件不能安装到C盘? 真相颠覆你的认知!

《电脑软件不能安装到C盘?真相颠覆你的认知!》很多人习惯把软件装到D盘、E盘,刻意绕开C盘,这种习惯从哪来?让我们用数据和案例,拆解背后的3大原因... 我身边不少朋友,在使用电脑安装软件的时候,总是习惯性的把软件安装到D盘或者E盘等位置,刻意避开C盘。如果你也有这样的习惯,或者不明白为什么要这么做,那么我

vscode不能打开终端问题的解决办法

《vscode不能打开终端问题的解决办法》:本文主要介绍vscode不能打开终端问题的解决办法,问题的根源是Windows的安全软件限制了PowerShell的运行,而VSCode默认使用Powe... 遇到vscode不能打开终端问题,一直以为是安全软件限制问题,也没搜到解决方案,因为影响也不大,就没有管