aboutsummaryrefslogtreecommitdiffstats
path: root/src/ortho/llvm-nodebug/llvm-bitwriter.ads
blob: 0c16f1cc6d625d529f96755e54af7f2d90648f0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
--  LLVM binding
--  Copyright (C) 2014 Tristan Gingold
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 2 of the License, or
--  (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program.  If not, see <gnu.org/licenses>.
with LLVM.Core; use LLVM.Core;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with Interfaces.C; use Interfaces.C;

package LLVM.BitWriter is
   -- Writes a module to an open file descriptor. Returns 0 on success.
   -- Closes the Handle. Use dup first if this is not what you want.
   function WriteBitcodeToFileHandle(M : ModuleRef; Handle : File_Descriptor)
                                    return int;

   -- Writes a module to the specified path. Returns 0 on success.
   function WriteBitcodeToFile(M : ModuleRef; Path : Cstring)
                              return int;
private
   pragma Import (C, WriteBitcodeToFileHandle, "LLVMWriteBitcodeToFileHandle");
   pragma Import (C, WriteBitcodeToFile, "LLVMWriteBitcodeToFile");
end LLVM.BitWriter;
='#n298'>298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Copyright IBM Corp. 2005, 2006, 2007
 *
 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
 *          Amos Waterland <apw@us.ibm.com>
 *          Hollis Blanchard <hollisb@us.ibm.com>
 */

#include <xen/config.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/cpumask.h>
#include <xen/sched.h>
#include <xen/multiboot.h>
#include <xen/serial.h>
#include <xen/softirq.h>
#include <xen/console.h>
#include <xen/trace.h>
#include <xen/mm.h>
#include <xen/domain.h>
#include <xen/gdbstub.h>
#include <xen/symbols.h>
#include <xen/keyhandler.h>
#include <xen/numa.h>
#include <xen/rcupdate.h>
#include <xen/version.h>
#include <acm/acm_hooks.h>
#include <public/version.h>
#include <asm/mpic.h>
#include <asm/processor.h>
#include <asm/desc.h>
#include <asm/cache.h>
#include <asm/debugger.h>
#include <asm/delay.h>
#include <asm/percpu.h>
#include <asm/io.h>
#include "exceptions.h"
#include "of-devtree.h"
#include "oftree.h"
#include "rtas.h"

#define DEBUG

/* opt_noht: If true, Hyperthreading is ignored. */
int opt_noht = 0;
boolean_param("noht", opt_noht);

int opt_earlygdb = 0;
boolean_param("earlygdb", opt_earlygdb);

/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
boolean_param("nosmp", opt_nosmp);

/* maxcpus: maximum number of CPUs to activate. */
static unsigned int max_cpus = NR_CPUS;
integer_param("maxcpus", max_cpus);

u32 tlbflush_clock = 1U;
DEFINE_PER_CPU(u32, tlbflush_time);

unsigned int watchdog_on;
unsigned long wait_init_idle;
ulong oftree;
ulong oftree_len;
ulong oftree_end;

uint cpu_hard_id[NR_CPUS] __initdata;
cpumask_t cpu_present_map;

/* XXX get this from ISA node in device tree */
char *vgabase;
ulong isa_io_base;
struct ns16550_defaults ns16550;

extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];

static struct domain *idle_domain;

volatile struct processor_area * volatile global_cpu_table[NR_CPUS];

static void __init do_initcalls(void)
{
    initcall_t *call;
    for (call = &__initcall_start; call < &__initcall_end; call++) {
        (*call)();
    }
}


void noinline __attn(void)
{
    /* To continue the probe will step over the ATTN instruction.  The
     * NOP is there to make sure there is something sane to "step
     * over" to. */
    console_start_sync();
    asm volatile(".long 0x200;nop");
    console_end_sync();
}

static void key_hw_probe_attn(unsigned char key)
{
    __attn();
}

static void key_ofdump(unsigned char key)
{
    printk("ofdump:\n");
    /* make sure the OF devtree is good */
    ofd_walk((void *)oftree, "devtree", OFD_ROOT,
             ofd_dump_props, OFD_DUMP_ALL);
}

static void percpu_init_areas(void)
{
    unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;

    BUG_ON(data_size > PERCPU_SIZE);

    for ( i = 1; i < NR_CPUS; i++ )
        memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
               __per_cpu_start,
               data_size);
}

