Skip to content
Snippets Groups Projects
loader.cc 3.38 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "drivers/isa-serial.hh"
    
    #include "fs/fs.hh"
    
    #include <boost/format.hpp>
    #include <cctype>
    
    #include "elf.hh"
    
    #include "tls.hh"
    #include "msr.hh"
    
    Avi Kivity's avatar
    Avi Kivity committed
    #include "exceptions.hh"
    
    #include "debug.hh"
    
    #include "drivers/pci.hh"
    
    #include "smp.hh"
    
    #include "drivers/virtio-net.hh"
    
    #include "drivers/virtio-blk.hh"
    
    Avi Kivity's avatar
    Avi Kivity committed
    #include "sched.hh"
    
    Avi Kivity's avatar
    Avi Kivity committed
    #include "drivers/clock.hh"
    
    Avi Kivity's avatar
    Avi Kivity committed
    #include "drivers/clockevent.hh"
    #include "barrier.hh"
    
    #include "tests/tst-hub.hh"
    
    Avi Kivity's avatar
    Avi Kivity committed
    asm(".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1 \n"
        ".byte 1 \n"
        ".asciz \"scripts/loader.py\" \n"
        ".popsection \n");
    
    
    namespace {
    
        void test_locale()
        {
    	auto loc = std::locale();
    	auto &fac = std::use_facet<std::ctype<char>>(loc);
    	bool ok = fac.is(std::ctype_base::digit, '3')
    	    && !fac.is(std::ctype_base::digit, 'x');
    
    	debug(ok ? "locale works" : "locale fails");
    
    Avi Kivity's avatar
    Avi Kivity committed
    elf::Elf64_Ehdr* elf_header;
    
    elf::tls_data tls_data;
    
    void setup_tls(elf::init_table inittab)
    {
    
        tls_data = inittab.tls;
    
        extern char tcb0[]; // defined by linker script
    
        memcpy(tcb0, inittab.tls.start, inittab.tls.size);
        auto p = reinterpret_cast<thread_control_block*>(tcb0 + inittab.tls.size);
    
        p->self = p;
        processor::wrmsr(msr::IA32_FS_BASE, reinterpret_cast<uint64_t>(p));
    }
    
    
    extern "C" {
        void premain();
        void vfs_init(void);
        void ramdisk_init(void);
    }
    
    void premain()
    {
        auto inittab = elf::get_init(elf_header);
    
        setup_tls(inittab);
    
        for (auto init = inittab.start; init < inittab.start + inittab.count; ++init) {
            (*init)();
        }
    }
    
    
    Avi Kivity's avatar
    Avi Kivity committed
    void disable_pic()
    {
        outb(0xff, 0x21);
        outb(0xff, 0xa1);
    }
    
    
    Avi Kivity's avatar
    Avi Kivity committed
    int main(int ac, char **av)
    {
    
        debug("Loader Copyright 2013 Unnamed");
    
    Avi Kivity's avatar
    Avi Kivity committed
        idt.load_on_cpu();
    
        smp_init();
    
        void main_cont(int ac, char** av);
        sched::init(tls_data, [=] { main_cont(ac, av); });
    }
    
    void main_cont(int ac, char** av)
    {
    
        smp_launch();
    
    Avi Kivity's avatar
    Avi Kivity committed
        sched::init_detached_threads_reaper();
    
        vfs_init();
    
    
        filesystem fs;
    
    Avi Kivity's avatar
    Avi Kivity committed
        disable_pic();
    
    Avi Kivity's avatar
    Avi Kivity committed
        processor::sti();
    
    Avi Kivity's avatar
    Avi Kivity committed
    
    
        prog = new elf::program(fs);
        void main_thread(int ac, char** av);
    
        main_thread(ac, av);
    
    struct argblock {
        int ac;
        char** av;
    };
    
    void run_main(elf::program *prog, struct argblock *args)
    {
        auto av = args->av;
        auto ac = args->ac;
        prog->add_object(av[0]);
        ++av, --ac;
    
        auto osv_main = prog->lookup_function<void (int, char**)>("osv_main");
        osv_main(ac, av);
    
    void* do_main_thread(void *_args)
    
        auto args = static_cast<argblock*>(_args);
    
    
        //Tests malloc and free using threads.
    
        unit_tests::tests::instance().execute_tests();
    
        pci::pci_device_enumeration();
    
        // Initialize all drivers
        hw::driver_manager* drvman = hw::driver_manager::instance();
    
        drvman->register_driver(new virtio::virtio_blk(0));
    
        drvman->register_driver(new virtio::virtio_blk(1));
    
        drvman->register_driver(new virtio::virtio_net());
        drvman->load_all();
        drvman->list_drivers();
    
        run_main(prog, args);
    
    Avi Kivity's avatar
    Avi Kivity committed
        while (true)
    	;
    
    void main_thread(int ac, char **av)
    
    {
        pthread_t pthread;
        // run the payload in a pthread, so pthread_self() etc. work
    
        argblock args{ ac, av };
        pthread_create(&pthread, nullptr, do_main_thread, &args);
    
        sched::thread::wait_until([] { return false; });