GPU Passthrough in Bhyve (2)

接着昨天继续折腾,目前并没有什么进展……

Windows 这边还是错误43。经常看某些视频的可能知道普通情况是显卡坏了,然而我这个显卡直接用是没问题的,所以还是 passthrough 有啥问题。

首先,说 NVidia 从某个版本开始,在驱动里面做了限制。如果检测到 VM,那就报43。围绕这个有很多办法,比如 KVM 那边可以设置一个 kvm=off (或者 libvirt 里面 hidden=on),隐藏 hypervisor 的存在。我看了眼那个 patch,照着改了几次 bhyve 里面的 CPUID 处理,另外还改了系统的 vendor 之类,然而依然没用。后来看见还有另一个办法:直接 patch 掉驱动里面的检测代码。我 patch 了一波,结果还是 43,那看来根本就不是这个检测的问题了……

那看来应该还是某种硬件上的问题。鉴于 Nouveau 跑得好好的,看来是某些不是那么关键的东西没有模拟对。Linux 虚拟机里面一开始有一堆错误,主要是 PCI BAR 分配的问题。

Bhyve 的 PCI BAR 分配很基础,就是从 0xC0000000 开始一路往上填。对于64位的 BAR,从64位的基础地址开始填。然而 Bhyve 的64位基础地址太高,所以其实搞下来一点就行。我为了尽可能模拟真实环境(我看我真机上64位 BAR 也是在32位地址空间里),hack 了一波分配逻辑,把显卡最大的那个64位 BAR 给塞到了 0xC0000000 – 0xD0000000,然后其他的直接从0xD0000000开始填。这么搞完之后,这部分错误就没有了。另一部分错误是因为 Bhyve 不关心 PCI ROM 那块的空间,所以 PCI Bridge 上面的资源窗口不包括 ROM 那块。因为 ROM 默认在 0xDF000000 – 0xDF00FFFF,我直接把窗口开到了 0xE0000000,那么这个错误也解决了。

所以现在就很尴尬,Linux 那边没啥错误,Nouveau 跑得挺好,官方驱动起不来,报RmInitAdapter Failed (0x31:0xffff:834),Windows下面错误43,也不清楚到底是哪里有问题……

剩下的疑点有几个:

  1. Linux那边的guide一般提到需要 VBIOS 支持 EFI。我看我 Windows 里面 VBIOS 访问并没有问题(GPU-Z还可以dump,结果和真机一样),所以VBIOS访问应该正常。然而是不是需要真的去跑这个VBIOS呢?比如说在OVMF固件里面?我也不知道……
  2. 中断可能有点问题,Linux有个错误说无法找到中断路径啥的,然而理论上不用MSI应该也能跑?比较奇怪……
  3. 貌似有些 PCI capability 没有传进去,两边的 lspci 结果有区别。

只能接着折腾了……

GPU Passthrough in Bhyve

所谓 GPU Passthrough 其实就是把一个 GPU 扔给虚拟机用。众所周知,虚拟机没法打游戏的主要问题就是显示性能不行,因为基本上没有 3D 加速。如果能够把整个显卡直接扔进去,那当然性能应该和原生的差不多,就可以打游戏了……

所以因为懒得重启到 win 下面打游戏,就想尝试在 Bhyve 搞这个。Linux 下面这套东西其实很成熟,大家都用 KVM 搞个 windows 虚拟机然后传个显卡进去,然而 FreeBSD 底下这个 Bhyve 么…… 问题还不少。

首先是设置一些设备为 passthrough 设备,这样 host 就管不着它们了。这个是在 /boot/loader.conf 里面加上

pptdevs="1/0/0 1/0/1"

至于为啥是这俩,是因为这俩是我显卡搞出来的俩 PCI 设备。装了 vm-bhyve 之后,直接 vm passthru 就能看见对应的 Bhyve ID 了。

弄完之后,直接在 VM 的配置文件(vm configure <vm name>)里面加上

passthru0="1/0/0=10:0"
passthru1="1/0/1=10:1"

就可以让这俩设备传给 VM 了。

当然,以上只是最基本的…… 接着跑个 windows 就会发现显卡错误43,跑个 Linux 会和你说啥 PCI BAR 地址不对之类。

