Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 Makefile                  |   2 +
 arch/x64/arch-setup.cc    | 124 +-------------------------------------
 arch/x64/arch-setup.hh    |  39 ++++++++++++
 arch/x64/boot.S           |  55 +----------------
 arch/x64/loader.ld        |   2 +-
 arch/x64/setup.S          |  38 ++++++++++++
 arch/x64/vmlinux-boot64.S |  26 ++++++++
 arch/x64/vmlinux.cc       |  93 ++++++++++++++++++++++++++++
 8 files changed, 202 insertions(+), 177 deletions(-)
 create mode 100644 arch/x64/setup.S
 create mode 100644 arch/x64/vmlinux-boot64.S
 create mode 100644 arch/x64/vmlinux.cc

diff --git a/Makefile b/Makefile
index ff9f2ed3..377e93e9 100644
--- a/Makefile
+++ b/Makefile
@@ -893,6 +893,8 @@ objects += arch/x64/ioapic.o
 objects += arch/x64/apic.o
 objects += arch/x64/apic-clock.o
 objects += arch/x64/entry-xen.o
+objects += arch/x64/vmlinux.o
+objects += arch/x64/vmlinux-boot64.o
 objects += core/sampler.o
 objects += $(acpi)
 endif # x64
diff --git a/arch/x64/arch-setup.cc b/arch/x64/arch-setup.cc
index 6db2f77c..6d0c2eaf 100644
--- a/arch/x64/arch-setup.cc
+++ b/arch/x64/arch-setup.cc
@@ -22,45 +22,6 @@
 #include <osv/commands.hh>
 #include "dmi.hh"
 
-struct multiboot_info_type {
-    u32 flags;
-    u32 mem_lower;
-    u32 mem_upper;
-    u32 boot_device;
-    u32 cmdline;
-    u32 mods_count;
-    u32 mods_addr;
-    u32 syms[4];
-    u32 mmap_length;
-    u32 mmap_addr;
-    u32 drives_length;
-    u32 drives_addr;
-    u32 config_table;
-    u32 boot_loader_name;
-    u32 apm_table;
-    u32 vbe_control_info;
-    u32 vbe_mode_info;
-    u16 vbe_mode;
-    u16 vbe_interface_seg;
-    u16 vbe_interface_off;
-    u16 vbe_interface_len;
-} __attribute__((packed));
-
-struct osv_multiboot_info_type {
-    struct multiboot_info_type mb;
-    u32 tsc_init, tsc_init_hi;
-    u32 tsc_disk_done, tsc_disk_done_hi;
-    u32 tsc_uncompress_done, tsc_uncompress_done_hi;
-    u8 disk_err;
-} __attribute__((packed));
-
-struct e820ent {
-    u32 ent_size;
-    u64 addr;
-    u64 size;
-    u32 type;
-} __attribute__((packed));
-
 osv_multiboot_info_type* osv_multiboot_info;
 
 void parse_cmdline(multiboot_info_type& mb)
@@ -117,96 +78,13 @@ extern size_t elf_size;
 extern void* elf_start;
 extern boot_time_chart boot_time;
 
-// Because entry64 replaces start32 as a new entry of loader.elf we need a way
+// Because vmlinux_entry64 replaces start32 as a new entry of loader.elf we 
need a way
 // to place address of start32 so that boot16 know where to jump to. We achieve
 // it by placing address of start32 at the known offset at memory
 // as defined by section .start32_address in loader.ld
 extern "C" void start32();
 void * __attribute__((section (".start32_address"))) start32_address = 
reinterpret_cast<void*>(&start32);
 
