Kudos Waldek!
On Thu, May 21, 2020 at 1:58 PM Waldek Kozaczuk <[email protected]>
wrote:
>
> *ubuntu@ubuntu-rasp4*:*~*$ uname -a
>
> Linux ubuntu-rasp4 5.3.0-1025-raspi2 #27-Ubuntu SMP Fri May 8 08:32:04
> UTC 2020 aarch64 aarch64 aarch64 GNU/Linux
>
> *ubuntu@ubuntu-rasp4*:*~*$ ./firecracker-v0.21.1-aarch64 --no-api --config
> -file ./osv-config.json
>
> OSv v0.55.0-9-g840428ad
>
> PSCI: version 65536.0 detected.
>
> setup_arm_clock() ENTERED, lr=00000000800d54e0
>
> arm_clock(): frequency read as 000000000337f980
>
> interrupt_table::interrupt_table() ENTERED, lr=00000000800a8d1c
>
> gic_driver::init_cpu() ENTERED, lr=0000000080201c80
>
> CPU interface enabled.
>
> gic_driver::init_dist() ENTERED, lr=0000000080201c8c
>
> number of supported IRQs: 0000000000000080
>
> interrupt table: gic driver created.
>
> registered IRQ id=0000000000000004
>
> registered IRQ id=000000000000001b
>
> registered IRQ id=0000000000000000
>
> Premain complete!
>
> smp_launch ENTERED, lr=00000000800d709c
>
> Booted up in 0.00 ms
>
> Cmdline: console=ttyS0 --verbose --nomount --maxnic=0 /tools/hello.so
> earlycon=uart,mmio,0x40001000
>
> faulting address 000010000001fea0
>
> faulting address 0000100000000328
>
> faulting address 0000100000020000
>
> faulting address 0000100000050018
>
> faulting address 00001000000301c8
>
> faulting address 000010000004fe00
>
> Hello from C code
>
> 2020-05-21T20:24:04.080765641 [anonymous-instance:ERROR:src/vmm/src/vstate
> .rs:951] Unexpected exit reason on vcpu run: SystemEvent
>
> In general it took me a bit of research as I am not really familiar with
> ARM architecture and even reading the assembly was a bit a challenge to say
> the least. And then debugging without debugger and any console (:-( .. so
> not debug() for long time. But all in all it was not too bad and the
> changes that I had to make to OSv are in my opinion much smaller and easier
> comparing to x86_64.
>
> Below you will see the "hack-patch" showing what changes I had to make.
> Logically, following things had to be changed:
>
> - The most important thing was to move kernel from 0x40000000 (1GB) to
> 0x80000000 (2GB) which required changing one line in Makefile (see below)
> and changing boot paging table to map the 2GB-3GB area of memory; only then
> I could actually start debugging :-) I wonder if it will also work on
> QEMU/KVM - possinly qemu boot loader will inspect ELF and place it
> accordingly in memory; firecracker does not read ELF and simply places it
> at 2GB
> - To get console working I guessed that that need to create equivalent
> class for isa_serial_console but communicating over mmio (see
> mmio_isa_serial_console.hh/cc) which in essence invokes mmio_set*/mmio_get*
> (it would be nice to extract common code somehow - suggestions welcome)
> - Some more trivial changes - for now mostly disabling things - for
> now quite disorganized
>
>
> diff --git a/Makefile b/Makefile
> index db3c68cf..ffd570a5 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -354,6 +354,7 @@ tools := tools/mkfs/mkfs.so tools/cpiod/cpiod.so
> $(out)/tools/%.o: COMMON += -fPIC
>
> tools += tools/uush/uush.so
> +tools += tools/uush/hello.so
> tools += tools/uush/ls.so
> tools += tools/uush/mkdir.so
>
> @@ -451,8 +452,8 @@ endif # x64
>
> ifeq ($(arch),aarch64)
>
> -kernel_base := 0x40080000
> -kernel_vm_base := 0x40080000
> +kernel_base := 0x80080000
> +kernel_vm_base := 0x80080000
> app_local_exec_tls_size := 0x0
>
> include $(libfdt_base)/Makefile.libfdt
> @@ -816,6 +817,7 @@ drivers += drivers/xenplatform-pci.o
> endif # x64
>
> ifeq ($(arch),aarch64)
> +drivers += drivers/mmio-isa-serial.o
> drivers += drivers/pl011.o
> drivers += drivers/xenconsole.o
> drivers += drivers/virtio.o
> diff --git a/arch/aarch64/arch-dtb.cc b/arch/aarch64/arch-dtb.cc
> index b59f1dcc..cd0719e8 100644
> --- a/arch/aarch64/arch-dtb.cc
> +++ b/arch/aarch64/arch-dtb.cc
> @@ -225,7 +225,8 @@ bool dtb_get_gic_v2(u64 *dist, size_t *dist_len, u64
> *cpu, size_t *cpu_len)
> if (!dtb)
> return false;
>
> - node = fdt_node_offset_by_compatible(dtb, -1, "arm,cortex-a15-gic");
> + //node = fdt_node_offset_by_compatible(dtb, -1, "arm,cortex-a15-gic");
> + node = fdt_node_offset_by_compatible(dtb, -1, "arm,gic-400");
> if (node < 0)
> return false;
>
> @@ -613,11 +614,13 @@ void __attribute__((constructor(init_prio::dtb)))
> dtb_setup()
> abort("dtb_setup: failed to parse cpu mpid.\n");
> }
>
> + //TODO: Parse PCI only if required and
> + // abort if missing only if required
> dtb_timer_irq = dtb_parse_timer_irq();
> dtb_pci_irqmask = dtb_parse_pci_irqmask();
> dtb_pci_irqmap_count = dtb_parse_pci_irqmap_count();
> if (!dtb_parse_pci_irqmap(dtb_pci_bdfs, dtb_pci_irq_ids,
> dtb_pci_irqmap_count)) {
> - abort("dtb_setup: failed to parse pci_irq_map.\n");
> + //abort("dtb_setup: failed to parse pci_irq_map.\n");
> }
>
> register u64 edata;
> diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc
> index bdbb1266..b12546ae 100644
> --- a/arch/aarch64/arch-setup.cc
> +++ b/arch/aarch64/arch-setup.cc
> @@ -17,6 +17,7 @@
> #include <osv/debug.hh>
> #include <osv/commands.hh>
> #include <osv/xen.hh>
> +#include <osv/version.h>
>
> #include "arch-mmu.hh"
> #include "arch-dtb.hh"
> @@ -25,6 +26,7 @@
> #include "drivers/pl011.hh"
> #include "early-console.hh"
> #include <osv/pci.hh>
> +#include "drivers/mmio-isa-serial.hh"
>
> #include <alloca.h>
>
> @@ -93,9 +95,10 @@ void arch_setup_free_memory()
>
> if (!is_xen()) {
> /* linear_map [TTBR0 - UART] */
> - addr = (mmu::phys)console::aarch64_console.pl011.get_base_addr();
> - mmu::linear_map((void *)addr, addr, 0x1000, mmu::page_size,
> - mmu::mattr::dev);
> + //TODO: Only run it if pl011 is detected
> + //addr =
> (mmu::phys)console::aarch64_console.pl011.get_base_addr();
> + //mmu::linear_map((void *)addr, addr, 0x1000, mmu::page_size,
> + // mmu::mattr::dev);
> }
>
> /* linear_map [TTBR0 - GIC DIST and GIC CPU] */
> @@ -110,12 +113,17 @@ void arch_setup_free_memory()
> mmu::linear_map((void *)cpu, (mmu::phys)cpu, cpu_len, mmu::page_size,
> mmu::mattr::dev);
>
> - arch_setup_pci();
> + //TODO: Call it only if PCI available
> + //arch_setup_pci();
>
> // get rid of the command line, before memory is unmapped
> osv::parse_cmdline(cmdline);
>
> mmu::switch_to_runtime_page_tables();
> +
> + //TODO: This is probably wrong place to init the console
> + arch_init_early_console();
> + debug_early("OSv " OSV_VERSION "\n");
> }
>
> void arch_setup_tls(void *tls, const elf::tls_data& info)
> @@ -185,27 +193,35 @@ void arch_init_early_console()
> return;
> }
>
> + /* Comment out for now
> new (&console::aarch64_console.pl011) console::PL011_Console();
> console::arch_early_console = console::aarch64_console.pl011;
> int irqid;
> - u64 addr = dtb_get_uart(&irqid);
> - if (!addr) {
> + u64 addr = dtb_get_uart(&irqid);*/
> + //if (!addr) {
> /* keep using default addresses */
> - return;
> - }
> + // return;
> + //}
>
> - console::aarch64_console.pl011.set_base_addr(addr);
> - console::aarch64_console.pl011.set_irqid(irqid);
> + //console::aarch64_console.pl011.set_base_addr(addr);
> + //console::aarch64_console.pl011.set_irqid(irqid);
> +
> + new (&console::aarch64_console.mmio_isa_serial)
> console::mmio_isa_serial_console();
> + console::arch_early_console =
> console::aarch64_console.mmio_isa_serial;
> +
> + console::mmio_isa_serial_console::early_init();
> }
>
> bool arch_setup_console(std::string opt_console)
> {
> + /*
> if (opt_console.compare("pl011") == 0) {
> console::console_driver_add(&console::arch_early_console);
> } else if (opt_console.compare("all") == 0) {
> console::console_driver_add(&console::arch_early_console);
> } else {
> return false;
> - }
> + }*/
> + console::console_driver_add(&console::arch_early_console);
> return true;
> }
> diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S
> index b29fd16a..1d2af75c 100644
> --- a/arch/aarch64/boot.S
> +++ b/arch/aarch64/boot.S
> @@ -188,21 +188,15 @@ ident_pt_l4_ttbr0:
> .quad 0
> .endr
> ident_pt_l3_ttbr0:
> - .quad ident_pt_l2_0_ttbr0 + 0x3
> - .quad ident_pt_l2_1_ttbr0 + 0x3
> - .rept 510
> + .quad 0
> + .quad 0
> + .quad ident_pt_l2_2_ttbr0 + 0x3 // Map 4GB-6GB one-to-one
> + .rept 509
> .quad 0
> .endr
> -ident_pt_l2_0_ttbr0:
> - index = 0
> - offset = 0x00000000
> - .rept 512
> - .quad (index << 21) + 0x401
> - index = index + 1
> - .endr
> -ident_pt_l2_1_ttbr0:
> +ident_pt_l2_2_ttbr0:
> index = 0
> - offset = 0x40000000
> + offset = 0x80000000
> .rept 512
> .quad offset + (index << 21) + 0x411
> index = index + 1
> diff --git a/arch/aarch64/early-console.cc b/arch/aarch64/early-console.cc
> index d5196c74..8c91c965 100644
> --- a/arch/aarch64/early-console.cc
> +++ b/arch/aarch64/early-console.cc
> @@ -13,6 +13,7 @@
> namespace console {
>
> union AARCH64_Console aarch64_console;
> -console_driver & arch_early_console = aarch64_console.pl011;
> +//console_driver & arch_early_console = aarch64_console.pl011;
> +console_driver & arch_early_console = aarch64_console.mmio_isa_serial;
>
> }
> diff --git a/arch/aarch64/early-console.hh b/arch/aarch64/early-console.hh
> index cbc2cac4..cd39738b 100644
> --- a/arch/aarch64/early-console.hh
> +++ b/arch/aarch64/early-console.hh
> @@ -11,12 +11,15 @@
> #include <drivers/console-driver.hh>
> #include <drivers/pl011.hh>
> #include <drivers/xenconsole.hh>
> +#include <drivers/mmio-isa-serial.hh>
> +
>
> namespace console {
>
> union AARCH64_Console {
> PL011_Console pl011;
> XEN_Console xen;
> + mmio_isa_serial_console mmio_isa_serial;
>
> AARCH64_Console() {}; /* placement new is used to initialize object
> */
> ~AARCH64_Console() {}; /* won't ever be called */
> diff --git a/arch/aarch64/mmu.cc b/arch/aarch64/mmu.cc
> index fef48e5a..012d3c57 100644
> --- a/arch/aarch64/mmu.cc
> +++ b/arch/aarch64/mmu.cc
> @@ -18,11 +18,11 @@ void page_fault(exception_frame *ef)
> {
> sched::fpu_lock fpu;
> SCOPE_LOCK(fpu);
> - debug_early_entry("page_fault");
> + //debug_early_entry("page_fault");
> u64 addr;
> asm volatile ("mrs %0, far_el1" : "=r"(addr));
> debug_early_u64("faulting address ", (u64)addr);
> - debug_early_u64("elr exception ra ", (u64)ef->elr);
> + //debug_early_u64("elr exception ra ", (u64)ef->elr);
>
> if (fixup_fault(ef)) {
> debug_early("fixed up with fixup_fault\n");
> @@ -45,7 +45,7 @@ void page_fault(exception_frame *ef)
> mmu::vm_fault(addr, ef);
> }
>
> - debug_early("leaving page_fault()\n");
> + //debug_early("leaving page_fault()\n");
> }
>
> namespace mmu {
> diff --git a/drivers/mmio-isa-serial.cc b/drivers/mmio-isa-serial.cc
> new file mode 100644
> index 00000000..c59cec8d
> --- /dev/null
> +++ b/drivers/mmio-isa-serial.cc
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2013 Cloudius Systems, Ltd.
> + *
> + * 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 "mmio-isa-serial.hh"
> +
> +namespace console {
> +
> +// UART registers, offsets to ioport:
> +enum regs {
> + IER = 1, // Interrupt Enable Register
> + FCR = 2, // FIFO Control Register
> + LCR = 3, // Line Control Register
> + MCR = 4, // Modem Control Register
> + LSR = 5, // Line Control Register
> + MSR = 6, // Modem Status Register
> + SCR = 7, // Scratch Register
> + DLL = 0, // Divisor Latch LSB Register
> + DLM = 1, // Divisor Latch MSB Register
> +};
> +
> +enum lcr {
> + // When bit 7 (DLAB) of LCR is set to 1, the two registers 0 and 1
> + // change their meaning and become two bytes controlling the baud rate
> + DLAB = 0x80, // Divisor Latch Access Bit in LCR register
> + LEN_8BIT = 3,
> +};
> +
> +// Various bits of the Line Status Register
> +enum lsr {
> + RECEIVE_DATA_READY = 0x1,
> + OVERRUN = 0x2,
> + PARITY_ERROR = 0x4,
> + FRAME_ERROR = 0x8,
> + BREAK_INTERRUPT = 0x10,
> + TRANSMIT_HOLD_EMPTY = 0x20,
> + TRANSMIT_EMPTY = 0x40,
> + FIFO_ERROR = 0x80,
> +};
> +
> +// Various bits of the Modem Control Register
> +enum mcr {
> + DTR = 0x1,
> + RTS = 0x2,
> + AUX_OUTPUT_1 = 0x4,
> + AUX_OUTPUT_2 = 0x8,
> + LOOPBACK_MODE = 0x16,
> +};
> +
> +mmioaddr_t mmio_isa_serial_console::_addr_mmio;
> +
> +void mmio_isa_serial_console::early_init()
> +{
> + u64 address = 0x40001000; //TODO: Should parse from boot command line
> ('earlycon=uart,mmio,0x40001000')
> + u64 size = 4096;
> +
> + _addr_mmio = mmio_map(address, size);
> +
> + // Set the UART speed to to 115,200 bps, This is done by writing 1,0
> to
> + // Divisor Latch registers, but to access these we need to temporarily
> + // set the Divisor Latch Access Bit (DLAB) on the LSR register,
> because
> + // the UART has fewer ports than registers...
> + mmio_setb(_addr_mmio + (int)regs::LCR, lcr::LEN_8BIT | lcr::DLAB);
> + mmio_setb(_addr_mmio + (int)regs::DLL, 1);
> + mmio_setb(_addr_mmio + (int)regs::DLM, 0);
> + mmio_setb(_addr_mmio + (int)regs::LCR, lcr::LEN_8BIT);
> +
> + // interrupt threshold
> + mmio_setb(_addr_mmio + (int)regs::FCR, 0);
> +
> + // disable interrupts
> + mmio_setb(_addr_mmio + (int)regs::IER, 0);
> +
> + // Most physical UARTs need the MCR AUX_OUTPUT_2 bit set to 1 for
> + // interrupts to be generated. QEMU doesn't bother checking this
> + // bit, but interestingly VMWare does, so we must set it.
> + mmio_setb(_addr_mmio + (int)regs::MCR, mcr::AUX_OUTPUT_2);
> +}
> +
> +void mmio_isa_serial_console::write(const char *str, size_t len)
> +{
> + while (len-- > 0)
> + putchar(*str++);
> +}
> +
> +bool mmio_isa_serial_console::input_ready()
> +{
> + u8 val = mmio_getb(_addr_mmio + (int)regs::LSR);
> + // On VMWare hosts without a serial port, this register always
> + // returns 0xff. Just ignore it instead of spinning incessantly.
> + return (val != 0xff && (val & lsr::RECEIVE_DATA_READY));
> +}
> +
> +char mmio_isa_serial_console::readch()
> +{
> + u8 val;
> + char letter;
> +
> + do {
> + val = mmio_getb(_addr_mmio + (int)regs::LSR);
> + } while (!(val & (lsr::RECEIVE_DATA_READY | lsr::OVERRUN |
> lsr::PARITY_ERROR | lsr::FRAME_ERROR)));
> +
> + letter = mmio_getb(_addr_mmio);
> +
> + return letter;
> +}
> +
> +void mmio_isa_serial_console::putchar(const char ch)
> +{
> + u8 val;
> +
> + do {
> + val = mmio_getb(_addr_mmio + (int)regs::LSR);
> + } while (!(val & lsr::TRANSMIT_HOLD_EMPTY));
> +
> + mmio_setb(_addr_mmio, ch);
> +}
> +
> +void mmio_isa_serial_console::enable_interrupt()
> +{
> + // enable interrupts
> + mmio_setb(_addr_mmio + (int)regs::IER, 1);
> +}
> +
> +void mmio_isa_serial_console::dev_start() {
> + //TODO: Figure out which interrupt and what kind to use
> + //_irq.reset(new sgi_edge_interrupt(4, [&] { _thread->wake(); }));
> + enable_interrupt();
> +}
> +
> +}
> diff --git a/drivers/mmio-isa-serial.hh b/drivers/mmio-isa-serial.hh
> new file mode 100644
> index 00000000..f422dfda
> --- /dev/null
> +++ b/drivers/mmio-isa-serial.hh
> @@ -0,0 +1,39 @@
> +/*
> + * Copyright (C) 2013 Cloudius Systems, Ltd.
> + *
> + * 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.
> + */
> +
> +#ifndef DRIVERS_MMIO_ISA_SERIAL_HH
> +#define DRIVERS_MMIO_ISA_SERIAL_HH
> +
> +#include "console-driver.hh"
> +#include <osv/pci.hh>
> +#include <osv/sched.hh>
> +#include <osv/interrupt.hh>
> +#include <osv/mmio.hh>
> +
> +namespace console {
> +
> +class mmio_isa_serial_console : public console_driver {
> +public:
> + static void early_init();
> + virtual void write(const char *str, size_t len);
> + virtual void flush() {}
> + virtual bool input_ready() override;
> + virtual char readch();
> +
> +private:
> + //std::unique_ptr<sgi_edge_interrupt> _irq;
> + static mmioaddr_t _addr_mmio;
> +
> + virtual void dev_start();
> + void enable_interrupt();
> + static void putchar(const char ch);
> + virtual const char *thread_name() { return "mmio-isa-serial-input"; }
> +};
> +
> +}
> +
> +#endif
> diff --git a/loader.cc b/loader.cc
> index 66bfb52c..9867ca49 100644
> --- a/loader.cc
> +++ b/loader.cc
> @@ -94,12 +94,12 @@ extern "C" {
>
> void premain()
> {
> - arch_init_early_console();
> + //arch_init_early_console();
>
> /* besides reporting the OSV version, this string has the function
> to check if the early console really works early enough,
> without depending on prior initialization. */
> - debug_early("OSv " OSV_VERSION "\n");
> + //debug_early("OSv " OSV_VERSION "\n");
>
> arch_init_premain();
>
> @@ -116,6 +116,7 @@ void premain()
> for (auto init = inittab.start; init < inittab.start + inittab.count;
> ++init) {
> (*init)();
> }
> + debug_early("Premain complete!\n");
> boot_time.event(".init functions");
> }
>
> @@ -230,6 +231,7 @@ static void parse_options(int loader_argc, char**
> loader_argv)
> opt_maxnic = true;
> maxnic = options::extract_option_int_value(options_values,
> "maxnic", handle_parse_error);
> }
> + maxnic = 0;
>
> if (extract_option_flag(options_values, "trace-backtrace")) {
> opt_log_backtrace = true;
> @@ -261,6 +263,7 @@ static void parse_options(int loader_argc, char**
> loader_argv)
> }
>
> opt_mount = !extract_option_flag(options_values, "nomount");
> + opt_mount = false;
> opt_pivot = !extract_option_flag(options_values, "nopivot");
> opt_random = !extract_option_flag(options_values, "norandom");
> opt_init = !extract_option_flag(options_values, "noinit");
> @@ -351,7 +354,8 @@ std::vector<std::vector<std::string> >
> prepare_commands(char* app_cmdline)
> bool ok;
>
> printf("Cmdline: %s\n", app_cmdline);
> - commands = osv::parse_command_line(app_cmdline, ok);
> + //commands = osv::parse_command_line(app_cmdline, ok);
> + commands = osv::parse_command_line("/tools/hello.so", ok);
>
> if (!ok) {
> puts("Failed to parse command line.");
> diff --git a/usr_ramfs.manifest.skel b/usr_ramfs.manifest.skel
> index 4bdfdd32..1a04c22f 100644
> --- a/usr_ramfs.manifest.skel
> +++ b/usr_ramfs.manifest.skel
> @@ -3,6 +3,8 @@
> /libvdso.so: libvdso.so
> /tools/mount-fs.so: tools/mount/mount-fs.so
> /tools/umount.so: tools/mount/umount.so
> +/tools/uush.so: tools/uush/uush.so
> +/tools/hello.so: tools/uush/hello.so
> /usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1
> /&/etc/hosts: ../../static/&
>
>
>
> Please not that I have not tested how it works with multiple CPUs or if
> virtual block and network devices operate.
>
> Waldek
>
> --
> 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].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/osv-dev/f4c6cafe-690a-4619-b7b6-e414e3f9343a%40googlegroups.com
> <https://groups.google.com/d/msgid/osv-dev/f4c6cafe-690a-4619-b7b6-e414e3f9343a%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
--
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].
To view this discussion on the web visit
https://groups.google.com/d/msgid/osv-dev/CAKUaUn6s4bCRBiEMyx8ALpmarUj01Bh%3DHUwtusu6MXHnLgmNrQ%40mail.gmail.com.