不同的操作系统修改QEMU的操作步骤不同,可直接参考表1直接跳转到对应的内容。
虚拟机操作系统 |
参考步骤 |
---|---|
openEuler 22.03 LTS x86 openEuler 20.03 LTS openEuler 22.03 LTS SP4 BC Linux 8.2 BC Linux 21.10 CULinux 3.0 Kylin V10 Arm Kylin V10 SP2 Kylin V10 SP3 UOS V20(1050e) UOS V20(1050u2e) |
|
CentOS 7.5(5.10.0) Atlas 200T A2 Box16 异构子框+Tlinux3.1 |
|
A200T A3 Box8 超节点服务器+Tlinux3.1 |
|
Ubuntu 20.04 Ubuntu 22.04 veLinux 1.1 veLinux 1.1(5.10.200) |
|
veLinux 1.2 Debian10.8 Debian10.13 Debian11.8 |
|
Debian10(veLinux 1.3) |
yum install spice-server spice-server-devel -y
显示如下,表示安装成功。
Complete!
virsh version
Compiled against library: libvirt 7.0.0 Using library: libvirt 7.0.0 Using API: QEMU 7.0.0 Running hypervisor: QEMU 4.1.0
chmod +x ./qemu-4.1.0.tar.xz
tar -xf ./qemu-4.1.0.tar.xz
cd qemu-4.1.0/
增加如下加粗字体标注的代码并保存:
… #include "hw/nvram/fw_cfg.h" #include "pci.h" #include "trace.h" // ascend-patch begin #define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_DEVICE_ID_ASCEND910 0xd801 #define PCI_DEVICE_ID_ASCEND910_A2 0xd802 #define PCI_DEVICE_ID_ASCEND310P 0xd500 #define PCI_DEVICE_ID_ASCEND310B 0xd105 #define PCI_DEVICE_ID_ASCEND310 0xd100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN 0x100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX 0x10f #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN 0x110 #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX 0x11f #define ASCEND910_XLOADER_SIZE 4 #define ASCEND910_XLOADER_OFFSET 0x80400 #define ASCEND910_A2_XLOADER_SIZE 4 #define ASCEND910_A2_XLOADER_OFFSET 0x18208430 #define ASCEND310P_2P_BASE (128 * 1024 * 1024) #define ASCEND310P_1P_DEVNUM 1 #define ASCEND310P_2P_DEVNUM 2 #define ASCEND310P_XLOADER_SIZE 4 #define ASCEND310P_XLOADER_OFFSET 0x100430 #define ASCEND310B_XLOADER_SIZE 4 #define ASCEND310B_XLOADER_OFFSET 0x4430 #define ASCEND310_XLOADER_SIZE 4 #define ASCEND310_XLOADER_OFFSET 0x400 typedef struct VFIOAscendBarQuirk { struct VFIOPCIDevice *vdev; pcibus_t offset; uint8_t bar; MemoryRegion *mem; } VFIOAscendBarQuirk; static uint64_t vfio_ascend_quirk_read(void *opaque, hwaddr addr, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); return vfio_region_read(&vdev->bars[quirk->bar].region, addr + quirk->offset, size); } static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; qemu_log("modifying RO region is not allowed! addr=0x%" HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", addr + quirk->offset, data, size); } static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { .read = vfio_ascend_quirk_read, .write = vfio_ascend_quirk_write, .endianness = DEVICE_LITTLE_ENDIAN, }; static void vfio_probe_ascend910_a2_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910_A2) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND910_A2_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910_a2-bar2-intercept-regs-quirk", ASCEND910_A2_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar0_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || vdev->device_id != PCI_DEVICE_ID_ASCEND910) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); bar0_quirk[0].vdev = vdev; bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; bar0_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar0_quirk[0], "vfio-ascend910-bar0-intercept-regs-quirk", ASCEND910_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar0_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310p_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; int sub_device_id; int devnum = 0; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310P) { return; } sub_device_id = pci_get_word(vdev->pdev.config + PCI_SUBSYSTEM_ID); if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX) { devnum = ASCEND310P_1P_DEVNUM; } else if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX) { devnum = ASCEND310P_2P_DEVNUM; } if (devnum != ASCEND310P_1P_DEVNUM && devnum != ASCEND310P_2P_DEVNUM) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = devnum; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310P_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310p-bar2-1p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); if (devnum == ASCEND310P_2P_DEVNUM) { bar2_quirk[1].vdev = vdev; bar2_quirk[1].offset = (ASCEND310P_2P_BASE + ASCEND310P_XLOADER_OFFSET); bar2_quirk[1].bar = nr; memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend310p-bar2-2p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); } QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310b-bar2-intercept-regs-quirk", ASCEND310B_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar4_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || vdev->device_id != PCI_DEVICE_ID_ASCEND310) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); bar4_quirk[0].vdev = vdev; bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; bar4_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar4_quirk[0], "vfio-ascend310-bar4-intercept-regs-quirk", ASCEND310_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar4_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } // ascend-patch end …
void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
{
vfio_probe_ati_bar4_quirk(vdev, nr);
vfio_probe_ati_bar2_quirk(vdev, nr);
vfio_probe_nvidia_bar5_quirk(vdev, nr);
vfio_probe_nvidia_bar0_quirk(vdev, nr);
// ascend-patch begin
vfio_probe_ascend910_a2_bar2_quirk(vdev, nr);
vfio_probe_ascend910_bar0_quirk(vdev, nr);
vfio_probe_ascend310p_bar2_quirk(vdev, nr);
vfio_probe_ascend310b_bar2_quirk(vdev, nr);
vfio_probe_ascend310_bar4_quirk(vdev, nr);
// ascend-patch end
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
vfio_probe_igd_bar4_quirk(vdev, nr);
}…
执行如下命令,修改配置文件“./linux-user/syscall.c”的TARGET_NR_stime函数。
vi ./linux-user/syscall.c
#ifdef TARGET_NR_stime /* not on alpha */ case TARGET_NR_stime: { time_t host_time; if (get_user_sal(host_time, argl)) return -TARGET_EFAULT; struct timespec res; res.tv_sec = host_time; return get_errno(clock_settime(CLOCK_REALTIME, &res)); } #endif
vi ./configure
修改如下加粗字体的参数取值为“yes”并保存。
qom_cast_debug="yes" trace_backends="log" trace_file="trace" spice="yes" rbd="" smartcard="" libusb="" usb_redir="" opengl="" opengl_dmabuf="no" cpuid_h="no" avx2_opt=""
yum install ninja-build
显示如下,表示安装成功。
Complete!
./configure --enable-kvm
make -j 64
make install
不同的OS回显信息不同,具体回显信息请以实际环境为准。
Redirecting to /bin/systemctl restart libvirtd.service
sudo systemctl disable apparmor
Compiled against library: libvirt 6.0.0 Using library: libvirt 6.0.0 Using API: QEMU 6.0.0 Running hypervisor: QEMU 4.1.0
yum install spice-server spice-server-devel -y
对于Tlinux3.1:还需执行yum install -y python3 perl
显示如下,表示安装成功。
Complete!
virsh version
Compiled against library: libvirt 7.0.0 Using library: libvirt 7.0.0 Using API: QEMU 7.0.0 Running hypervisor: QEMU 4.1.0
chmod +x ./qemu-5.2.0.tar.xz
tar -xf ./qemu-5.2.0.tar.xz
cd qemu-5.2.0/
增加如下加粗字体标注的代码并保存:
… #include "hw/nvram/fw_cfg.h" #include "pci.h" #include "trace.h" // ascend-patch begin #define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_DEVICE_ID_ASCEND910 0xd801 #define PCI_DEVICE_ID_ASCEND910_A2 0xd802 #define PCI_DEVICE_ID_ASCEND310P 0xd500 #define PCI_DEVICE_ID_ASCEND310B 0xd105 #define PCI_DEVICE_ID_ASCEND310 0xd100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN 0x100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX 0x10f #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN 0x110 #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX 0x11f #define ASCEND910_XLOADER_SIZE 4 #define ASCEND910_XLOADER_OFFSET 0x80400 #define ASCEND910_A2_XLOADER_SIZE 4 #define ASCEND910_A2_XLOADER_OFFSET 0x18208430 #define ASCEND310P_2P_BASE (128 * 1024 * 1024) #define ASCEND310P_1P_DEVNUM 1 #define ASCEND310P_2P_DEVNUM 2 #define ASCEND310P_XLOADER_SIZE 4 #define ASCEND310P_XLOADER_OFFSET 0x100430 #define ASCEND310B_XLOADER_SIZE 4 #define ASCEND310B_XLOADER_OFFSET 0x4430 #define ASCEND310_XLOADER_SIZE 4 #define ASCEND310_XLOADER_OFFSET 0x400 typedef struct VFIOAscendBarQuirk { struct VFIOPCIDevice *vdev; pcibus_t offset; uint8_t bar; MemoryRegion *mem; } VFIOAscendBarQuirk; static uint64_t vfio_ascend_quirk_read(void *opaque, hwaddr addr, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); return vfio_region_read(&vdev->bars[quirk->bar].region, addr + quirk->offset, size); } static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; qemu_log("modifying RO region is not allowed! addr=0x%" HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", addr + quirk->offset, data, size); } static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { .read = vfio_ascend_quirk_read, .write = vfio_ascend_quirk_write, .endianness = DEVICE_LITTLE_ENDIAN, }; static void vfio_probe_ascend910_a2_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910_A2) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND910_A2_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910_a2-bar2-intercept-regs-quirk", ASCEND910_A2_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar0_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || vdev->device_id != PCI_DEVICE_ID_ASCEND910) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); bar0_quirk[0].vdev = vdev; bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; bar0_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar0_quirk[0], "vfio-ascend910-bar0-intercept-regs-quirk", ASCEND910_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar0_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310p_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; int sub_device_id; int devnum = 0; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310P) { return; } sub_device_id = pci_get_word(vdev->pdev.config + PCI_SUBSYSTEM_ID); if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX) { devnum = ASCEND310P_1P_DEVNUM; } else if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX) { devnum = ASCEND310P_2P_DEVNUM; } if (devnum != ASCEND310P_1P_DEVNUM && devnum != ASCEND310P_2P_DEVNUM) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = devnum; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310P_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310p-bar2-1p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); if (devnum == ASCEND310P_2P_DEVNUM) { bar2_quirk[1].vdev = vdev; bar2_quirk[1].offset = (ASCEND310P_2P_BASE + ASCEND310P_XLOADER_OFFSET); bar2_quirk[1].bar = nr; memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend310p-bar2-2p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); } QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310b-bar2-intercept-regs-quirk", ASCEND310B_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar4_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || vdev->device_id != PCI_DEVICE_ID_ASCEND310) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); bar4_quirk[0].vdev = vdev; bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; bar4_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar4_quirk[0], "vfio-ascend310-bar4-intercept-regs-quirk", ASCEND310_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar4_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } // ascend-patch end …
void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
{
vfio_probe_ati_bar4_quirk(vdev, nr);
vfio_probe_ati_bar2_quirk(vdev, nr);
vfio_probe_nvidia_bar5_quirk(vdev, nr);
vfio_probe_nvidia_bar0_quirk(vdev, nr);
// ascend-patch begin
vfio_probe_ascend910_a2_bar2_quirk(vdev, nr);
vfio_probe_ascend910_bar0_quirk(vdev, nr);
vfio_probe_ascend310p_bar2_quirk(vdev, nr);
vfio_probe_ascend310b_bar2_quirk(vdev, nr);
vfio_probe_ascend310_bar4_quirk(vdev, nr);
// ascend-patch end
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
vfio_probe_igd_bar4_quirk(vdev, nr);
}…
#ifdef TARGET_NR_stime /* not on alpha */ case TARGET_NR_stime: { time_t host_time; if (get_user_sal(host_time, argl)) return -TARGET_EFAULT; struct timespec res; res.tv_sec = host_time; return get_errno(clock_settime(CLOCK_REALTIME, &res)); } #endif
增加如下加粗字体标注的内容并保存。
static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { … if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { if (accel_uses_host_cpuid()) { uint32_t host_phys_bits = x86_host_phys_bits(); static bool warned; cpu->host_phys_bits = true; … } else { … } … }
vi ./linux-user/strace.c
增加如下加粗字体内容并保存。
#include "qemu/osdep.h" #include <sys/ipc.h> #include <sys/msg.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/select.h> #include <sys/mount.h> #include <arpa/inet.h> #include <netinet/tcp.h> #include <linux/if_packet.h> #include <linux/netlink.h> #include <linux/falloc.h> #include <sched.h> #include "qemu.h"
vi ./configure
修改如下加粗字体的参数取值为“yes”并保存。
qom_cast_debug="yes" trace_backends="log" trace_file="trace" spice="yes" rbd="" smartcard="" libusb="" usb_redir="" opengl="" opengl_dmabuf="no" cpuid_h="no" avx2_opt=""
yum install -y ninja-build libffi-devel unzip
显示如下,表示安装成功。
Complete!
./configure --enable-kvm
make -j 64
make install
不同的OS回显信息不同,具体回显信息请以实际环境为准。
Redirecting to /bin/systemctl restart libvirtd.service
sudo systemctl disable apparmor
Compiled against library: libvirt 6.0.0 Using library: libvirt 6.0.0 Using API: QEMU 6.0.0 Running hypervisor: QEMU 5.2.0
yum install epel-release -y
yum install libvirt* virt-install virt-viewer virt-manager bridge-utils -y
yum install git glib2-devel libfdt-devel pixman-devel zlib-devel bzip2 ninja-build python3 -y
yum install numactl-devel spice-server* spice-protocol -y
显示如下,表示安装成功。
Complete!
virsh version
Compiled against library: libvirt 7.0.0 Using library: libvirt 7.0.0 Using API: QEMU 7.0.0 Running hypervisor: QEMU 4.1.0
chmod +x ./qemu-4.1.0.tar.xz
tar -xf ./qemu-4.1.0.tar.xz
cd qemu-4.1.0/
增加如下加粗字体标注的代码并保存。
static VFIOQuirk *vfio_quirk_alloc(int nr_mem) return quirk; } // ascend-patch begin #define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_DEVICE_ID_ASCEND910 0xd801 #define PCI_DEVICE_ID_ASCEND910A2 0xd802 #define PCI_DEVICE_ID_ASCEND910A3 0xd803 #define PCI_DEVICE_ID_ASCEND310P 0xd500 #define PCI_DEVICE_ID_ASCEND310B 0xd105 #define PCI_DEVICE_ID_ASCEND310 0xd100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN 0x100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX 0x10f #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN 0x110 #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX 0x11f #define ASCEND910_XLOADER_SIZE 4 #define ASCEND910_XLOADER_OFFSET 0x80400 #define ASCEND910A2_XLOADER_SIZE 4 #define ASCEND910A2_XLOADER_OFFSET 0x18208430 #define ASCEND910A3_XLOADER_SIZE 4 #define ASCEND910A3_XLOADER_OFFSET 0x18208430 #define ASCEND910A3_FEATURE_SIZE 4 #define ASCEND910A3_FEATURE_OFFSET 0x182085f8 #define ASCEND310P_2P_BASE (128 * 1024 * 1024) #define ASCEND310P_1P_DEVNUM 1 #define ASCEND310P_2P_DEVNUM 2 #define ASCEND310P_XLOADER_SIZE 4 #define ASCEND310P_XLOADER_OFFSET 0x100430 #define ASCEND310B_XLOADER_SIZE 4 #define ASCEND310B_XLOADER_OFFSET 0x4430 #define ASCEND310_XLOADER_SIZE 4 #define ASCEND310_XLOADER_OFFSET 0x400 enum { VFIO_ASCEND_TYPE_ERR = 0, VFIO_ASCEND_TYPE_XLOADER = 1, VFIO_ASCEND_TYPE_FEATURE = 2, }; enum { QIURK_READ_SIZE_1_BYTE = 1, QIURK_READ_SIZE_2_BYTE = 2, QIURK_READ_SIZE_4_BYTE = 4, }; typedef struct VFIOAscendBarQuirk { struct VFIOPCIDevice *vdev; pcibus_t offset; unsigned int flags; /* for normal NC */ int type; /* XLOADER or FEATURE or etc. */ uint8_t bar; MemoryRegion *mem; } VFIOAscendBarQuirk; static uint64_t vfio_ascend_quirk_read(void *opaque, hwaddr addr, unsigned size) { uint64_t value, off_value; const unsigned byte_size = 8; unsigned start = addr * byte_size, length_size = size * byte_size; VFIOAscendBarQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); switch (quirk->type) { case VFIO_ASCEND_TYPE_XLOADER: value = vfio_region_read(&vdev->bars[quirk->bar].region, addr + quirk->offset, size); break; case VFIO_ASCEND_TYPE_FEATURE: switch (size) { case QIURK_READ_SIZE_1_BYTE: case QIURK_READ_SIZE_2_BYTE: case QIURK_READ_SIZE_4_BYTE: off_value = ((uint64_t)quirk->flags >> start) & ((1UL << length_size) - 1); return le64_to_cpu(off_value); default: qemu_log("Ascend quirk unsupported read size, %d bytes\n", size); return 0; } default: qemu_log("read RO region error type! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); return 0; } return value; } static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; qemu_log("modifying RO region is not allowed! addr=0x%" HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", addr + quirk->offset, data, size); } static unsigned int vfio_ascend_get_region_flags(VFIOPCIDevice *vdev, int nr) { int ret = 0; unsigned int flags; VFIODevice *vbasedev = &vdev->vbasedev; struct vfio_region_info *reg_info; ret = vfio_get_region_info(vbasedev, nr, ®_info); if (ret != 0) { qemu_log("Ascend failed to get region %d info\n", nr); return 0; } flags = reg_info->flags; g_free(reg_info); return flags; } static unsigned int vfio_ascend_get_all_regions_flags(VFIOPCIDevice *vdev) { int i = 0; unsigned int flag = 0, flags = 0; for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) { flag = vfio_ascend_get_region_flags(vdev, i); if (flag & VFIO_REGION_INFO_FLAG_NORMAL_NC) { flags |= (1 << i); } } return flags; } static void vfio_ascend_set_bar_quirk_array(VFIOAscendBarQuirk *bar_quirk, VFIOPCIDevice *vdev, int index, pcibus_t offset, unsigned int flags, int type, uint8_t bar) { bar_quirk[index].vdev = vdev; bar_quirk[index].offset = offset; bar_quirk[index].flags = flags; bar_quirk[index].type = type; bar_quirk[index].bar = bar; } static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { .read = vfio_ascend_quirk_read, .write = vfio_ascend_quirk_write, .endianness = DEVICE_LITTLE_ENDIAN, }; static void vfio_probe_ascend910a3_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; const int quirk_region_num = 2; /* XLOADER and FEATURE */ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910A3) { return; } quirk = vfio_quirk_alloc(quirk_region_num); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); vfio_ascend_set_bar_quirk_array(bar2_quirk, vdev, 0, ASCEND910A3_XLOADER_OFFSET, 0, VFIO_ASCEND_TYPE_XLOADER, nr); /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910a3-bar2-intercept-regs-quirk", ASCEND910A3_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); /* 910A3 FEATURE */ vfio_ascend_set_bar_quirk_array(bar2_quirk, vdev, 1, ASCEND910A3_FEATURE_OFFSET, vfio_ascend_get_all_regions_flags(vdev), VFIO_ASCEND_TYPE_FEATURE, nr); memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend910a3-bar2-feature-regs-quirk", ASCEND910A3_FEATURE_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910a2_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910A2) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND910A2_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910a2-bar2-intercept-regs-quirk", ASCEND910A2_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar0_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || vdev->device_id != PCI_DEVICE_ID_ASCEND910) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); bar0_quirk[0].vdev = vdev; bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; bar0_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar0_quirk[0], "vfio-ascend910-bar0-intercept-regs-quirk", ASCEND910_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar0_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310p_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; int sub_device_id; int devnum = 0; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310P) { return; } sub_device_id = pci_get_word(vdev->pdev.config + PCI_SUBSYSTEM_ID); if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX) { devnum = ASCEND310P_1P_DEVNUM; } else if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX) { devnum = ASCEND310P_2P_DEVNUM; } if (devnum != ASCEND310P_1P_DEVNUM && devnum != ASCEND310P_2P_DEVNUM) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = devnum; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310P_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310p-bar2-1p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); if (devnum == ASCEND310P_2P_DEVNUM) { bar2_quirk[1].vdev = vdev; bar2_quirk[1].offset = (ASCEND310P_2P_BASE + ASCEND310P_XLOADER_OFFSET); bar2_quirk[1].bar = nr; memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend310p-bar2-2p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); } QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310b-bar2-intercept-regs-quirk", ASCEND310B_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar4_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || vdev->device_id != PCI_DEVICE_ID_ASCEND310) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); bar4_quirk[0].vdev = vdev; bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; bar4_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar4_quirk[0], "vfio-ascend310-bar4-intercept-regs-quirk", ASCEND310_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar4_quirk[0].offset, &quirk->mem[0], ); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } // ascend-patch end static void vfio_ioeventfd_exit(VFIOPCIDevice *vdev, VFIOIOEventFD *ioeventfd) { QLIST_REMOVE(ioeventfd, next);
void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) { vfio_probe_ati_bar4_quirk(vdev, nr); vfio_probe_ati_bar2_quirk(vdev, nr); vfio_probe_nvidia_bar5_quirk(vdev, nr); vfio_probe_nvidia_bar0_quirk(vdev, nr); // ascend-patch begin vfio_probe_ascend910a3_bar2_quirk(vdev, nr); vfio_probe_ascend910a2_bar2_quirk(vdev, nr); vfio_probe_ascend910_bar0_quirk(vdev, nr); vfio_probe_ascend310p_bar2_quirk(vdev, nr); vfio_probe_ascend310b_bar2_quirk(vdev, nr); vfio_probe_ascend310_bar4_quirk(vdev, nr); // ascend-patch end #ifdef CONFIG_VFIO_IGD vfio_probe_igd_bar4_quirk(vdev, nr); #endif }…
修改extended_memmap数组定义,加粗字体由512修改至2048后保存。
static MemMapEntry extended_memmap[] = { /* Additional 64 MB redist region (can contain up to 512 redistributors) */ [VIRT_HIGH_GIC_REDIST2] = { 0x0, 64 * MiB }, [VIRT_HIGH_PCIE_ECAM] = { 0x0, 256 * MiB }, /* Second PCIe window */ [VIRT_HIGH_PCIE_MMIO] = { 0x0, 2048 * GiB },
vi ./linux-headers/linux/vfio.h
增加如下加粗字体标注的代码并保存。
struct vfio_region_info { __u32 argsz; __u32 flags; #define VFIO_REGION_INFO_FLAG_READ (1 << 0) /* Region supports read */ #define VFIO_REGION_INFO_FLAG_WRITE (1 << 1) /* Region supports write */ #define VFIO_REGION_INFO_FLAG_MMAP (1 << 2) /* Region supports mmap */ #define VFIO_REGION_INFO_FLAG_CAPS (1 << 3) /* Info supports caps */ #define VFIO_REGION_INFO_FLAG_NORMAL_NC (1 << 4) /* Region supports normal NC */ __u32 index; /* Region index */ __u32 cap_offset; /* Offset within info struct of first cap */ __u64 size; /* Region size (bytes) */ __u64 offset; /* Region offset from start of device fd */ };
vi ./linux-user/strace.c
增加如下加粗字体内容并保存。
#include "qemu/osdep.h" #include <sys/ipc.h> #include <sys/msg.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/select.h> #include <sys/mount.h> #include <arpa/inet.h> #include <netinet/tcp.h> #include <linux/if_packet.h> #include <linux/netlink.h> #include <linux/falloc.h> #include <sched.h> #include "qemu.h"
增加如下加粗字体标注的内容并保存。
static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { … if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { if (accel_uses_host_cpuid()) { uint32_t host_phys_bits = x86_host_phys_bits(); static bool warned; cpu->host_phys_bits = true; … } else { … } … }
yum install -y ninja-build libffi-devel unzip
显示如下,表示安装成功。
Complete!
./configure --enable-kvm
make -j 64
make install
不同的OS回显信息不同,具体回显信息请以实际环境为准。
Redirecting to /bin/systemctl restart libvirtd.service
sudo systemctl disable apparmor
Compiled against library: libvirt 8.0.0 Using library: libvirt 8.0.0 Using API: QEMU 8.0.0 Running hypervisor: QEMU 4.1.0
apt-get install -y ninja-build gcc pkg-config build-essential zlib1g-dev libglib2.0-dev libmount-dev libpixman-1-dev
apt-get install -y libusbredirhost-dev libusbredirhost1 libusbredirparser-dev libusbredirparser1 usbredirserver
apt-get install libspice-server-dev libspice-server1
Reading package lists... DoneBuilding dependency treeReading state information... Donelibspice-server1 is already the newest version (0.14.2-4ubuntu3.1).libspice-server1 set to manually installed.The following NEW packages will be installed: libspice-protocol-dev libspice-server-dev0 upgraded, 2 newly installed, 0 to remove and 263 not upgraded.Need to get 31.8 kB of archives.After this operation, 198 kB of additional disk space will be used.Get:1 http://ports.ubuntu.com/ubuntu-ports focal/main arm64 libspice-protocol-dev all 0.14.0-0ubuntu1 [21.5 kB]Get:2 http://ports.ubuntu.com/ubuntu-ports focal-updates/main arm64 libspice-server-dev arm64 0.14.2-4ubuntu3.1 [10.3 kB]Fetched 31.8 kB in 8s (3,903 B/s)Selecting previously unselected package libspice-protocol-dev.(Reading database ... 97326 files and directories currently installed.)Preparing to unpack .../libspice-protocol-dev_0.14.0-0ubuntu1_all.deb ...
virsh version
Compiled against library: libvirt 7.0.0 Using library: libvirt 7.0.0 Using API: QEMU 7.0.0 Running hypervisor: QEMU 4.1.0
对于Atlas 200T A2 Box16 异构子框,建议下载5.2.0版本的QEMU源码包。
chmod +x ./qemu-4.1.0.tar.xz
tar -xf ./qemu-4.1.0.tar.xz
cd qemu-4.1.0/
增加如下加粗字体标注的代码并保存:
… #include "hw/nvram/fw_cfg.h" #include "pci.h" #include "trace.h" // ascend-patch begin #define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_DEVICE_ID_ASCEND910 0xd801 #define PCI_DEVICE_ID_ASCEND910_A2 0xd802 #define PCI_DEVICE_ID_ASCEND310P 0xd500 #define PCI_DEVICE_ID_ASCEND310B 0xd105 #define PCI_DEVICE_ID_ASCEND310 0xd100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN 0x100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX 0x10f #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN 0x110 #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX 0x11f #define ASCEND910_XLOADER_SIZE 4 #define ASCEND910_XLOADER_OFFSET 0x80400 #define ASCEND910_A2_XLOADER_SIZE 4 #define ASCEND910_A2_XLOADER_OFFSET 0x18208430 #define ASCEND310P_2P_BASE (128 * 1024 * 1024) #define ASCEND310P_1P_DEVNUM 1 #define ASCEND310P_2P_DEVNUM 2 #define ASCEND310P_XLOADER_SIZE 4 #define ASCEND310P_XLOADER_OFFSET 0x100430 #define ASCEND310B_XLOADER_SIZE 4 #define ASCEND310B_XLOADER_OFFSET 0x4430 #define ASCEND310_XLOADER_SIZE 4 #define ASCEND310_XLOADER_OFFSET 0x400 typedef struct VFIOAscendBarQuirk { struct VFIOPCIDevice *vdev; pcibus_t offset; uint8_t bar; MemoryRegion *mem; } VFIOAscendBarQuirk; static uint64_t vfio_ascend_quirk_read(void *opaque, hwaddr addr, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); return vfio_region_read(&vdev->bars[quirk->bar].region, addr + quirk->offset, size); } static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; qemu_log("modifying RO region is not allowed! addr=0x%" HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", addr + quirk->offset, data, size); } static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { .read = vfio_ascend_quirk_read, .write = vfio_ascend_quirk_write, .endianness = DEVICE_LITTLE_ENDIAN, }; static void vfio_probe_ascend910_a2_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910_A2) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND910_A2_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910_a2-bar2-intercept-regs-quirk", ASCEND910_A2_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar0_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || vdev->device_id != PCI_DEVICE_ID_ASCEND910) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); bar0_quirk[0].vdev = vdev; bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; bar0_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar0_quirk[0], "vfio-ascend910-bar0-intercept-regs-quirk", ASCEND910_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar0_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310p_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; int sub_device_id; int devnum = 0; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310P) { return; } sub_device_id = pci_get_word(vdev->pdev.config + PCI_SUBSYSTEM_ID); if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX) { devnum = ASCEND310P_1P_DEVNUM; } else if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX) { devnum = ASCEND310P_2P_DEVNUM; } if (devnum != ASCEND310P_1P_DEVNUM && devnum != ASCEND310P_2P_DEVNUM) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = devnum; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310P_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310p-bar2-1p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); if (devnum == ASCEND310P_2P_DEVNUM) { bar2_quirk[1].vdev = vdev; bar2_quirk[1].offset = (ASCEND310P_2P_BASE + ASCEND310P_XLOADER_OFFSET); bar2_quirk[1].bar = nr; memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend310p-bar2-2p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); } QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310b-bar2-intercept-regs-quirk", ASCEND310B_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar4_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || vdev->device_id != PCI_DEVICE_ID_ASCEND310) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); bar4_quirk[0].vdev = vdev; bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; bar4_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar4_quirk[0], "vfio-ascend310-bar4-intercept-regs-quirk", ASCEND310_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar4_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } // ascend-patch end …
void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
{
vfio_probe_ati_bar4_quirk(vdev, nr);
vfio_probe_ati_bar2_quirk(vdev, nr);
vfio_probe_nvidia_bar5_quirk(vdev, nr);
vfio_probe_nvidia_bar0_quirk(vdev, nr);
// ascend-patch begin
vfio_probe_ascend910_a2_bar2_quirk(vdev, nr);
vfio_probe_ascend910_bar0_quirk(vdev, nr);
vfio_probe_ascend310p_bar2_quirk(vdev, nr);
vfio_probe_ascend310b_bar2_quirk(vdev, nr);
vfio_probe_ascend310_bar4_quirk(vdev, nr);
// ascend-patch end
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
vfio_probe_igd_bar4_quirk(vdev, nr);
}…
对于Atlas 800 训练服务器(型号:9000)/Atlas 800 训练服务器(型号:9010),请跳过此步骤。
vi ./linux-user/syscall.c
#ifdef TARGET_NR_stime /* not on alpha */ case TARGET_NR_stime: { time_t host_time; if (get_user_sal(host_time, argl)) return -TARGET_EFAULT; struct timespec res; res.tv_sec = host_time; return get_errno(clock_settime(CLOCK_REALTIME, &res)); } #endif
vi ./target/i386/cpu.c
增加如下加粗字体内容并保存。
static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { … if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { if (accel_uses_host_cpuid()) { uint32_t host_phys_bits = x86_host_phys_bits(); static bool warned; cpu->host_phys_bits = true; … } else { … } … }
vi ./configure
修改如下加粗字体的参数取值为“yes”并保存。
qom_cast_debug="yes" trace_backends="log" trace_file="trace" spice="yes" rbd="" smartcard="" libusb="" usb_redir="" opengl="" opengl_dmabuf="no" cpuid_h="no" avx2_opt=""
./configure --enable-kvm
make -j 64
make install
不同的OS回显信息不同,具体回显信息请以实际环境为准。
Redirecting to /bin/systemctl restart libvirtd.service
sudo systemctl disable apparmor
Compiled against library: libvirt 6.0.0 Using library: libvirt 6.0.0 Using API: QEMU 6.0.0 Running hypervisor: QEMU 4.1.0
apt install -y make gcc pkg-config build-essential zlib1g-dev libglib2.0-dev libmount-dev libpixman-1-dev --allow-unauthenticated
apt install -y libusbredirhost1 libusbredirparser1
apt install libspice-server1 ninja*
Reading package lists... Done Building dependency tree... Done Reading state information... Done libspice-server1 is already the newest version (0.14.3-2.1). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
virsh version
Compiled against library: libvirt 7.0.0 Using library: libvirt 7.0.0 Using API: QEMU 7.0.0 Running hypervisor: QEMU 4.1.0
chmod +x ./qemu-4.1.0.tar.xz
tar -xf ./qemu-4.1.0.tar.xz
cd qemu-4.1.0/
增加如下加粗字体标注的代码并保存:
… #include "hw/nvram/fw_cfg.h" #include "pci.h" #include "trace.h" // ascend-patch begin #define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_DEVICE_ID_ASCEND910 0xd801 #define PCI_DEVICE_ID_ASCEND910_A2 0xd802 #define PCI_DEVICE_ID_ASCEND310P 0xd500 #define PCI_DEVICE_ID_ASCEND310B 0xd105 #define PCI_DEVICE_ID_ASCEND310 0xd100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN 0x100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX 0x10f #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN 0x110 #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX 0x11f #define ASCEND910_XLOADER_SIZE 4 #define ASCEND910_XLOADER_OFFSET 0x80400 #define ASCEND910_A2_XLOADER_SIZE 4 #define ASCEND910_A2_XLOADER_OFFSET 0x18208430 #define ASCEND310P_2P_BASE (128 * 1024 * 1024) #define ASCEND310P_1P_DEVNUM 1 #define ASCEND310P_2P_DEVNUM 2 #define ASCEND310P_XLOADER_SIZE 4 #define ASCEND310P_XLOADER_OFFSET 0x100430 #define ASCEND310B_XLOADER_SIZE 4 #define ASCEND310B_XLOADER_OFFSET 0x4430 #define ASCEND310_XLOADER_SIZE 4 #define ASCEND310_XLOADER_OFFSET 0x400 typedef struct VFIOAscendBarQuirk { struct VFIOPCIDevice *vdev; pcibus_t offset; uint8_t bar; MemoryRegion *mem; } VFIOAscendBarQuirk; static uint64_t vfio_ascend_quirk_read(void *opaque, hwaddr addr, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); return vfio_region_read(&vdev->bars[quirk->bar].region, addr + quirk->offset, size); } static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; qemu_log("modifying RO region is not allowed! addr=0x%" HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", addr + quirk->offset, data, size); } static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { .read = vfio_ascend_quirk_read, .write = vfio_ascend_quirk_write, .endianness = DEVICE_LITTLE_ENDIAN, }; static void vfio_probe_ascend910_a2_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910_A2) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND910_A2_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910_a2-bar2-intercept-regs-quirk", ASCEND910_A2_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar0_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || vdev->device_id != PCI_DEVICE_ID_ASCEND910) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); bar0_quirk[0].vdev = vdev; bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; bar0_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar0_quirk[0], "vfio-ascend910-bar0-intercept-regs-quirk", ASCEND910_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar0_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310p_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; int sub_device_id; int devnum = 0; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310P) { return; } sub_device_id = pci_get_word(vdev->pdev.config + PCI_SUBSYSTEM_ID); if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX) { devnum = ASCEND310P_1P_DEVNUM; } else if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX) { devnum = ASCEND310P_2P_DEVNUM; } if (devnum != ASCEND310P_1P_DEVNUM && devnum != ASCEND310P_2P_DEVNUM) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = devnum; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310P_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310p-bar2-1p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); if (devnum == ASCEND310P_2P_DEVNUM) { bar2_quirk[1].vdev = vdev; bar2_quirk[1].offset = (ASCEND310P_2P_BASE + ASCEND310P_XLOADER_OFFSET); bar2_quirk[1].bar = nr; memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend310p-bar2-2p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); } QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310b-bar2-intercept-regs-quirk", ASCEND310B_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar4_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || vdev->device_id != PCI_DEVICE_ID_ASCEND310) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); bar4_quirk[0].vdev = vdev; bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; bar4_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar4_quirk[0], "vfio-ascend310-bar4-intercept-regs-quirk", ASCEND310_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar4_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } // ascend-patch end …
void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
{
vfio_probe_ati_bar4_quirk(vdev, nr);
vfio_probe_ati_bar2_quirk(vdev, nr);
vfio_probe_nvidia_bar5_quirk(vdev, nr);
vfio_probe_nvidia_bar0_quirk(vdev, nr);
// ascend-patch begin
vfio_probe_ascend910_a2_bar2_quirk(vdev, nr);
vfio_probe_ascend910_bar0_quirk(vdev, nr);
vfio_probe_ascend310p_bar2_quirk(vdev, nr);
vfio_probe_ascend310b_bar2_quirk(vdev, nr);
vfio_probe_ascend310_bar4_quirk(vdev, nr);
// ascend-patch end
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
vfio_probe_igd_bar4_quirk(vdev, nr);
}…
#ifdef TARGET_NR_stime /* not on alpha */ case TARGET_NR_stime: { time_t host_time; if (get_user_sal(host_time, argl)) return -TARGET_EFAULT; struct timespec res; res.tv_sec = host_time; return get_errno(clock_settime(CLOCK_REALTIME, &res)); } #endif
./configure --enable-kvm
make -j 64
make install
不同的OS回显信息不同,具体回显信息请以实际环境为准。
Redirecting to /bin/systemctl restart libvirtd.service
sudo systemctl disable apparmor
不同的OS回显信息不同,具体回显信息请以实际环境为准。
Synchronizing state of apparmor.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable apparmor Removed /etc/systemd/system/sysinit.target.wants/apparmor.service
若系统环境为Debian10.13/veLinux 1.2系统,可跳过此步骤。
Compiled against library: libvirt 6.0.0 Using library: libvirt 6.0.0 Using API: QEMU 6.0.0 Running hypervisor: QEMU 4.1.0
apt install -y make gcc pkg-config build-essential zlib1g-dev libglib2.0-dev libmount-dev libpixman-1-dev --allow-unauthenticated
apt install -y libusbredirhost1 libusbredirparser1
Reading package lists... Done Building dependency tree... Done Reading state information... Done libspice-server1 is already the newest version (0.14.3-2.1). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
virsh version
Compiled against library: libvirt 7.0.0 Using library: libvirt 7.0.0 Using API: QEMU 7.0.0 Running hypervisor: QEMU 4.1.0
chmod +x ./qemu-8.1.0.tar.xz
tar -xf ./qemu-8.1.0.tar.xz
cd qemu-8.1.0/
增加如下加粗字体标注的代码并保存:
… #include "hw/nvram/fw_cfg.h" #include "pci.h" #include "trace.h" // ascend-patch begin #define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_DEVICE_ID_ASCEND910 0xd801 #define PCI_DEVICE_ID_ASCEND910_A2 0xd802 #define PCI_DEVICE_ID_ASCEND910_A3 0xd803 #define PCI_DEVICE_ID_ASCEND310P 0xd500 #define PCI_DEVICE_ID_ASCEND310B 0xd105 #define PCI_DEVICE_ID_ASCEND310 0xd100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN 0x100 #define PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX 0x10f #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN 0x110 #define PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX 0x11f #define ASCEND910_XLOADER_SIZE 4 #define ASCEND910_XLOADER_OFFSET 0x80400 #define ASCEND910_A2_XLOADER_SIZE 4 #define ASCEND910_A2_XLOADER_OFFSET 0x18208430 #define ASCEND910_A3_XLOADER_SIZE 4 #define ASCEND910_A3_XLOADER_OFFSET 0x18208430 #define ASCEND910_A3_FEATURE_SIZE 4 #define ASCEND910_A3_FEATURE_OFFSET 0x182085f8 #define ASCEND310P_2P_BASE (128 * 1024 * 1024) #define ASCEND310P_1P_DEVNUM 1 #define ASCEND310P_2P_DEVNUM 2 #define ASCEND310P_XLOADER_SIZE 4 #define ASCEND310P_XLOADER_OFFSET 0x100430 #define ASCEND310B_XLOADER_SIZE 4 #define ASCEND310B_XLOADER_OFFSET 0x4430 #define ASCEND310_XLOADER_SIZE 4 #define ASCEND310_XLOADER_OFFSET 0x400 enum { VFIO_ASCEND_TYPE_ERR = 0, VFIO_ASCEND_TYPE_XLOADER = 1, VFIO_ASCEND_TYPE_FEATURE = 2, }; enum { QIURK_READ_SIZE_1_BYTE = 1, QIURK_READ_SIZE_2_BYTE = 2, QIURK_READ_SIZE_4_BYTE = 4, }; typedef struct VFIOAscendBarQuirk { struct VFIOPCIDevice *vdev; pcibus_t offset; unsigned int flags; /* for normal NC */ int type; /* XLOADER or FEATURE or etc. */ uint8_t bar; MemoryRegion *mem; } VFIOAscendBarQuirk; static uint64_t vfio_ascend_quirk_read(void *opaque, hwaddr addr, unsigned size) { uint64_t value, off_value; const unsigned byte_size = 8; unsigned start = addr * byte_size, length_size = size * byte_size; VFIOAscendBarQuirk *quirk = opaque; VFIOPCIDevice *vdev = quirk->vdev; qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); switch (quirk->type) { case VFIO_ASCEND_TYPE_XLOADER: value = vfio_region_read(&vdev->bars[quirk->bar].region, addr + quirk->offset, size); break; case VFIO_ASCEND_TYPE_FEATURE: switch (size) { case QIURK_READ_SIZE_1_BYTE: case QIURK_READ_SIZE_2_BYTE: case QIURK_READ_SIZE_4_BYTE: off_value = ((uint64_t)quirk->flags >> start) & ((1UL << length_size) - 1); return le64_to_cpu(off_value); default: qemu_log("Ascend quirk unsupported read size, %d bytes\n", size); return 0; } default: qemu_log("read RO region error type! addr=0x%" HWADDR_PRIx ", size=%d\n", addr + quirk->offset, size); return 0; } return value; } static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { VFIOAscendBarQuirk *quirk = opaque; qemu_log("modifying RO region is not allowed! addr=0x%" HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", addr + quirk->offset, data, size); } static unsigned int vfio_ascend_get_region_flags(VFIOPCIDevice *vdev, int nr) { int ret = 0; unsigned int flags; VFIODevice *vbasedev = &vdev->vbasedev; struct vfio_region_info *reg_info; ret = vfio_get_region_info(vbasedev, nr, ®_info); if (ret != 0) { qemu_log("Ascend failed to get region %d info\n", nr); return 0; } flags = reg_info->flags; g_free(reg_info); return flags; } static unsigned int vfio_ascend_get_all_regions_flags(VFIOPCIDevice *vdev) { int i = 0; unsigned int flag = 0, flags = 0; for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) { flag = vfio_ascend_get_region_flags(vdev, i); if (flag & VFIO_REGION_INFO_FLAG_NORMAL_NC) { flags |= (1 << i); } } return flags; } static void vfio_ascend_set_bar_quirk_array(VFIOAscendBarQuirk *bar_quirk, VFIOPCIDevice *vdev, int index, pcibus_t offset, unsigned int flags, int type, uint8_t bar) { bar_quirk[index].vdev = vdev; bar_quirk[index].offset = offset; bar_quirk[index].flags = flags; bar_quirk[index].type = type; bar_quirk[index].bar = bar; } static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { .read = vfio_ascend_quirk_read, .write = vfio_ascend_quirk_write, .endianness = DEVICE_LITTLE_ENDIAN, }; static void vfio_probe_ascend910_a2_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910_A2) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND910_A2_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910_a2-bar2-intercept-regs-quirk", ASCEND910_A2_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_a3_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; const int quirk_region_num = 2; /* XLOADER and FEATURE */ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND910_A3) { return; } quirk = vfio_quirk_alloc(quirk_region_num); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); vfio_ascend_set_bar_quirk_array(bar2_quirk, vdev, 0, ASCEND910_A3_XLOADER_OFFSET, 0, VFIO_ASCEND_TYPE_XLOADER, nr); /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend910_a3-bar2-intercept-regs-quirk", ASCEND910_A3_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); /* 910_A3 FEATURE */ vfio_ascend_set_bar_quirk_array(bar2_quirk, vdev, 1, ASCEND910_A3_FEATURE_OFFSET, vfio_ascend_get_all_regions_flags(vdev), VFIO_ASCEND_TYPE_FEATURE, nr); memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend910_a3-bar2-feature-regs-quirk", ASCEND910_A3_FEATURE_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar0_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || vdev->device_id != PCI_DEVICE_ID_ASCEND910) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); bar0_quirk[0].vdev = vdev; bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; bar0_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar0_quirk[0], "vfio-ascend910-bar0-intercept-regs-quirk", ASCEND910_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar0_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310p_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; int sub_device_id; int devnum = 0; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310P) { return; } sub_device_id = pci_get_word(vdev->pdev.config + PCI_SUBSYSTEM_ID); if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_1P_MAX) { devnum = ASCEND310P_1P_DEVNUM; } else if (sub_device_id >= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MIN && sub_device_id <= PCI_SUB_DEVICE_ID_ASCEND310P_2P_MAX) { devnum = ASCEND310P_2P_DEVNUM; } if (devnum != ASCEND310P_1P_DEVNUM && devnum != ASCEND310P_2P_DEVNUM) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = devnum; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310P_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310p-bar2-1p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); if (devnum == ASCEND310P_2P_DEVNUM) { bar2_quirk[1].vdev = vdev; bar2_quirk[1].offset = (ASCEND310P_2P_BASE + ASCEND310P_XLOADER_OFFSET); bar2_quirk[1].bar = nr; memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[1], "vfio-ascend310p-bar2-2p-intercept-regs-quirk", ASCEND310P_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[1].offset, &quirk->mem[1], 1); } QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310b_bar2_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar2_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 2 || vdev->device_id != PCI_DEVICE_ID_ASCEND310B) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar2_quirk = quirk->data = g_new0(typeof(*bar2_quirk), quirk->nr_mem); bar2_quirk[0].vdev = vdev; bar2_quirk[0].offset = ASCEND310B_XLOADER_OFFSET; bar2_quirk[0].bar = nr; /* intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar2_quirk[0], "vfio-ascend310b-bar2-intercept-regs-quirk", ASCEND310B_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar2_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) { VFIOQuirk *quirk; VFIOAscendBarQuirk *bar4_quirk; if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || vdev->device_id != PCI_DEVICE_ID_ASCEND310) { return; } quirk = g_malloc0(sizeof(*quirk)); quirk->nr_mem = 1; quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); bar4_quirk[0].vdev = vdev; bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; bar4_quirk[0].bar = nr; /* * intercept w/r to the xloader-updating register, * so the vm can't enable xloader-updating */ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_ascend_intercept_regs_quirk, &bar4_quirk[0], "vfio-ascend310-bar4-intercept-regs-quirk", ASCEND310_XLOADER_SIZE); memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, bar4_quirk[0].offset, &quirk->mem[0], 1); QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); } // ascend-patch end …
void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
{
vfio_probe_ati_bar4_quirk(vdev, nr);
vfio_probe_ati_bar2_quirk(vdev, nr);
vfio_probe_nvidia_bar5_quirk(vdev, nr);
vfio_probe_nvidia_bar0_quirk(vdev, nr);
// ascend-patch begin
vfio_probe_ascend910_a2_bar2_quirk(vdev, nr);
vfio_probe_ascend910_a3_bar2_quirk(vdev, nr);
vfio_probe_ascend910_bar0_quirk(vdev, nr);
vfio_probe_ascend310p_bar2_quirk(vdev, nr);
vfio_probe_ascend310b_bar2_quirk(vdev, nr);
vfio_probe_ascend310_bar4_quirk(vdev, nr);
// ascend-patch end
#ifdef CONFIG_VFIO_IGD
vfio_probe_igd_bar4_quirk(vdev, nr);
#endif
}…
vi ./linux-headers/linux/vfio.h
增加如下加粗字体标注的代码并保存。
struct vfio_region_info { __u32 argsz; __u32 flags; #define VFIO_REGION_INFO_FLAG_READ (1 << 0) /* Region supports read */ #define VFIO_REGION_INFO_FLAG_WRITE (1 << 1) /* Region supports write */ #define VFIO_REGION_INFO_FLAG_MMAP (1 << 2) /* Region supports mmap */ #define VFIO_REGION_INFO_FLAG_CAPS (1 << 3) /* Info supports caps */ #define VFIO_REGION_INFO_FLAG_NORMAL_NC (1 << 4) /* Region supports normal NC */ __u32 index; /* Region index */ __u32 cap_offset; /* Offset within info struct of first cap */ __u64 size; /* Region size (bytes) */ __u64 offset; /* Region offset from start of device fd */ };
修改extended_memmap数组定义,加粗字体由512修改至2048后保存。
static MemMapEntry extended_memmap[] = { /* Additional 64 MB redist region (can contain up to 512 redistributors) */ [VIRT_HIGH_GIC_REDIST2] = { 0x0, 64 * MiB }, [VIRT_HIGH_PCIE_ECAM] = { 0x0, 256 * MiB }, /* Second PCIe window */ [VIRT_HIGH_PCIE_MMIO] = { 0x0, 2048 * GiB },
./configure --enable-kvm --enable-numa
make -j 64
make install
修改虚拟机msix中断个数,如下加粗字体标注的内容。
#max_processes = 0 max_files = 8192