Porting your own OS to Xen

    A couple of years ago on Mat-Meh there was a student project to turn Embox into an ideal platform for the cloud so fashionable today. One of the obvious parts of this task was porting to some virtualization platform, and the choice fell on Xen. In this article I will talk about the process of porting students OS under Xen, adding a new platform to Embox, and, of course, why all this was started.

    The idea of ​​an ideal platform for the cloud is as follows:
    There is a concept of unikernel. In short, the developer of a single application selects the desired set of functionality for work. Only this functionality is included in the operating system, which is linked into a single image with the application. With this approach, resources are obviously saved. Of course, this is the only application that doesn’t have much functionality, but if you put many different applications (in essence, services) in the cloud, you can get very wide functionality.

    Porting to Xen

    Xen Health Check

    Any porting of something to something should start with checking existing solutions. Under Xen, quite a few operating systems already work. Of course, we are primarily interested in open Linux. Xen has one feature: before you start something, you first need to learn how to instantiate this platform and manage it. In other words, you need to learn how to create separate virtual machines (domains).

    To work with Xen, you need to install the appropriate packages:

    sudo apt-get install xen-hypervisor-4.8-amd64 xen-tools

    After that, you need to reboot and, at boot time, select the version of your OS on Xen (usually it is the default).

    To verify that we are now under the control of a hypervisor, it is enough to verify that the output of the command is cat /proc/cpuinfo | grep hypervisornot empty. Similarly, you can check the output of the command virt-what, it must contain the xen-dom0 domain.

    Another test option is to use the “xl” command, which we will need in the future.

    The command sudo xl listshould output something like this:

    Name                                        ID   Mem VCPUs      State   Time(s)
    Domain-0                                     0   945     1     r-----      11.3

    Domain management

    Xen has several ways to create and manage virtual machines.
    The first is installation using third-party programs (for example, virt-manager or oVirt). Usually they have a graphical interface, and the program itself “digs” into the system files, making the necessary changes.

    The second way is to work in the console.

    In the case of Linux virtualization, we will use xen-tools + xl (or xm). This is convenient because many Linux distributions are already prepared for paravirtualization.

    The parameters with which new virtual machines are created are located in a file /etc/xen-tools/xen-tools.conf; they can be redefined. All parameters can also be overridden when creating a machine.

    Setting up a network environment

    There are several ways to network between domains. We choose the simplest one - Bridge Network (virtual machines will be visible on the local network as physical devices along with dom0).

    Install packages:

    sudo apt-get install bridge-utils

    Next, edit the file /etc/network/interfaces

    # The loopback network interface
    auto lo
    iface lo inet loopback
    # The primary network interface
    allow-hotplug enp5s0
    iface enp5s0 inet dhcp

    Has become

    # The loopback network interface
    auto lo
    iface lo inet loopback
    # The primary network interface
    allow-hotplug enp5s0
    iface enp5s0 inet manual
    auto xenbr0
    iface xenbr0 inet dhcp
            bridge_ports enp5s0

    Creating an image of a virtual machine.

    An example of creating a virtual machine with Ubuntu:

    sudo xen-create-image --hostname test --dhcp --pygrub --dist precise --mirror="http://mirror.yandex.ru/ubuntu" --dir /srv/xen/test

    The flag --pygrubindicates that the PyGrub loader will be used in the virtual machine, allowing each virtual machine to use its own kernel instead of the core from dom0. The parameter --dirindicates that you want to use the directory for the images, and not a separate section of the previously partitioned disk.

    The output is approximately the following:
    General Information
    - Hostname: test
    Distribution: precise
    Mirror: mirror.yandex.ru/ubuntu
    Partitions: swap 512M (swap)
    / 4G (ext4)
    Image type: sparse
    Memory size: 256M
    Bootloader: pygrub

    Networking Information
    - IP Address: DHCP [MAC : 00: 16: 3E: 8E: 3C: E0]

    Creating partition image: /srv/xen/test/domains/test/swap.img

    Creating swap on /srv/xen/test/domains/test/swap.img

    Creating partition image: /srv/xen/test/domains/test/disk.img

    Creating ext4 filesystem on /srv/xen/test/domains/test/disk.img
    Installation method: debootstrap

    Running hooks

    No role scripts were specified. Skipping

    Creating Xen configuration file

    No role scripts were specified. Skipping
    Setting up root password
    Generating a password for the new guest.
    All done

    Logfile produced at:

    Installation Summary
    - Hostname: test
    Distribution: precise
    MAC Address: 00: 16: 3E: 8E: 3C: E0
    IP Address (es): dynamic
    SSH Fingerprint : SHA256: H49PEnPv0k0tw2faq1CStkR6KFlHF0GkUOWvYaeiqOU (DSA)
    SSH Fingerprint: SHA256: 5gIsrTAriqEiwdkVCygOtLOi9uOd2DJWFBlJKxdJfUw (ECDSA)
    SSH Fingerprint: SHA256: SB + bTbkIUr2Qn019xT8AFtAKO5f6xlkbt8juVBq6zTE (RSA)
    Root Password: RJpaLfBFseH9YJX77ScxRwP

    You can verify that the image is created using the command:

    sudo xen-list-images

    In my case, the command issued

    Name: test
    Memory: 256 MB
    Config: /etc/xen/test.cfg

    Start up (machine creation)

    sudo xl create /etc/xen/test.cfg

    Now test virtual machine will appear when the “sudo xl list” command is called:

    Name                                        ID   Mem VCPUs    State    Time(s)
    Domain-0                                     0 15356     8     r-----    4283.8
    test                                         2   256     1     -b----       1.5

    It remains to connect to her console:

    sudo xl console test    

    Exiting the virtual machine console is a combination of "ctrl + ]"

    The resulting conclusion
    [    0.000000] Initializing cgroup subsys cpuset
    [    0.000000] Initializing cgroup subsys cpu
    [    0.000000] Linux version 3.2.0-126-virtual (buildd@lcy01-11) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #169-Ubuntu SMP Fri Mar 31 14:47:56 UTC 2017 (Ubuntu 3.2.0-126.169-virtual 3.2.79)
    [    0.000000] Command line: root=/dev/xvda2 ro elevator=noop root=/dev/xvda2 ro
    [    0.000000] KERNEL supported cpus:
    [    0.000000]   Intel GenuineIntel
    [    0.000000]   AMD AuthenticAMD
    [    0.000000]   Centaur CentaurHauls
    [    0.000000] ACPI in unprivileged domain disabled
    [    0.000000] Released 0 pages of unused memory
    [    0.000000] Set 0 page(s) to 1-1 mapping
    [    0.000000] BIOS-provided physical RAM map:
    [    0.000000]  Xen: 0000000000000000 - 00000000000a0000 (usable)
    [    0.000000]  Xen: 00000000000a0000 - 0000000000100000 (reserved)
    [    0.000000]  Xen: 0000000000100000 - 0000000010000000 (usable)
    [    0.000000] NX (Execute Disable) protection: active
    [    0.000000] DMI not present or invalid.
    [    0.000000] No AGP bridge found
    [    0.000000] last_pfn = 0x10000 max_arch_pfn = 0x400000000
    [    0.000000] init_memory_mapping: 0000000000000000-0000000010000000
    [    0.000000] RAMDISK: 0205c000 - 02c43000
    [    0.000000] NUMA turned off
    [    0.000000] Faking a node at 0000000000000000-0000000010000000
    [    0.000000] Initmem setup node 0 0000000000000000-0000000010000000
    [    0.000000]   NODE_DATA [000000000fffb000 - 000000000fffffff]
    [    0.000000] Zone PFN ranges:
    [    0.000000]   DMA      0x00000010 -> 0x00001000
    [    0.000000]   DMA32    0x00001000 -> 0x00100000
    [    0.000000]   Normal   empty
    [    0.000000] Movable zone start PFN for each node
    [    0.000000] early_node_map[2] active PFN ranges
    [    0.000000]     0: 0x00000010 -> 0x000000a0
    [    0.000000]     0: 0x00000100 -> 0x00010000
    [    0.000000] SFI: Simple Firmware Interface v0.81 http://simplefirmware.org
    [    0.000000] SMP: Allowing 1 CPUs, 0 hotplug CPUs
    [    0.000000] No local APIC present
    [    0.000000] APIC: disable apic facility
    [    0.000000] APIC: switched to apic NOOP
    [    0.000000] PM: Registered nosave memory: 00000000000a0000 - 0000000000100000
    [    0.000000] Allocating PCI resources starting at 10000000 (gap: 10000000:f0000000)
    [    0.000000] Booting paravirtualized kernel on Xen
    [    0.000000] Xen version: 4.8.3-pre (preserve-AD)
    [    0.000000] setup_percpu: NR_CPUS:64 nr_cpumask_bits:64 nr_cpu_ids:1 nr_node_ids:1
    [    0.000000] PERCPU: Embedded 27 pages/cpu @ffff88000fc00000 s78848 r8192 d23552 u2097152
    [    0.000000] Built 1 zonelists in Node order, mobility grouping on.  Total pages: 64395
    [    0.000000] Policy zone: DMA32
    [    0.000000] Kernel command line: root=/dev/xvda2 ro elevator=noop root=/dev/xvda2 ro
    [    0.000000] PID hash table entries: 1024 (order: 1, 8192 bytes)
    [    0.000000] xsave/xrstor: enabled xstate_bv 0x7, cntxt size 0x340
    [    0.000000] Checking aperture...
    [    0.000000] No AGP bridge found
    [    0.000000] Memory: 228408k/262144k available (6617k kernel code, 448k absent, 33288k reserved, 6579k data, 932k init)
    [    0.000000] SLUB: Genslabs=15, HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
    [    0.000000] Hierarchical RCU implementation.
    [    0.000000]     RCU dyntick-idle grace-period acceleration is enabled.
    [    0.000000] NR_IRQS:4352 nr_irqs:256 16
    [    0.000000] Console: colour dummy device 80x25
    [    0.000000] console [tty0] enabled
    [    0.000000] console [hvc0] enabled
    [    0.000000] allocated 2097152 bytes of page_cgroup
    [    0.000000] please try 'cgroup_disable=memory' option if you don't want memory cgroups
    [    0.000000] installing Xen timer for CPU 0
    [    0.000000] Detected 3194.398 MHz processor.
    [    0.004000] Calibrating delay loop (skipped), value calculated using timer frequency.. 6388.79 BogoMIPS (lpj=12777592)
    [    0.004000] pid_max: default: 32768 minimum: 301
    [    0.004000] Security Framework initialized
    [    0.004000] AppArmor: AppArmor initialized
    [    0.004000] Yama: becoming mindful.
    [    0.004000] Dentry cache hash table entries: 32768 (order: 6, 262144 bytes)
    [    0.004000] Inode-cache hash table entries: 16384 (order: 5, 131072 bytes)
    [    0.004000] Mount-cache hash table entries: 256
    [    0.004000] Initializing cgroup subsys cpuacct
    [    0.004000] Initializing cgroup subsys memory
    [    0.004000] Initializing cgroup subsys devices
    [    0.004000] Initializing cgroup subsys freezer
    [    0.004000] Initializing cgroup subsys blkio
    [    0.004000] Initializing cgroup subsys perf_event
    [    0.004000] CPU: Physical Processor ID: 0
    [    0.004000] CPU: Processor Core ID: 0
    [    0.006575] SMP alternatives: switching to UP code
    [    0.034623] Freeing SMP alternatives: 24k freed
    [    0.034647] ftrace: allocating 26699 entries in 105 pages
    [    0.036061] cpu 0 spinlock event irq 17
    [    0.036079] Performance Events:
    [    0.036082] no APIC, boot with the "lapic" boot parameter to force-enable it.
    [    0.036086] no hardware sampling interrupt available.
    [    0.036094] Broken PMU hardware detected, using software events only.
    [    0.036207] NMI watchdog disabled (cpu0): hardware events not enabled
    [    0.036229] Brought up 1 CPUs
    [    0.036343] devtmpfs: initialized
    [    0.036844] EVM: security.selinux
    [    0.036848] EVM: security.SMACK64
    [    0.036851] EVM: security.capability
    [    0.037364] Grant table initialized
    [    0.037410] print_constraints: dummy:
    [    0.057265] RTC time: 165:165:165, date: 165/165/65
    [    0.057318] NET: Registered protocol family 16
    [    0.057508] Extended Config Space enabled on 0 nodes
    [    0.057542] PCI: setting up Xen PCI frontend stub
    [    0.057542] bio: create slab  at 0
    [    0.057542] ACPI: Interpreter disabled.
    [    0.057542] xen/balloon: Initialising balloon driver.
    [    0.057542] xen-balloon: Initialising balloon driver.
    [    0.057542] vgaarb: loaded
    [    0.057542] i2c-core: driver [aat2870] using legacy suspend method
    [    0.057542] i2c-core: driver [aat2870] using legacy resume method
    [    0.057542] SCSI subsystem initialized
    [    0.057542] usbcore: registered new interface driver usbfs
    [    0.057542] usbcore: registered new interface driver hub
    [    0.057542] usbcore: registered new device driver usb
    [    0.057542] PCI: System does not support PCI
    [    0.057542] PCI: System does not support PCI
    [    0.057542] NetLabel: Initializing
    [    0.057542] NetLabel:  domain hash size = 128
    [    0.057542] NetLabel:  protocols = UNLABELED CIPSOv4
    [    0.057542] NetLabel:  unlabeled traffic allowed by default
    [    0.057542] Switching to clocksource xen
    [    0.061230] AppArmor: AppArmor Filesystem Enabled
    [    0.061253] pnp: PnP ACPI: disabled
    [    0.062521] NET: Registered protocol family 2
    [    0.065648] IP route cache hash table entries: 2048 (order: 2, 16384 bytes)
    [    0.065807] TCP established hash table entries: 8192 (order: 5, 131072 bytes)
    [    0.065861] TCP bind hash table entries: 8192 (order: 5, 131072 bytes)
    [    0.065881] TCP: Hash tables configured (established 8192 bind 8192)
    [    0.065885] TCP reno registered
    [    0.065889] UDP hash table entries: 128 (order: 0, 4096 bytes)
    [    0.065895] UDP-Lite hash table entries: 128 (order: 0, 4096 bytes)
    [    0.065934] NET: Registered protocol family 1
    [    0.065967] platform rtc_cmos: registered platform RTC device (no PNP device found)
    [    0.066094] Trying to unpack rootfs image as initramfs...
    [    0.072210] audit: initializing netlink socket (disabled)
    [    0.190742] type=2000 audit(1518793913.856:1): initialized
    [    0.209702] Freeing initrd memory: 12188k freed
    [    0.213726] VFS: Disk quotas dquot_6.5.2
    [    0.213770] Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
    [    0.213950] hugetlbfs: disabling because there are no supported hugepage sizes
    [    0.214050] fuse init (API version 7.17)
    [    0.214104] msgmni has been set to 469
    [    0.214342] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
    [    0.214362] io scheduler noop registered (default)
    [    0.214367] io scheduler deadline registered
    [    0.214386] io scheduler cfq registered
    [    0.214439] pci_hotplug: PCI Hot Plug PCI Core version: 0.5
    [    0.214454] pciehp: PCI Express Hot Plug Controller Driver version: 0.4
    [    0.214460] acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
    [    0.214672] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
    [    0.215413] Linux agpgart interface v0.103
    [    0.216235] brd: module loaded
    [    0.216618] loop: module loaded
    [    0.217745] blkfront device/vbd/51714 num-ring-pages 1 nr_ents 32.
    [    0.218925] blkfront device/vbd/51713 num-ring-pages 1 nr_ents 32.
    [    0.219299] Fixed MDIO Bus: probed
    [    0.219322] tun: Universal TUN/TAP device driver, 1.6
    [    0.219329] tun: (C) 1999-2004 Max Krasnyansky 
    [    0.219390] PPP generic driver version 2.4.2
    [    0.219430] Initialising Xen virtual ethernet driver.
    [    0.222394] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
    [    0.222413] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
    [    0.222423] uhci_hcd: USB Universal Host Controller Interface driver
    [    0.222459] usbcore: registered new interface driver libusual
    [    0.222477] i8042: PNP: No PS/2 controller found. Probing ports directly.
    [    1.223457] i8042: No controller found
    [    1.223625] mousedev: PS/2 mouse device common for all mice
    [    1.263475] rtc_cmos rtc_cmos: rtc core: registered rtc_cmos as rtc0
    [    1.263520] rtc_cmos: probe of rtc_cmos failed with error -38
    [    1.263601] device-mapper: uevent: version 1.0.3
    [    1.263654] device-mapper: ioctl: 4.22.0-ioctl (2011-10-19) initialised: dm-devel@redhat.com
    [    1.263664] EFI Variables Facility v0.08 2004-May-17
    [    1.263886] TCP cubic registered
    [    1.263952] NET: Registered protocol family 10
    [    1.264555] NET: Registered protocol family 17
    [    1.264564] Registering the dns_resolver key type
    [    1.264668] registered taskstats version 1
    [    1.273569] blkfront: xvda2: flush diskcache: enabled
    [    1.274605] blkfront: xvda1: flush diskcache: enabled
    [    1.368068]   Magic number: 1:252:3141
    [    1.368107] /build/linux-JvAKgs/linux-3.2.0/drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
    [    1.368118] BIOS EDD facility v0.16 2004-Jun-25, 0 devices found
    [    1.368121] EDD information not available.
    [    1.368534] Freeing unused kernel memory: 932k freed
    [    1.368687] Write protecting the kernel read-only data: 12288k
    [    1.373188] Freeing unused kernel memory: 1556k freed
    [    1.373812] Freeing unused kernel memory: 1172k freed
    Loading, please wait...
    Begin: Loading essential drivers ... done.
    [    1.402645] udevd[82]: starting version 175
    Begin: Running /scripts/init-premount ... done.
    Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
    Begin: Running /scripts/local-premount ... done.
    [    1.506696] JBD2: Unrecognised features on journal
    [    1.506706] EXT4-fs (xvda2): error loading journal
    mount: mounting /dev/xvda2 on /root failed: Invalid argument
    Begin: Running /scripts/local-bottom ... done.
    Begin: Running /scripts/init-bottom ... mount: mounting /dev on /root/dev failed: No such file or directory
    mount: mounting /sys on /root/sys failed: No such file or directory
    mount: mounting /proc on /root/proc failed: No such file or directory
    Target filesystem doesn't have requested /sbin/init.
    No init found. Try passing init= bootarg.
    BusyBox v1.18.5 (Ubuntu 1:1.18.5-1ubuntu4) built-in shell (ash)
    Enter 'help' for a list of built-in commands.

    Let's see what kind of image it is:

    (initramfs) uname -a
    Linux (none) 3.2.0-126-virtual #169-Ubuntu SMP Fri Mar 31 14:47:56 UTC 2017 x86_64 GNU/Linux

    Launching a small OS (Mini-OS)

    From the previous part, it became clear that to work it is necessary to create a domain (instance). It is created using the xl utility based on the configuration file.

    But if we look at the configuration file
    # Configuration file for the Xen instance test, created
    # by xen-tools 4.7 on Fri Feb 16 18:09:35 2018.
    #  Kernel + memory size
    bootloader = '/usr/lib/xen-4.8/bin/pygrub'
    vcpus       = '1'
    memory      = '256'
    #  Disk device(s).
    root        = '/dev/xvda2 ro'
    disk        = [
    #  Physical volumes
    #  Hostname
    name        = 'test'
    #  Networking
    dhcp        = 'dhcp'
    vif         = [ 'mac=00:16:3E:8E:3C:E0' ]
    #  Behaviour
    on_poweroff = 'destroy'
    on_reboot   = 'restart'
    on_crash    = 'restart'

    Then we will see that there is a need for disk images, there is a network, and so on. Most likely, it is too complicated for our purposes. But Xen also supports other OSs. The base is the so-called Mini-OS . Moreover, it is intended for those who want to port their operating systems to XEN , that is, this is just our option.
    The git code is separate from XEN.

    Let's do the instructions from README right away.

    sudo xl create -c domain_config

    We get the conclusion
    Parsing config from domain_config
    Xen Minimal OS (pv)!
      start_info: 0x7d000(VA)
        nr_pages: 0x2000
      shared_inf: 0xdee73000(MA)
         pt_base: 0x80000(VA)
    nr_pt_frames: 0x5
        mfn_list: 0x6d000(VA)
       mod_start: 0x0(VA)
         mod_len: 0
           flags: 0x0
           stack: 0x2c6a0-0x4c6a0
    MM: Init
          _text: 0(VA)
         _etext: 0x18484(VA)
       _erodata: 0x1f000(VA)
         _edata: 0x1f252(VA)
    stack start: 0x2c6a0(VA)
           _end: 0x6cfd8(VA)
      start_pfn: 85
        max_pfn: 2000
    Mapping memory range 0x85000 - 0x2000000
    setting 0-0x1f000 readonly
    skipped 1000
    MM: Initialise page allocator for 93000(93000)-2000000(2000000)
        Adding memory range 94000-2000000
    MM: done
    Demand map pfns at 100000000000-108000000000.
    Initialising timer interface
    Initialising console ... done.
    gnttab_table mapped at 0x100000000000.
    Initialising scheduler
    Thread "Idle": pointer: 0x0x96078, stack: 0x0xa0000
    Thread "xenstore": pointer: 0x0x960d8, stack: 0x0xb0000
    xenbus initialised on irq 1
    Thread "shutdown": pointer: 0x0x96138, stack: 0x0xc0000
    kernel.c: dummy main: par=0

    Exit the console, as usual, ctrl +]

    Check that we have started some kind of machine

    sudo xl list
    Name                                        ID   Mem VCPUs    State    Time(s)
    Domain-0                                     0 15455     8     r-----    5117.7
    Mini-OS                                      2    32     1     -b----       0.0

    To return to the console

    sudo xl console Mini-OS

    To delete a domain

    sudo xl  destroy Mini-OS

    Well, let's look at the contents of domain_config in the root of the project
    #  -*- mode: python; -*-
    # Python configuration setup for 'xm create'.
    # This script sets the parameters used when a domain is created using 'xm create'.
    # You use a separate script for each domain you want to create, or
    # you can set the parameters for the domain on the xm command line.
    # Kernel image file.
    kernel = "mini-os.gz"
    # Initial memory allocation (in megabytes) for the new domain.
    memory = 32
    # A name for your domain. All domains must have different names.
    name = "Mini-OS"
    on_crash = 'destroy'

    It can be seen that it is possible to specify not disks, but directly the image using the kernel parameter , and also not to specify network settings and other parameters that we do not need at the first stage.

    Porting Embox to Xen

    Creating a configuration file

    First, to start the domain with Embox, we will make a configuration file in the image and likeness of Mini-OS.

    name = "embox"
    memory = 256
    kernel = "/tmp/xen_embox"

    Adding Architecture to Embox

    Embox has a diploma of Anton Kozlov ( antonkozlov ) about transferring it to the new platform “Porting an operating system with modular HAL to user mode” . More precisely, the diploma was not about porting Embox, but about organizing operating systems in general, and Embox was used as a guinea pig. Specifically, about Xen there is a course Andrei Golikov “Porting the Embox operating system to the Xen platform” . In order not to retell the diploma and course, I will limit myself to a few important and specific to Xen parts.

    All the necessary information, as you probably guessed, can be obtained from the Mini-OS .

    One of the first things that porting starts with is a memory card (no, not an SD card, which you might have thought of, but different memory regions - a memory map), which is traditionally described in an lds script. The linker needs to indicate where the program code, data, the entry point to the program should lie, and so on. In our case, this is added by the fact that before loading the image, some features from the “.note.Xen” sections should be read, more precisely, the header in the ELF PT_NOTE format. A memory card along with features is described here .

    The following is added to the Embox linker script for Xen

    PHDRS {
        xen      PT_NOTE;
        .note : {
        } :xen

    Well, another assembly file has been added that contains the content for this header

    .section ".note", "a"
    #define ELFNOTE(type, desc) \
        .p2align 2; \
        .long 1f - 0f; \
        .long 3f - 2f; \
        .long type; \
    0:  .asciz "Xen"; \
    1:  .p2align 2; \
    2:   desc; \
    3:  .p2align 2;
    ELFNOTE(XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
    ELFNOTE(XEN_ELFNOTE_LOADER, .asciz "generic")
    ELFNOTE(XEN_ELFNOTE_VIRT_BASE, .long 0x100000)

    In addition, there are a couple more structures needed for the interaction between the image and Xen struct start_info and struct shared_info.
    struct start_info is needed if we want to get information about the machine when the image starts, that is, without it, in principle, we can do.

     * `incontents 200 startofday_shared Start-of-day shared data structure
     * Xen/kernel shared data -- pointer provided in start_info.
     * This structure is defined to be both smaller than a page, and the
     * only data on the shared page, but may vary in actual size even within
     * compatible Xen versions; guests should not rely on the size
     * of this structure remaining constant.
    struct shared_info {
        struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
         * A domain can create "event channels" on which it can send and receive
         * asynchronous event notifications. There are three classes of event that
         * are delivered by this mechanism:
         *  1. Bi-directional inter- and intra-domain connections. Domains must
         *     arrange out-of-band to set up a connection (usually by allocating
         *     an unbound 'listener' port and avertising that via a storage service
         *     such as xenstore).
         *  2. Physical interrupts. A domain with suitable hardware-access
         *     privileges can bind an event-channel port to a physical interrupt
         *     source.
         *  3. Virtual interrupts ('events'). A domain can bind an event-channel
         *     port to a virtual interrupt source, such as the virtual-timer
         *     device or the emergency console.
         * Event channels are addressed by a "port index". Each channel is
         * associated with two bits of information:
         *  1. PENDING -- notifies the domain that there is a pending notification
         *     to be processed. This bit is cleared by the guest.
         *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
         *     will cause an asynchronous upcall to be scheduled. This bit is only
         *     updated by the guest. It is read-only within Xen. If a channel
         *     becomes pending while the channel is masked then the 'edge' is lost
         *     (i.e., when the channel is unmasked, the guest must manually handle
         *     pending notifications as no upcall will be scheduled by Xen).
         * To expedite scanning of pending notifications, any 0->1 pending
         * transition on an unmasked channel causes a corresponding bit in a
         * per-vcpu selector word to be set. Each bit in the selector covers a
         * 'C long' in the PENDING bitfield array.
        xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
        xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
         * Wallclock time: updated only by control software. Guests should base
         * their gettimeofday() syscall on this wallclock-base value.
        uint32_t wc_version;      /* Version counter: see vcpu_time_info_t. */
        uint32_t wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
        uint32_t wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
        struct arch_shared_info arch;

    struct shared_infoAs you can see, it contains information about the interaction, that is, through it we will receive events: interruptions, data came, etc.
    This structure is located with a 4k offset.

    And our linker script looks like this

        .text : {
            . = ALIGN(0x1000);
            hypercall_page = .;
            . += 0x1000;
            xen_shared_info = .;
            . += 0x1000;
            _traps_text_start = .;
            _traps_text_end = .;

    Actually, I would like to end here, since the analysis of all the code is clearly beyond the scope of one article. I can only say that at the moment, students have implemented a machine launch with debug output.
    To verify this, just do the following in Embox;

    make confload-xen/debug

    The domain will be created and the output of Embox itself will go. The output from the console, as always, ctrl +], and then do not forget to remove the car: sudo destroy embox.

    Naturally, you first need to set the environment. But for simplicity, we, and not students, already added the ability to deliver everything through vagrand. This is described on the wiki . You only need VirtualBox and vagrand. You need to install it not under Xen.

    In the end, I would like to touch upon the topic of training in IT again. As I already wrote in the article: “How to catch a programmer on cheating and is it worth it to do it”, in our project we are promoting the immersion of students in a real project. In this case, students get much more experience than when performing educational tasks, albeit quite ambitious. And most importantly, they not only learn a particular language, but learn to create products, solve problems on their own and simply be able to think. As an example, I will refer to the author of the idea about an ideal cloud platform, Anton Kozlov ( antonkozlov ), because I referred to his diploma earlier. According to the results of training, he was able not only to write code, but also to offer his own ideas, implement them, break down the task into components and train students. We have many similar examples.

    PS: Video from that conference is available here .

    Also popular now: