前回でとりあえずarch_init_early()は大体読んだので次はinit_early()に戻ってcell_init()から。
cell_init()はhypervisor/control.cにある。
int cell_init(struct cell *cell, struct jailhouse_cell_desc *config, bool copy_cpu_set) { unsigned long *config_cpu_set = (unsigned long *)(((void *)config) + sizeof(struct jailhouse_cell_desc)); unsigned long cpu_set_size = config->cpu_set_size; struct jailhouse_memory *config_ram = (struct jailhouse_memory *)(((void *)config_cpu_set) + cpu_set_size); struct cpu_set *cpu_set;
ここまでで変数定義+データの初期化でconfigで示されるアドレス範囲から各種データが設定される。
cell名の設定とcellのidの設定。
memcpy(cell->name, config->name, sizeof(cell->name));
cell->id = get_free_cell_id();
cellに対してidをget_free_cell_id()で設定。このget_free_cell_id()はそんなにたいしたことはしていないので省略。関数はhypervisor/control.cに。
ここはcpu_setが何者か分からないとだめですね(´ε`;)ウーン…
if (cpu_set_size > PAGE_SIZE) return -EINVAL; else if (cpu_set_size > sizeof(cell->small_cpu_set.bitmap)) { cpu_set = page_alloc(&mem_pool, 1); if (!cpu_set) return -ENOMEM; cpu_set->max_cpu_id = ((PAGE_SIZE - sizeof(unsigned long)) * 8) - 1; } else { cpu_set = &cell->small_cpu_set; cpu_set->max_cpu_id = (sizeof(cell->small_cpu_set.bitmap) * 8) - 1; } cell->cpu_set = cpu_set;
まず最初にcell->small_cpu_set.bitmapに関する部分を見ます。cell構造体はhypervisor/arch/x86/include/asm/cell.hにて定義されています。そしてif文ではcell構造体のメンバ変数のsmall_cpu_set構造体のメンバ変数であるbitmapを見てますね。
struct cell { struct { /* should be first as it requires page alignment */ u8 __attribute__((aligned(PAGE_SIZE))) io_bitmap[2*PAGE_SIZE]; pgd_t *ept; } vmx; struct { pgd_t *page_table; } vtd; char name[JAILHOUSE_CELL_NAME_MAXLEN+1]; unsigned int id; struct cpu_set *cpu_set; struct cpu_set small_cpu_set; unsigned long page_offset; struct cell *next; };
という訳でhypervisor/arch/x86/include/asm/types.hを見てみると
struct cpu_set { unsigned long max_cpu_id; /* Note: The bitmap is supposed to be extended by embedding this * struct into a larger buffer. */ unsigned long bitmap[1]; };
これで何となく分かった気が。このcpu_set構造体で使用しているbitmapはcpu0~cpuNまでを表しているんでしょう、きっと。そしてcell_init()のif文に戻って
else if (cpu_set_size > sizeof(cell->small_cpu_set.bitmap)) {
これはホストのcpu数がsizeof(cell->small_cpu_set.bitmap)個以上(x86_64ならsizeof(unsigned long)は64のはず)で64以上有る場合はbitmapの大きさが足りないので1ページをプールから取得してcpu_set構造体として扱う。64個もcpuが無ければcell->small_cpu_setを使うってことですね。
cell_init()の引数にあるcopy_cpu_setがtrueだったら実施。
if (copy_cpu_set)
memcpy(cell->cpu_set->bitmap, config_cpu_set, cpu_set_size);
cellが使用するメモリの開始アドレス設定。
cell->page_offset = config_ram->phys_start; return 0; }
とりあえずこれにてinit_early()は一通り終了。
これでhypervisor/setup.cのentry()に戻り、cpu_init()に入っていきます。
if (master_cpu_id == -1) { master = true; init_early(cpu_data->cpu_id); } if (!error) { cpu_init(cpu_data); if (master && !error) init_late(); }