根据某些网上的帖子,这个原因是 bhyve 没检查 CPU 能支持的最大地址,于是分了个巨高的地址给某个 BAR,结果高过头了…… 这个可以通过篡改 bhyve 解决:

#define PCI_EMUL_MEMBASE64  0xD0000000UL
#define PCI_EMUL_MEMLIMIT64 0xFD000000UL

改完这个之后,跑个 Linux,里面用上 nouveau 驱动,就可以在 VM 里跑加速桌面了……

然而官方驱动还是不行。根据 Linux 各种帖子的说法,是因为 NV 会检测虚拟机,检测到就不让跑…… KVM 为此有个选项能隐藏 hypervisor 信息。然而我照着那个在 bhyve 抄了一份,依旧没法跑…… 不知道是不是抄得不对…… 官方驱动现在 Linux 里会说 RmInitAdapter Failed …… 还需要研究研究……

因为 nouveau 不支持 cuda,搞个 Linux 桌面最多也就能跑几个 Linux 游戏而已,最终目标还是要搞出来 windows 桌面……

WFH Setup

因为长期的 WFH,貌似很多原来没有的需求都冒了出来。大概就是在电脑前面呆上八个小时,细微的不舒服的地方都会被放大的原因?于是购物冲动也多了起来……

桌子:首先是换了个桌子。之前是好多年前收来的二手货,这次因为要在家里开会于是决定换个位置,换了位置之后发现,原来桌子有个腿裂开了…… 那么就在 Amazon 戳了个新桌子,100$ 左右,感觉还挺不错,大小和原本的类似,结构非常简单:就是个木板加俩金属框。现在就是有点担心这个桌板时间长了会不会凹下去,毕竟之前宜家的桌子就凹了下去……

键盘掌托:换了桌子之后,注意到新桌子边缘经常勒手。老桌子边缘是圆角的,然而新桌子就是直角木板,结果就是把手腕勒得疼。于是就去 Amazon 搞了个掌托。先是搞了个橡胶类的,结果买来味道重还热,于是退掉换了个木头的,一开始还不太习惯,现在觉得挺不错的。感觉打字速度略有上升,估计是错觉……

鼠标掌托:键盘掌托只解决了键盘的问题,那鼠标当然也需要搞一个。这个目前只是下单了,还没送过来,不知道效果如何。

耳机:本来的耳机戴的时间短还好,时间长了略热,戴不住,于是去搞了个 HD 6XX,毕竟我之前戴的 HD 598 感觉非常舒服。来了之后嘛,反正音质能满足要求,戴着么感觉也还可以,虽然好像比 598 还是差一点,不过也还可以了。

显示器支架:这个东西目前还在考虑中。其实很早就想买,然而老桌子没法夹,所以一直拖着。买新桌子的时候就考虑到这个买了个边缘可以夹的。现在桌子已经准备好,就看啥时候支架降价……或者购物冲动再来了。

这个 WFH 看来至少要持续到六月份,所以估计购物冲动还会继续下去…… 比如最近又在考虑是不是折腾个新键盘之类…… 有个同事最近入了机械键盘坑(我只有一部分责任而已),才两周就已经搞了两个键盘了……

另外,现在看来当初买了个 Switch 真是个正确的决定……

PS. 鼠标掌托到货,这个就没啥气味,手感还挺好……

Pixel C 也鼓起来了

前两天突然发现,我平时插着电当时钟的 Pixel C 也鼓起来了。具体来说,屏幕隆起来,和背壳中间有了条缝:

鼓得最厉害的一条边

看见这个,作为一个已经鼓了两个平板一个手表的人,我迅速做出判断:又一个平板的电池鼓起来了……

我想能不能拆掉电池,就插电继续当时钟。然而这货并不好拆,iFixit 做过一个拆解,屏幕是用一圈胶黏在背壳(铝合金)上面的,硬掰的话,很容易掰坏屏幕(毕竟是一块玻璃)。

听说点吹风加热能好弄一点,于是我也试了一把,感觉有那么点效果。在拿一个塑料片子折腾了半天之后,终于把鼓得厉害的两条边分离了:

理论上完成了一半,然而后一半更麻烦……

然后继续拿塑料片划拉。屏幕和背壳之间那个胶可以慢慢蹭掉,每次划开一点。因为电池鼓着,所以划开之后基本就不会再合起来了。

蹭了很久之后,终于完全蹭开来了。分开之后是这个样子(有俩排线):