static void percpu_free_unused_areas(void)
{
    unsigned int i, first_unused;

    /* Find first unused CPU number. */
    for ( i = 0; i < NR_CPUS; i++ )
        if ( !cpu_online(i) )
            break;
    first_unused = i;

    /* Check that there are no holes in cpu_online_map. */
    for ( ; i < NR_CPUS; i++ )
        BUG_ON(cpu_online(i));

    init_xenheap_pages((ulong)__per_cpu_start + (first_unused << PERCPU_SHIFT),
                       (ulong)__per_cpu_end);
}

static void __init start_of_day(void)
{
    init_IRQ();

    scheduler_init();

    /* create idle domain */
    idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
    if ((idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL))
        BUG();
    set_current(idle_domain->vcpu[0]);
    idle_vcpu[0] = current;

    initialize_keytable();
    /* Register another key that will allow for the the Harware Probe
     * to be contacted, this works with RiscWatch probes and should
     * work with Chronos and FSPs */
    register_keyhandler('^', key_hw_probe_attn, "Trap to Hardware Probe");

    /* allow the dumping of the devtree */
    register_keyhandler('D', key_ofdump , "Dump OF Devtree");

    timer_init();
    rcu_init();
    serial_init_postirq();
    do_initcalls();
}

void startup_cpu_idle_loop(void)
{
    struct vcpu *v = current;

    ASSERT(is_idle_vcpu(v));
    cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
    cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);

    /* Finally get off the boot stack. */
    reset_stack_and_jump(idle_loop);
}

/* The boot_pa is enough "parea" for the boot CPU to get thru
 * initialization, it will ultimately get replaced later */
static __init void init_boot_cpu(void)
{
    static struct processor_area boot_pa;
    boot_pa.whoami = 0;
    parea = &boot_pa;
}    

static void init_parea(int cpuid)
{
    /* Be careful not to shadow the global variable.  */
    volatile struct processor_area *pa;
    void *stack;

    pa = xmalloc(struct processor_area);
    if (pa == NULL)
        panic("%s: failed to allocate parea for cpu #%d\n", __func__, cpuid);

    stack = alloc_xenheap_pages(STACK_ORDER);
    if (stack == NULL)
        panic("%s: failed to allocate stack (order %d) for cpu #%d\n", 
              __func__, STACK_ORDER, cpuid);

    pa->whoami = cpuid;
    pa->hard_id = cpu_hard_id[cpuid];
    pa->hyp_stack_base = (void *)((ulong)stack + STACK_SIZE);
    mb();

    /* This store has the effect of invoking secondary_cpu_init.  */
    global_cpu_table[cpuid] = pa;
    mb();
}

static int kick_secondary_cpus(int maxcpus)
{
    int cpuid;

    for_each_present_cpu(cpuid) {
        int threads;
        int i;
        
        threads = cpu_threads(cpuid);
        for (i = 0; i < threads; i++)
            cpu_set(i, cpu_sibling_map[cpuid]);

        /* For now everything is single core */
        cpu_set(cpuid, cpu_core_map[cpuid]);

        rcu_online_cpu(cpuid);

        numa_set_node(cpuid, 0);
        numa_add_cpu(cpuid);

        if (cpuid == 0)
            continue;
        if (cpuid >= maxcpus)
            break;
        init_parea(cpuid);
        smp_generic_give_timebase();

        /* wait for it */
        while (!cpu_online(cpuid))
            cpu_relax();
    }

    return 0;
}

/* This is the first C code that secondary processors invoke.  */
void secondary_cpu_init(int cpuid, unsigned long r4)
{
    struct vcpu *vcpu;

    cpu_initialize(cpuid);
    smp_generic_take_timebase();

    /* If we are online, we must be able to ACK IPIs.  */
    mpic_setup_this_cpu();
    cpu_set(cpuid, cpu_online_map);

    vcpu = alloc_vcpu(idle_domain, cpuid, cpuid);
    BUG_ON(vcpu == NULL);

    set_current(idle_domain->vcpu[cpuid]);
    idle_vcpu[cpuid] = current;
    startup_cpu_idle_loop();

    panic("should never get here\n");
}

