jailhouse的ko已经编译出来了,这里主要开始从代码分析jailhouse的加载过程
初始化主要如下几个步骤
对于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下
Cstatic 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);
主要文件如下:
对于cell目录的内容,如下
Ckobject_init_and_add(&cell->kobj, &cell_type, cells_dir, "%d",
cell->id);
可见cell目录下只存在id目录,在cell的enable和create的过程中,会主动创建,模块加载时并不会创建
对于id目录内的内容,如下
Cstatic 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");
主要文件如下:
对于statistics目录,主要内容如下
Cstatic 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);
主要文件如下:
对于cpu%u目录,主要内容如下:
Cstatic 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
};
对于文件如下:
这里需要留意的是如下:
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设备,就是往/dev下创建jailhouse文件。主要如下:
Cstatic 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
关于在jailhouse enable的ioctl中做的事情,后续再分析
注册一个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中做的事情,后续再分析
这里只是简单的在reboot的时候,给jailhouse发送disable的cmd
Cstatic 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的流程了