边上白色的就是胶。已经可以看出来电池鼓了……

断电之后,下一个问题就是咋拆掉电池。iFixit 的拆解都没拆电池,因为实在是粘得太牢。我拿了几张过期银行卡之类的在底下死命往里划拉,慢慢的还是把电池和背壳分离了开来。最后就是这个样子:

背面划拉得都是褶皱,好歹没破……

然后插电,发现大功率充电器能够启动到fastboot,然而不能进系统;小功率的根本不亮。简单来说,没电池看来不太行……

去网上看了眼,很少有卖这个电池的,大概三十一份,倒是不算贵。然而这货我基本也是吃灰状态,买来也没啥用。另外,根据之前 Nexus 7 2013的经验,买来的电池很快也会鼓…… 于是先暂时放着了。不知道这个显示面板能不能插到别的啥上面用用,比如这个 Pine64 之类的。

总的来说,我已经鼓了3个平板了:Pixel 7 2013,Surface Pro 4,以及 Pixel C。Surface Pro 4 微软给换了一个,到目前为止还没鼓起来。Pixel 7 2013 我倒是换过电池,然而没多久又鼓了。

这个 Pixel C 是 2016 年初买的,到现在差不多是4年。看了眼之前的blog,Nexus 7 是2017年买的,差不多也是4年。看来这种平板电池寿命就是4年,如果一直插在上面的话。Surface Pro 4 是18年鼓起来的,16年8月买的,看来是特别不行…… 可能和这货很容易温度特别高(这是个i7……)有关系……

网上说鼓起来基本是过充,虽然这些电池应该都有智能保护电路,估计一直插着就有这个问题。这样来看,不用的平板一直插着并不是啥好主意。这样的话,需要一直插着电的东西,还是选没电池的比较好。

看了眼现在当媒体播放器的 Pixel Slate,感觉也很危险,看来要考虑换一个设备当播放器了…… 其实我还有个 NVIDIA Shield,然而这货那个 Android TV 并不好用,不如 ChromeOS 来的灵活,所以看来还要换成别的比较好…… 比如一个 Chrome Box 啦,或者干脆弄个 HTPC 啦……

说起来这个板子鼓起来之前,屏幕开始有区域颜色不正常,有点发黄之类。考虑到之前 Surface Pro 鼓起来之前好像也有过这个问题,看来是电池鼓起来顶到了背光,导致颜色出问题的…… 以后再看见这个就知道又有平板要鼓起来了……

另外,摸了摸现役7寸板,一个便宜的联想平板,好像也…… 有点鼓?

多设备蓝牙键盘

这东西倒也没啥新鲜的,罗技基本上现在每个都有这个功能。然而家里键盘并不想换,反正还有个扔着没用的 Pine64,就考虑结合一下变成多设备蓝牙键盘……

输入嘛就靠libinput。这年头拿个输入还是很方便的,拿python的wrapper随便折腾折腾就有了。

蓝牙比较麻烦。本身蓝牙就比较复杂,要先搞 SDP 记录然后再接收连接。参考了网上直接模拟蓝牙键盘的代码,改改 HID 描述符加上鼠标,加上接收多个连接的功能,搞个快捷键切换设备,也就差不多了。

蓝牙键盘鼠标和 USB 的那套差不多,就是 HID 套个壳。这个倒是比较简单,之前也研究过 HID 描述符和 HID 报告的格式,随便折腾一下就能发送报告了。然而被 Python 3 的 bytes/str 坑了一波,最后发现 0xa1 发送成了 0xc2 0xa1 才注意到这个问题……

目前倒是折腾到能用,然而蓝牙那块还是有一些诡异的问题。比如说,Android 和 Linux 经常连不上来,看上去 bluez 这边发送的回复是说 Connection pending, Authentication pending,过一会就 fail 了,然而有时候又能跑,还需要更多研究……

至于为啥不直接用 synergy 或者远程跑个服务器然后发数据嘛…… 因为毕竟蓝牙比较通用,远程不需要啥设置,以及折腾折腾比较好玩……

说起来折腾这货还发现了奇妙的bug。只要(不)恰当地设置 SDP 记录,Windows一连上就会蓝屏…… KERNEL_SECRUITY_CHECK_EXCEPTION来着。

https://github.com/HenryHu/bthub/tree/master/src