X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_multiboot.c;h=a9a20b38f036e6a3c096b5fec2c7e2658d08031c;hb=142b59ca44b3d00f0479910c986f6791216651e7;hp=0a7f60b3fca99d8c4b089bd099e99f90df5dd738;hpb=3650bf4aaa4f83afae52c8fee98fce6e3ee68deb;p=palacios.git diff --git a/palacios/src/palacios/vmm_multiboot.c b/palacios/src/palacios/vmm_multiboot.c index 0a7f60b..a9a20b3 100644 --- a/palacios/src/palacios/vmm_multiboot.c +++ b/palacios/src/palacios/vmm_multiboot.c @@ -144,93 +144,6 @@ int v3_deinit_multiboot_core(struct guest_info *core) #define INFO(fmt, args...) PrintDebug(VM_NONE,VCORE_NONE,"multiboot: " fmt,##args) - -/****************************************************************** - Data contained in the ELF file we will attempt to boot -******************************************************************/ - -#define ELF_MAGIC 0x464c457f -#define MB2_MAGIC 0xe85250d6 - - -/****************************************************************** - Data we will pass to the kernel via rbx -******************************************************************/ - -#define MB2_INFO_MAGIC 0x36d76289 - -typedef struct mb_info_header { - uint32_t totalsize; - uint32_t reserved; -} __attribute__((packed)) mb_info_header_t; - -// A tag of type 0, size 8 indicates last value -// -typedef struct mb_info_tag { - uint32_t type; - uint32_t size; -} __attribute__((packed)) mb_info_tag_t; - - -#define MB_INFO_MEM_TAG 4 -typedef struct mb_info_mem { - mb_info_tag_t tag; - uint32_t mem_lower; // 0..640K in KB - uint32_t mem_upper; // in KB to first hole - 1 MB -} __attribute__((packed)) mb_info_mem_t; - -#define MB_INFO_CMDLINE_TAG 1 -// note alignment of 8 bytes required for each... -typedef struct mb_info_cmdline { - mb_info_tag_t tag; - uint32_t size; // includes zero termination - uint8_t string[]; // zero terminated -} __attribute__((packed)) mb_info_cmdline_t; - - -#define MEM_RAM 1 -#define MEM_ACPI 3 -#define MEM_RESV 4 - -typedef struct mb_info_memmap_entry { - uint64_t base_addr; - uint64_t length; - uint32_t type; - uint32_t reserved; -} __attribute__((packed)) mb_info_memmap_entry_t; - -#define MB_INFO_MEMMAP_TAG 6 -// note alignment of 8 bytes required for each... -typedef struct mb_info_memmap { - mb_info_tag_t tag; - uint32_t entry_size; // multiple of 8 - uint32_t entry_version; // 0 - mb_info_memmap_entry_t entries[]; -} __attribute__((packed)) mb_info_memmap_t; - -#define MB_INFO_HRT_TAG 0xf00df00d -typedef struct mb_info_hrt { - mb_info_tag_t tag; - // apic ids are 0..num_apics-1 - // apic and ioapic addresses are the well known places - uint32_t total_num_apics; - uint32_t first_hrt_apic_id; - uint32_t have_hrt_ioapic; - uint32_t first_hrt_ioapic_entry; -} __attribute__((packed)) mb_info_hrt_t; - - -// We are not doing: -// -// - BIOS Boot Devie -// - Modules -// - ELF symbols -// - Boot Loader name -// - APM table -// - VBE info -// - Framebuffer info -// - static int is_elf(uint8_t *data, uint64_t size) { if (*((uint32_t*)data)==ELF_MAGIC) { @@ -381,7 +294,7 @@ static int parse_multiboot_kernel(uint8_t *data, uint64_t size, mb_data_t *mb) INFO(" size = 0x%x\n", mb_modalign->size); } break; -#if 0 +#if 1 case MB_TAG_MB64_HRT: { if (mb_mb64_hrt) { ERROR("Multiple mb64_hrt tags found!\n"); @@ -449,7 +362,7 @@ int v3_parse_multiboot_header(struct v3_cfg_file *file, mb_data_t *result) - only ROS memory visible - regular multiboot or bios boot assumed HRT core - - full HRT memory visible + - all memory visible - HRT64 multiboot assumed */ @@ -457,14 +370,14 @@ int v3_parse_multiboot_header(struct v3_cfg_file *file, mb_data_t *result) uint64_t v3_build_multiboot_table(struct guest_info *core, uint8_t *dest, uint64_t size) { struct v3_vm_info *vm = core->vm_info; - mb_info_header_t *header; + mb_info_header_t *header=0; #ifdef V3_CONFIG_HVM - mb_info_hrt_t *hrt; + mb_info_hrt_t *hrt=0; #endif - mb_info_mem_t *mem; - mb_info_memmap_t *memmap; - mb_info_tag_t *tag; - uint64_t num_mem, cur_mem; + mb_info_mem_t *mem=0; + mb_info_memmap_t *memmap=0; + mb_info_tag_t *tag=0; + uint64_t num_mem=0, cur_mem=0; uint64_t total_mem = vm->mem_size; @@ -538,12 +451,7 @@ uint64_t v3_build_multiboot_table(struct guest_info *core, uint8_t *dest, uint64 #ifdef V3_CONFIG_HVM if (core->vm_info->hvm_state.is_hvm && v3_is_hvm_hrt_core(core)) { - hrt->tag.type = MB_INFO_HRT_TAG; - hrt->tag.size = sizeof(mb_info_hrt_t); - hrt->total_num_apics = vm->num_cores; - hrt->first_hrt_apic_id = vm->hvm_state.first_hrt_core; - hrt->have_hrt_ioapic=0; - hrt->first_hrt_ioapic_entry=0; + v3_build_hrt_multiboot_tag(core,hrt); } #endif @@ -636,7 +544,9 @@ uint64_t v3_build_multiboot_table(struct guest_info *core, uint8_t *dest, uint64 int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, struct v3_cfg_file *file, void *base, uint64_t limit) { - uint32_t offset; + uint32_t offset=0; + uint32_t header_offset = (uint32_t) ((uint64_t)(mb->header) - (uint64_t)(file->data)); + uint32_t size; if (!mb->addr || !mb->entry) { PrintError(vm,VCORE_NONE, "multiboot: kernel is missing address or entry point\n"); @@ -650,21 +560,39 @@ int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, struct v3_cf return -1; } - offset = mb->addr->load_addr - mb->addr->header_addr; + offset = header_offset - (mb->addr->header_addr - mb->addr->load_addr); + size = mb->addr->load_end_addr - mb->addr->load_addr; + + if (size != file->size-offset) { + V3_Print(vm,VCORE_NONE,"multiboot: strange: size computed as %u, but file->size-offset = %llu\n",size,file->size-offset); + } - // Skip the ELF header - assume 1 page... weird.... // We are trying to do as little ELF loading here as humanly possible v3_write_gpa_memory(&vm->cores[0], (addr_t)(mb->addr->load_addr), - file->size-PAGE_SIZE-offset, - file->data+PAGE_SIZE+offset); + size, + file->data+offset); PrintDebug(vm,VCORE_NONE, "multiboot: wrote 0x%llx bytes starting at offset 0x%llx to %p\n", - (uint64_t) file->size-PAGE_SIZE-offset, - (uint64_t) PAGE_SIZE+offset, + (uint64_t) size, + (uint64_t) offset, (void*)(addr_t)(mb->addr->load_addr)); + size = mb->addr->bss_end_addr - mb->addr->load_end_addr + 1; + + // Now we need to zero the BSS + v3_set_gpa_memory(&vm->cores[0], + (addr_t)(mb->addr->load_end_addr), + size, + 0); + + PrintDebug(vm,VCORE_NONE, + "multiboot: zeroed 0x%llx bytes starting at %p\n", + (uint64_t) size, + (void*)(addr_t)(mb->addr->load_end_addr)); + + return 0; } @@ -732,12 +660,7 @@ static void write_gdt(struct v3_vm_info *vm, void *base, uint64_t limit) static void write_tss(struct v3_vm_info *vm, void *base, uint64_t limit) { - int i; - uint64_t tss_data=0x0; - - for (i=0;icores[0],(addr_t)(base+8*i),8,(uint8_t*) &tss_data); - } + v3_set_gpa_memory(&vm->cores[0],(addr_t)base,limit,0); PrintDebug(vm,VCORE_NONE,"multiboot: wrote TSS at %p\n",base); } @@ -944,22 +867,26 @@ int v3_setup_multiboot_core_for_boot(struct guest_info *core) core->segments.cs.selector = 0x8 ; // entry 1 of GDT (RPL=0) core->segments.cs.base = (addr_t) base; core->segments.cs.limit = limit; - core->segments.cs.type = 0xe; - core->segments.cs.system = 0; + core->segments.cs.type = 0xa; + core->segments.cs.system = 1; core->segments.cs.dpl = 0; core->segments.cs.present = 1; core->segments.cs.long_mode = 0; + core->segments.cs.db = 1; // 32 bit operand and address size + core->segments.cs.granularity = 1; // pages // DS, SS, etc are identical core->segments.ds.selector = 0x10; // entry 2 of GDT (RPL=0) core->segments.ds.base = (addr_t) base; core->segments.ds.limit = limit; - core->segments.ds.type = 0x6; - core->segments.ds.system = 0; + core->segments.ds.type = 0x2; + core->segments.ds.system = 1; core->segments.ds.dpl = 0; core->segments.ds.present = 1; core->segments.ds.long_mode = 0; - + core->segments.ds.db = 1; // 32 bit operand and address size + core->segments.ds.granularity = 1; // pages + memcpy(&core->segments.ss,&core->segments.ds,sizeof(core->segments.ds)); memcpy(&core->segments.es,&core->segments.ds,sizeof(core->segments.ds)); memcpy(&core->segments.fs,&core->segments.ds,sizeof(core->segments.ds)); @@ -984,3 +911,54 @@ int v3_setup_multiboot_core_for_boot(struct guest_info *core) return 0; } + + +int v3_handle_multiboot_reset(struct guest_info *core) +{ + int rc; + + if (core->core_run_state!=CORE_RESETTING) { + return 0; + } + + if (!core->vm_info->mb_state.is_multiboot) { + return 0; + } + + // wait for everyone + v3_counting_barrier(&core->vm_info->reset_barrier); + + if (core->vcpu_id==0) { + // I am leader (this is true if I am a ROS core or this is a non-HVM) + core->vm_info->run_state = VM_RESETTING; + } + + rc=0; + + if (core->vcpu_id==0) { + // we will recopy the image + rc |= v3_setup_multiboot_vm_for_boot(core->vm_info); + } + + rc |= v3_setup_multiboot_core_for_boot(core); + + if (core->vcpu_id==0) { + core->core_run_state = CORE_RUNNING; + core->vm_info->run_state = VM_RUNNING; + } else { + // for APs, we need to bring them back to the init state + core->cpu_mode = REAL; + core->mem_mode = PHYSICAL_MEM; + core->core_run_state = CORE_STOPPED; + } + + // sync on the way out + v3_counting_barrier(&core->vm_info->reset_barrier); + + if (rc<0) { + return rc; + } else { + return 1; // reboot + } +} +