-#define OSV_MULTI_BOOT_INFO_ADDR      0x1000
-#define OSV_E820_TABLE_ADDR           0x2000
-
-//
-// Instead of defining full boot_params and setup_header structs as in
-// Linux source code, we define only handful of offsets pointing the fields
-// we need to read from there. For details please this chunk of Linux code -
-// 
https://github.com/torvalds/linux/blob/b6839ef26e549de68c10359d45163b0cfb031183/arch/x86/include/uapi/asm/bootparam.h#L151-L198
-#define LINUX_KERNEL_BOOT_FLAG_MAGIC  0xaa55
-#define LINUX_KERNEL_HDR_MAGIC        0x53726448 // "HdrS"
-
-#define SETUP_HEADER_OFFSET  0x1f1   // look at bootparam.h in linux
-#define SETUP_HEADER_FIELD_VAL(boot_params, offset, field_type) \
-    (*static_cast<field_type*>(boot_params + SETUP_HEADER_OFFSET + offset))
-
-#define BOOT_FLAG_OFFSET     sizeof(u8) + 4 * sizeof(u16) + sizeof(u32)
-#define HDR_MAGIC_OFFSET     sizeof(u8) + 6 * sizeof(u16) + sizeof(u32)
-
-#define E820_ENTRIES_OFFSET  0x1e8   // look at bootparam.h in linux
-#define E820_TABLE_OFFSET    0x2d0   // look at bootparam.h in linux
-
-#define CMD_LINE_PTR_OFFSET  sizeof(u8) * 5 + sizeof(u16) * 11 + sizeof(u32) * 
7
-
-struct linux_e820ent {
-    u64 addr;
-    u64 size;
-    u32 type;
-} __attribute__((packed));
-
-// When OSv kernel gets booted directly as 64-bit ELF (loader.elf) as it is
-// the case on firecracker we need a way to extract all necessary information
-// about available memory and command line. This information is provided
-// the struct boot_params (see details above) placed in memory at the address
-// specified in the RSI register.
-// The following extract_linux_boot_params() function is called from
-// entry64 in boot.S and verifies OSV was indeed boot as Linux and
-// copies memory and cmdline information into OSv multiboot struct.
-// Please see https://www.kernel.org/doc/Documentation/x86/boot.txt for details
-// of Linux boot protocol. Bear in mind that OSv implements very narrow 
specific
-// subset of the protocol as assumed by firecracker.
-extern "C" void extract_linux_boot_params(void *boot_params)
-{   //
-    // Verify we are being booted as Linux 64-bit ELF kernel
-    assert( SETUP_HEADER_FIELD_VAL(boot_params, BOOT_FLAG_OFFSET, u16) == 
LINUX_KERNEL_BOOT_FLAG_MAGIC);
-    assert( SETUP_HEADER_FIELD_VAL(boot_params, HDR_MAGIC_OFFSET, u32) == 
LINUX_KERNEL_HDR_MAGIC);
-
-    // Set location of multiboot info struct at arbitrary place in lower memory
-    // to copy to (happens to be the same as in boot16.S)
-    osv_multiboot_info_type* mb_info = 
reinterpret_cast<osv_multiboot_info_type*>(OSV_MULTI_BOOT_INFO_ADDR);
-
-    // Copy command line pointer from boot params
-    mb_info->mb.cmdline = SETUP_HEADER_FIELD_VAL(boot_params, 
CMD_LINE_PTR_OFFSET, u32);
-
-    // Copy e820 information from boot params
-    mb_info->mb.mmap_length = 0;
-    mb_info->mb.mmap_addr = OSV_E820_TABLE_ADDR;
-
-    struct linux_e820ent *source_e820_table = static_cast<struct linux_e820ent 
*>(boot_params + E820_TABLE_OFFSET);
-    struct e820ent *dest_e820_table = reinterpret_cast<struct e820ent 
*>(mb_info->mb.mmap_addr);
-
-    u8 en820_entries = *static_cast<u8*>(boot_params + E820_ENTRIES_OFFSET);
-    for (int e820_index = 0; e820_index < en820_entries; e820_index++) {
-        dest_e820_table[e820_index].ent_size = 20;
-        dest_e820_table[e820_index].type = source_e820_table[e820_index].type;
-        dest_e820_table[e820_index].addr = source_e820_table[e820_index].addr;
-        dest_e820_table[e820_index].size = source_e820_table[e820_index].size;
-        mb_info->mb.mmap_length += sizeof(e820ent);
-    }
-
-    auto now = processor::ticks();
-    u32 now_high = (u32)(now >> 32);
-    u32 now_low = (u32)now;
-
-    mb_info->tsc_init_hi = now_high;
-    mb_info->tsc_init = now_low;
-
-    mb_info->tsc_disk_done_hi = now_high;
-    mb_info->tsc_disk_done = now_low;
-
-    mb_info->tsc_uncompress_done_hi = now_high;
-    mb_info->tsc_uncompress_done = now_low;
-}
-
 void arch_setup_free_memory()
 {
     static ulong edata;
diff --git a/arch/x64/arch-setup.hh b/arch/x64/arch-setup.hh
index ff950cc1..32ba378a 100644
--- a/arch/x64/arch-setup.hh
+++ b/arch/x64/arch-setup.hh
@@ -13,6 +13,45 @@
 
 #include <osv/elf.hh>
 
+struct multiboot_info_type {
+    u32 flags;
+    u32 mem_lower;
+    u32 mem_upper;
+    u32 boot_device;
+    u32 cmdline;
+    u32 mods_count;
+    u32 mods_addr;
+    u32 syms[4];
+    u32 mmap_length;
+    u32 mmap_addr;
+    u32 drives_length;
+    u32 drives_addr;
+    u32 config_table;
+    u32 boot_loader_name;
+    u32 apm_table;
+    u32 vbe_control_info;
+    u32 vbe_mode_info;
+    u16 vbe_mode;
+    u16 vbe_interface_seg;
+    u16 vbe_interface_off;
+    u16 vbe_interface_len;
+} __attribute__((packed));
+
+struct osv_multiboot_info_type {
+    struct multiboot_info_type mb;
+    u32 tsc_init, tsc_init_hi;
+    u32 tsc_disk_done, tsc_disk_done_hi;
+    u32 tsc_uncompress_done, tsc_uncompress_done_hi;
+    u8 disk_err;
+} __attribute__((packed));
+
+struct e820ent {
+    u32 ent_size;
+    u64 addr;
+    u64 size;
+    u32 type;
+} __attribute__((packed));
+
 void arch_init_early_console();
 void arch_init_premain();
 void arch_setup_tls(void *tls, const elf::tls_data& info);
diff --git a/arch/x64/boot.S b/arch/x64/boot.S
index 9277dffd..f5587fc4 100644
--- a/arch/x64/boot.S
+++ b/arch/x64/boot.S
@@ -4,46 +4,14 @@
 # BSD license as described in the LICENSE file in the top-level directory.
 
 #include "processor-flags.h"
-
-#define BOOT_CR0 ( X86_CR0_PE \
-                 | X86_CR0_WP \
-                 | X86_CR0_PG )
-
-#define BOOT_CR4 ( X86_CR4_DE         \
-                 | X86_CR4_PSE        \
-                 | X86_CR4_PAE        \
-                 | X86_CR4_PGE        \
-                 | X86_CR4_PCE        \
-                 | X86_CR4_OSFXSR     \
-                 | X86_CR4_OSXMMEXCPT )
-
-.macro setup_64bit_long_mode
-    // Enable PAE (Physical Address Extension) - ability to address 64GB
-    // TODO: Add more comments to processor-flags.h what each flag does
-    mov $BOOT_CR4, %eax
-    mov %eax, %cr4
-
-    // Set root of a page table in cr3
-    lea ident_pt_l4, %eax
-    mov %eax, %cr3
-
-    // Set long mode?
-    mov $0xc0000080, %ecx // EFER MSR number
-    mov $0x00000900, %eax // Set LME = 1
-    xor %edx, %edx
-    wrmsr // Write contents of EDX:EAX (0:to Model Specific Register specified 
by ECX register
-
-    // Activate paging and ...?
-    // TODO: Add more comments to processor-flags.h what each flag does
-    mov $BOOT_CR0, %eax
-    mov %eax, %cr0
-.endm
+#include "setup.S"
 
 .text
 .code32
 
 .data
 .align 4096
