编辑
2024-01-25
工作知识
0
请注意,本文编写于 498 天前,最后修改于 451 天前,其中某些信息可能已经过时。

目录

Jailhouse启动分析
init
sysfs
misc
pci
notifier
总结

Jailhouse启动分析

jailhouse的ko已经编译出来了,这里主要开始从代码分析jailhouse的加载过程

init

初始化主要如下几个步骤

  1. jailhouse_sysfs_init
  2. misc_register
  3. jailhouse_pci_register
  4. register_reboot_notifier

sysfs

对于sysfs的创建,如下解释:

/sys/devices/jailhouse |- console - hypervisor console (see [1]) |- enabled - 1 if Jailhouse is enabled, 0 otherwise |- mem_pool_size - number of pages in hypervisor memory pool |- mem_pool_used - used pages of hypervisor memory pool |- remap_pool_size - number of pages in hypervisor remapping pool |- remap_pool_used - used pages of hypervisor remapping pool `- cells |- <id> - unique numerical ID | |- name - cell name | |- state - "running", "running/locked", "shut down", or | | "failed" | |- cpus_assigned - bitmask of assigned logical CPUs | |- cpus_assigned_list - human readable list of assigned logical CPUs | |- cpus_failed - bitmask of logical CPUs that caused a failure | |- cpus_failed_list - human readable list of logical CPUs that | | caused a failure | `- statistics | |- cpu<n> | | |- vmexits_total - Total number of VM exits on CPU <n> | | `- vmexits_<reason> - VM exits due to <reason> on CPU <n> | |- vmexits_total - Total number of VM exits on all cell CPUs | `- vmexits_<reason> - VM exits due to <reason> on all cell CPUs `- ...

在目录/sys/devices/jailhouse下

C
static struct attribute *jailhouse_sysfs_entries[] = { &dev_attr_console.attr, &dev_attr_enabled.attr, &dev_attr_mem_pool_size.attr, &dev_attr_mem_pool_used.attr, &dev_attr_remap_pool_size.attr, &dev_attr_remap_pool_used.attr, NULL }; kobject_create_and_add("cells", &dev->kobj);

主要文件如下:

  1. console 虚拟机状态信息
  2. enabled jailhouse使能信息
  3. mem_pool_size 虚拟机内存池大小
  4. mem_pool_used 虚拟机内存池使用量
  5. remap_pool_size 虚拟机内存映射大小
  6. remap_pool_used 虚拟机内存映射使用量
  7. cell目录

对于cell目录的内容,如下

C
kobject_init_and_add(&cell->kobj, &cell_type, cells_dir, "%d", cell->id);

可见cell目录下只存在id目录,在cell的enable和create的过程中,会主动创建,模块加载时并不会创建

对于id目录内的内容,如下

C
static struct attribute *cell_attrs[] = { &cell_name_attr.attr, &cell_state_attr.attr, &cell_cpus_assigned_attr.attr, &cell_cpus_assigned_list_attr.attr, &cell_cpus_failed_attr.attr, &cell_cpus_failed_list_attr.attr, NULL, }; kobject_init_and_add(&cell->stats_kobj, &cell_stats_type, &cell->kobj, "%s", "statistics");

主要文件如下:

  1. name cell的名字
  2. state cell的状态
  3. cpus_assigned cpumask信息,以%*pb显示,例如ffff
  4. cpus_assigned_list cpumask信息,以%*pbl显示,例如0-7
  5. cpus_failed 失败的cpumask信息,以%*pb显示
  6. cpus_failed_list 失败的cpumask信息,以%*pbl显示
  7. statistics目录

对于statistics目录,主要内容如下

C
static struct attribute *cell_stats_attrs[] = { &vmexits_total_cell_attr.kattr.attr, &vmexits_mmio_cell_attr.kattr.attr, &vmexits_management_cell_attr.kattr.attr, &vmexits_hypercall_cell_attr.kattr.attr, &vmexits_maintenance_cell_attr.kattr.attr, &vmexits_virt_irq_cell_attr.kattr.attr, &vmexits_virt_sgi_cell_attr.kattr.attr, &vmexits_psci_cell_attr.kattr.attr, &vmexits_smccc_cell_attr.kattr.attr, NULL }; kobject_init_and_add(&cell_cpu->kobj, &cell_cpu_type, &cell->stats_kobj, "cpu%u", cpu);

主要文件如下:

  1. vmexits_total 虚拟机退出个数
  2. vmexits_mmio (Memory mapping I/O)
  3. vmexits_management (Memory management)
  4. vmexits_hypercall (Hypercall)
  5. vmexits_maintenance (Cache Maintenance)
  6. vmexits_virt_irq (IRQ)
  7. vmexits_virt_sgi (Software Generated Interrupt)
  8. vmexits_psci (Power State Coordination Interface)
  9. vmexits_smccc (SMC Calling Convention SMC调用约定)
  10. cpu%u cpu目录

对于cpu%u目录,主要内容如下:

C
static struct attribute *cpu_stats_attrs[] = { &vmexits_total_cpu_attr.kattr.attr, &vmexits_mmio_cpu_attr.kattr.attr, &vmexits_management_cpu_attr.kattr.attr, &vmexits_hypercall_cpu_attr.kattr.attr, &vmexits_maintenance_cpu_attr.kattr.attr, &vmexits_virt_irq_cpu_attr.kattr.attr, &vmexits_virt_sgi_cpu_attr.kattr.attr, &vmexits_psci_cpu_attr.kattr.attr, &vmexits_smccc_cpu_attr.kattr.attr, NULL };

对于文件如下:

  1. vmexits_total
  2. vmexits_mmio
  3. vmexits_management
  4. vmexits_hypercall
  5. vmexits_maintenance
  6. vmexits_virt_irq
  7. vmexits_virt_sgi
  8. vmexits_psci
  9. vmexits_smccc

这里需要留意的是如下:

C
asm volatile( JAILHOUSE_CALL_INS : "+r" (num_result), "+r" (__arg1), "+r" (__arg2) : : "memory", JAILHOUSE_CALL_CLOBBERED); #define JAILHOUSE_CALL_INS "hvc #0x4a48" #define JAILHOUSE_CALL_NUM_RESULT "x0" #define JAILHOUSE_CALL_ARG1 "x1" #define JAILHOUSE_CALL_ARG2 "x2" #define JAILHOUSE_CALL_CLOBBERED "x3"

misc

对于misc设备,就是往/dev下创建jailhouse文件。主要如下:

C
static const struct file_operations jailhouse_fops = { .owner = THIS_MODULE, .unlocked_ioctl = jailhouse_ioctl, .compat_ioctl = jailhouse_ioctl, .llseek = noop_llseek, .open = jailhouse_console_open, .release = jailhouse_console_release, .read = jailhouse_console_read, }; static struct miscdevice jailhouse_misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "jailhouse", .fops = &jailhouse_fops, };

关于ioctl,主要提供如下

JAILHOUSE_ENABLE JAILHOUSE_DISABLE JAILHOUSE_CELL_CREATE JAILHOUSE_CELL_LOAD JAILHOUSE_CELL_START JAILHOUSE_CELL_DESTROY

这些ioctl提供了jailhouse的基本使能,禁用,创建,加载,开始,销毁的能力。
对于open release read三个file operations

  1. open 提供console_state结构体
  2. release 销毁console_state结构体
  3. read 向dump 虚拟机状态console信息

关于在jailhouse enable的ioctl中做的事情,后续再分析

pci

注册一个pci驱动,在probe中遍历并打印宣传在no root cell的pci设备

C
list_for_each_entry(claimed_dev, &claimed_devs, list) { if (claimed_dev->dev == dev) { dev_info(&dev->dev, "claimed for use in non-root cell\n"); ret = 0; break; } }

关于在jailhouse enable的ioctl中做的事情,后续再分析

notifier

这里只是简单的在reboot的时候,给jailhouse发送disable的cmd

C
static int jailhouse_shutdown_notify(struct notifier_block *unused1, unsigned long unused2, void *unused3) { int err; err = jailhouse_cmd_disable(); if (err && err != -EINVAL) pr_emerg("jailhouse: ordered shutdown failed!\n"); return NOTIFY_DONE; }

总结

至此,jailhouse驱动的加载过程完成了,接下来就是给jailhouse发送enable的ioctl的流程了