📜 ⬆️ ⬇️

Porting your own OS to Xen

A couple of years ago, a student project on the transformation of Embox into an ideal platform for the cloud so fashionable was taking place on Mat-Meh. 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 by students OS under Xen, adding a new platform to Embox, and, of course, why all this was started at all.

The idea behind the ideal cloud platform is:
There is the concept of unikernel . In short, the developer of a single application chooses the right set of functionality to work with. Only this functionality is included in the operating system, which is linked into a single image along with the application. With this approach, resources are obviously saved. Of course, this is the only application that does not have very large functionality, but if you put a lot of different applications in the cloud (in fact, services), you can get very broad functionality.

Porting to Xen


Xen Health Check


Any porting of anything to anything is worth starting with checking existing solutions. Under Xen, quite a lot of operating systems are already running. Of course, we are primarily interested in open Linux. Xen has one feature: before you launch something, you must first learn how to create and manage instances of this platform. 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 by default).

To verify that we are now running the hypervisor, it suffices to verify that the output of the command cat /proc/cpuinfo | grep hypervisor cat /proc/cpuinfo | grep hypervisor not empty. Similarly, you can verify the output of the command virt-what , it should contain the domain xen-dom0

Another verification option is to use the “xl” command that we will need in the future.

The sudo xl list command should display something like this:

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

Domain Management


There are several ways to create and manage virtual machines in Xen.
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 up” in the files of the system, 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 the /etc/xen-tools/xen-tools.conf file and can be overridden. All parameters can also be overridden when creating the machine.

Network setup


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

Install the packages:

 sudo apt-get install bridge-utils 

Next, edit the file /etc/network/interfaces
It was

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

It became

 # 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 


Create a virtual machine image.


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 --pygrub flag indicates that the PyGrub boot loader will be used in the virtual machine, allowing each virtual machine to use its own kernel instead of the dom0 kernel. The --dir parameter indicates that you want to use the directory for images, and not a separate partition of a previously broken disk.

The conclusion is approximately as follows:
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
Done

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

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

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

Running hooks
Done

No role scripts were specified. Skipping

Creating Xen configuration file
Done

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

Logfile produced at:
/var/log/xen-tools/test.log

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 make sure that the image is created using the command:

 sudo xen-list-images 

In my case, the team issued

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

Start (car creation)


 sudo xl create /etc/xen/test.cfg 

Now virtualka test will appear when calling the command “sudo xl list”:

 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 its console:

 sudo xl console test 

Exit from the console of the virtual machine by the combination "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 <bio-0> 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 <maxk@qualcomm.com> [ 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. done. Begin: Running /scripts/init-bottom ... mount: mounting /dev on /root/dev failed: No such file or directory done. 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. (initramfs) 


Let's see what this image 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 (initramfs) 

Run a small OS (Mini-OS)


From the previous part, it became clear that to work you need 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 = [ 'file:/srv/xen/test/domains/test/disk.img,xvda2,w', 'file:/srv/xen/test/domains/test/swap.img,xvda1,w', ] # # 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 it requires the presence of disk images, there is a network, and so on. Most likely, it is too difficult for our purposes. But Xen supports other operating systems. The base is the so-called Mini-OS . And it is designed 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 the README right away.

 make sudo xl create -c domain_config 

We get a 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 cmd_line: 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 from the console, as usual, ctrl +]

Check that we have started some kind of car

 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 you can specify not disks, but directly the image using the parameter kernel , and also not specify network settings and other parameters that we do not need in the first stage.

Porting Embox to Xen


Creating a configuration file


To begin with, to launch a domain with Embox, we will make a configuration file in the image of Mini-OS.

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

Adding Architecture to Embox


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

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

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

The following is added to the Embox linker script for Xen:

 PHDRS { xen PT_NOTE; } SECTIONS { .note : { *(.note) } :xen } 

Well, an assembly file was added that contains the content for this header.

 #include <xen/elfnote.h> .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_PAE_MODE, .asciz "yes") ELFNOTE(XEN_ELFNOTE_VIRT_BASE, .long 0x100000) ELFNOTE(XEN_ELFNOTE_PADDR_OFFSET, .long 0x100000) ELFNOTE(XEN_ELFNOTE_HYPERCALL_PAGE, .long 0x100000) 

In addition, there are a couple of structures needed for interaction between the image and Xen struct start_info and struct shared_info.
struct start_info is needed if we want to receive information about the machine when starting an image, 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 * (ie, 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_info , as can be seen, contains information about the interaction, that is, through it we will receive events: interrupts, data has come, and so on.
This structure is located with an offset of 4kb.

And our linker script looks like this.

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

Actually, I would like to finish this, since the analysis of the entire code is clearly beyond the scope of one article. Let me just say that at the moment the students implemented the launch of the machine with a debug output.
To make sure of this, it is enough to do the following in Embox;

 make confload-xen/debug make ./scripts/xen/run_xen 

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

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

In the end I would like to again address the topic of training in IT. As I already wrote in the article: “How to catch a programmer on cheating and whether it is worth doing this,” in our project we are promoting diving students into a real project. In this case, students get much more experience than when performing learning tasks, albeit fairly large-scale ones. And most importantly, they are not only learning a particular language, but learning how to create products, solve problems on their own and simply be able to think. As an example, I refer to the author of the idea of ​​the ideal cloud platform, Anton Kozlov ( antonkozlov ), because I referred to his diploma earlier. As a result of his studies, he was able not only to write code, but also to propose his own ideas, implement them, break the task up into components and train students. We have many such examples.

PS: Video from that conference is available here .

Source: https://habr.com/ru/post/349526/


All Articles