+.global ident_pt_l4
 ident_pt_l4:
     .quad ident_pt_l3 + 0x67
     .rept 511
@@ -194,22 +162,3 @@ smpboot64:
     jnz 1b
     lea 4096(%rax), %rsp
     call smp_main
-
-.text
-.code64
-.global entry64
-entry64:
-# The address of boot_params structed is passed in RSI
-# register so pass it to extract_linux_boot_params fuction
-# which will extract cmdline and memory information and verify
-# that loader.elf was indeed called as Linux 64-bit vmlinux ELF
-    mov %rsi, %rdi
-    call extract_linux_boot_params
-
-# Even though we are in 64-bit long mode we need to reset
-# page tables and other CPU settings the way OSv expects it
-    setup_64bit_long_mode
-
-    mov $OSV_KERNEL_BASE, %rbp
-    mov $0x1000, %rbx
-    jmp start64
diff --git a/arch/x64/loader.ld b/arch/x64/loader.ld
index 6bb4b861..caae1f68 100644
--- a/arch/x64/loader.ld
+++ b/arch/x64/loader.ld
@@ -114,4 +114,4 @@ PHDRS {
        eh_frame PT_GNU_EH_FRAME;
        note PT_NOTE;
 }
-ENTRY(entry64);
+ENTRY(vmlinux_entry64);
diff --git a/arch/x64/setup.S b/arch/x64/setup.S
new file mode 100644
index 00000000..dcc6bfe2
--- /dev/null
+++ b/arch/x64/setup.S
@@ -0,0 +1,38 @@
+# Copyright (C) 2019 Waldemar Kozaczuk
+#
+# This work is open source software, licensed under the terms of the
+# BSD license as described in the LICENSE file in the top-level directory.
+
+#define BOOT_CR0 ( X86_CR0_PE \
+                 | X86_CR0_WP \
+                 | X86_CR0_PG )
+
+#define BOOT_CR4 ( X86_CR4_DE         \
+                 | X86_CR4_PSE        \
+                 | X86_CR4_PAE        \
+                 | X86_CR4_PGE        \
+                 | X86_CR4_PCE        \
+                 | X86_CR4_OSFXSR     \
+                 | X86_CR4_OSXMMEXCPT )
+
+.macro setup_64bit_long_mode
+    // Enable PAE (Physical Address Extension) - ability to address 64GB
+    // TODO: Add more comments to processor-flags.h what each flag does
+    mov $BOOT_CR4, %eax
+    mov %eax, %cr4
+
+    // Set root of a page table in cr3
+    lea ident_pt_l4, %eax
+    mov %eax, %cr3
+
+    // Set long mode
+    mov $0xc0000080, %ecx // EFER MSR number
+    mov $0x00000900, %eax // Set LME = 1
+    xor %edx, %edx
+    wrmsr // Write contents of EDX:EAX (0:to Model Specific Register specified 
by ECX register
+
+    // Activate paging and ...?
+    // TODO: Add more comments to processor-flags.h what each flag does
+    mov $BOOT_CR0, %eax
+    mov %eax, %cr0
+.endm
diff --git a/arch/x64/vmlinux-boot64.S b/arch/x64/vmlinux-boot64.S
new file mode 100644
index 00000000..8db70a4e
--- /dev/null
+++ b/arch/x64/vmlinux-boot64.S
@@ -0,0 +1,26 @@
+# Copyright (C) 2019 Waldemar Kozaczuk
+#
+# This work is open source software, licensed under the terms of the
+# BSD license as described in the LICENSE file in the top-level directory.
+
+#include "processor-flags.h"
+#include "setup.S"
+
+.text
+.code64
+.global vmlinux_entry64
+vmlinux_entry64:
+# The address of boot_params structed is passed in RSI
+# register so pass it to extract_linux_boot_params fuction
+# which will extract cmdline and memory information and verify
+# that loader.elf was indeed called as Linux 64-bit vmlinux ELF
+    mov %rsi, %rdi
+    call extract_linux_boot_params
+
+# Even though we are in 64-bit long mode we need to reset
+# page tables and other CPU settings the way OSv expects it
+    setup_64bit_long_mode
+
+    mov $OSV_KERNEL_BASE, %rbp
+    mov $0x1000, %rbx
+    jmp start64
diff --git a/arch/x64/vmlinux.cc b/arch/x64/vmlinux.cc
new file mode 100644
index 00000000..6a551a98
--- /dev/null
+++ b/arch/x64/vmlinux.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 Waldemar Kozaczuk
+ *
+ * This work is open source software, licensed under the terms of the
+ * BSD license as described in the LICENSE file in the top-level directory.
+ */
+
+#include <osv/types.h>
+#include "arch-setup.hh"
+#include "processor.hh"
+
+#define OSV_MULTI_BOOT_INFO_ADDR      0x1000
+#define OSV_E820_TABLE_ADDR           0x2000
+
+//
+// Instead of defining full boot_params and setup_header structs as in
+// Linux source code, we define only handful of offsets pointing the fields
+// we need to read from there. For details please this chunk of Linux code -
+// 
https://github.com/torvalds/linux/blob/b6839ef26e549de68c10359d45163b0cfb031183/arch/x86/include/uapi/asm/bootparam.h#L151-L198
+#define LINUX_KERNEL_BOOT_FLAG_MAGIC  0xaa55
+#define LINUX_KERNEL_HDR_MAGIC        0x53726448 // "HdrS"
+
+#define SETUP_HEADER_OFFSET  0x1f1   // look at bootparam.h in linux
+#define SETUP_HEADER_FIELD_VAL(boot_params, offset, field_type) \
+    (*static_cast<field_type*>(boot_params + SETUP_HEADER_OFFSET + offset))
+
+#define BOOT_FLAG_OFFSET     sizeof(u8) + 4 * sizeof(u16) + sizeof(u32)
+#define HDR_MAGIC_OFFSET     sizeof(u8) + 6 * sizeof(u16) + sizeof(u32)
+
+#define E820_ENTRIES_OFFSET  0x1e8   // look at bootparam.h in linux
+#define E820_TABLE_OFFSET    0x2d0   // look at bootparam.h in linux
+
+#define CMD_LINE_PTR_OFFSET  sizeof(u8) * 5 + sizeof(u16) * 11 + sizeof(u32) * 
7
+
+struct linux_e820ent {
+    u64 addr;
+    u64 size;
+    u32 type;
+} __attribute__((packed));
+
+// When OSv kernel gets booted directly as 64-bit ELF (loader.elf) as it is
+// the case on firecracker we need a way to extract all necessary information
+// about available memory and command line. This information is provided
+// the struct boot_params (see details above) placed in memory at the address
+// specified in the RSI register.
+// The following extract_linux_boot_params() function is called from
+// entry64 in boot.S and verifies OSV was indeed boot as Linux and
+// copies memory and cmdline information into OSv multiboot struct.
+// Please see https://www.kernel.org/doc/Documentation/x86/boot.txt for details
+// of Linux boot protocol. Bear in mind that OSv implements very narrow 
specific
+// subset of the protocol as assumed by firecracker.
+extern "C" void extract_linux_boot_params(void *boot_params)
+{   //
+    // Verify we are being booted as Linux 64-bit ELF kernel
+    assert( SETUP_HEADER_FIELD_VAL(boot_params, BOOT_FLAG_OFFSET, u16) == 
LINUX_KERNEL_BOOT_FLAG_MAGIC);
+    assert( SETUP_HEADER_FIELD_VAL(boot_params, HDR_MAGIC_OFFSET, u32) == 
LINUX_KERNEL_HDR_MAGIC);
+
+    // Set location of multiboot info struct at arbitrary place in lower memory
+    // to copy to (happens to be the same as in boot16.S)
+    osv_multiboot_info_type* mb_info = 
reinterpret_cast<osv_multiboot_info_type*>(OSV_MULTI_BOOT_INFO_ADDR);
+
+    // Copy command line pointer from boot params
+    mb_info->mb.cmdline = SETUP_HEADER_FIELD_VAL(boot_params, 
CMD_LINE_PTR_OFFSET, u32);
+
+    // Copy e820 information from boot params
+    mb_info->mb.mmap_length = 0;
+    mb_info->mb.mmap_addr = OSV_E820_TABLE_ADDR;
+
+    struct linux_e820ent *source_e820_table = static_cast<struct linux_e820ent 
*>(boot_params + E820_TABLE_OFFSET);
+    struct e820ent *dest_e820_table = reinterpret_cast<struct e820ent 
*>(mb_info->mb.mmap_addr);
+
+    u8 en820_entries = *static_cast<u8*>(boot_params + E820_ENTRIES_OFFSET);
+    for (int e820_index = 0; e820_index < en820_entries; e820_index++) {
+        dest_e820_table[e820_index].ent_size = 20;
+        dest_e820_table[e820_index].type = source_e820_table[e820_index].type;
+        dest_e820_table[e820_index].addr = source_e820_table[e820_index].addr;
+        dest_e820_table[e820_index].size = source_e820_table[e820_index].size;
+        mb_info->mb.mmap_length += sizeof(e820ent);
+    }
+
+    auto now = processor::ticks();
+    u32 now_high = (u32)(now >> 32);
+    u32 now_low = (u32)now;
+
+    mb_info->tsc_init_hi = now_high;
+    mb_info->tsc_init = now_low;
+
+    mb_info->tsc_disk_done_hi = now_high;
+    mb_info->tsc_disk_done = now_low;
+
+    mb_info->tsc_uncompress_done_hi = now_high;
+    mb_info->tsc_uncompress_done = now_low;
+}
-- 
2.19.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to