static void __init __start_xen(multiboot_info_t *mbi)
{
    char *cmdline;
    module_t *mod = (module_t *)((ulong)mbi->mods_addr);
    ulong dom0_start, dom0_len;
    ulong initrd_start, initrd_len;

    memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
    synchronize_caches(0, exception_vectors_end - exception_vectors);

    ticks_per_usec = timebase_freq / 1000000ULL;

    /* Parse the command-line options. */
    if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
        cmdline_parse(__va((ulong)mbi->cmdline));

    /* we need to be able to identify this CPU early on */
    init_boot_cpu();

    /* We initialise the serial devices very early so we can get debugging. */
    ns16550.io_base = 0x3f8;
    ns16550_init(0, &ns16550);
    ns16550.io_base = 0x2f8;
    ns16550_init(1, &ns16550);
    serial_init_preirq();

    init_console();
    /* let synchronize until we really get going */
    console_start_sync();

    /* Check that we have at least one Multiboot module. */
    if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
        panic("FATAL ERROR: Require at least one Multiboot module.\n");
    }

    /* OF dev tree is the last module */
    oftree = mod[mbi->mods_count-1].mod_start;
    oftree_end = mod[mbi->mods_count-1].mod_end;
    oftree_len = oftree_end - oftree;

    /* remove it from consideration */
    mod[mbi->mods_count-1].mod_start = 0;
    mod[mbi->mods_count-1].mod_end = 0;
    --mbi->mods_count;

    if (rtas_entry) {
        rtas_init((void *)oftree);
        /* remove rtas module from consideration */
        mod[mbi->mods_count-1].mod_start = 0;
        mod[mbi->mods_count-1].mod_end = 0;
        --mbi->mods_count;
    }
    memory_init(mod, mbi->mods_count);

#ifdef OF_DEBUG
    key_ofdump(0);
#endif
    percpu_init_areas();

    init_parea(0);
    cpu_initialize(0);

#ifdef CONFIG_GDB
    initialise_gdb();
    if (opt_earlygdb)
        debugger_trap_immediate();
#endif

    start_of_day();

    acm_init(NULL, 0);

    mpic_setup_this_cpu();

    /* Deal with secondary processors.  */
    if (opt_nosmp || ofd_boot_cpu == -1) {
        printk("nosmp: leaving secondary processors spinning forever\n");
    } else {
        printk("spinning up at most %d total processors ...\n", max_cpus);
        kick_secondary_cpus(max_cpus);
    }

    /* This cannot be called before secondary cpus are marked online.  */
    percpu_free_unused_areas();

    /* Create initial domain 0. */
    dom0 = domain_create(0, 0, DOM0_SSIDREF);
    if (dom0 == NULL)
        panic("Error creating domain 0\n");

    /* The Interrupt Controller will route everything to CPU 0 so we
     * need to make sure Dom0's vVCPU 0 is pinned to the CPU */
    dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);

    dom0->is_privileged = 1;

    cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);

    /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
    local_irq_enable();
    /* Scrub RAM that is still free and so may go to an unprivileged domain. */
    scrub_heap_pages();

    dom0_start = mod[0].mod_start;
    dom0_len = mod[0].mod_end - mod[0].mod_start;
    if (mbi->mods_count > 1) {
        initrd_start = mod[1].mod_start;
        initrd_len = mod[1].mod_end - mod[1].mod_start;
    } else {
        initrd_start = 0;
        initrd_len = 0;
    }
    if (construct_dom0(dom0, dom0_start, dom0_len,
                       initrd_start, initrd_len,
                       cmdline) != 0) {
        panic("Could not set up DOM0 guest OS\n");
    }

    init_xenheap_pages(ALIGN_UP(dom0_start, PAGE_SIZE),
                       ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
    if (initrd_start)
        init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE),
                           ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));

    init_trace_bufs();

    console_endboot();

    /* Hide UART from DOM0 if we're using it */
    serial_endboot();

    console_end_sync();

    domain_unpause_by_systemcontroller(dom0);
#ifdef DEBUG_IPI
    ipi_torture_test();
#endif
    startup_cpu_idle_loop();
}

void __init __start_xen_ppc(
    ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr)
{
    multiboot_info_t *mbi = NULL;

    /* clear bss */
    memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);

    if (r5 > 0) {
        /* we were booted by OpenFirmware */
        mbi = boot_of_init(r3, r4, r5, r6, r7, orig_msr);

    } else {
        /* booted by someone else that hopefully has a trap handler */
        __builtin_trap();
    }

    __start_xen(mbi);

}

extern void arch_get_xen_caps(xen_capabilities_info_t *info);
void arch_get_xen_caps(xen_capabilities_info_t *info)
{
    /* Interface name is always xen-3.0-* for Xen-3.x. */
    int major = 3, minor = 0;
    char s[32];

    (*info)[0] = '\0';

    snprintf(s, sizeof(s), "xen-%d.%d-powerpc64 ", major, minor);
    safe_strcat(*info, s);
}



/*
 * Local variables:
 * mode: C
 * c-set-style: "BSD"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */