setup.c

来自「xen 3.2.2 源码」· C语言 代码 · 共 509 行

C
509
字号
/* * 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/multiboot2.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 <xsm/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 <asm/boot.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;/* linked-in dom0: */extern char dom0_start[] __attribute__ ((weak));extern char dom0_size[] __attribute__ ((weak));char *xen_cmdline;char *dom0_cmdline;ulong dom0_addr;ulong dom0_len;ulong initrd_start;ulong initrd_len;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(void){    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. */    cmdline_parse(xen_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();    console_start_sync(); /* Stay synchronous for early debugging. */    rtas_init((void *)oftree);    memory_init();    printk("xen_cmdline:  %016lx\n", (ulong)xen_cmdline);    printk("dom0_cmdline: %016lx\n", (ulong)dom0_cmdline);    printk("dom0_addr:    %016lx\n", (ulong)dom0_addr);    printk("dom0_len:     %016lx\n", (ulong)dom0_len);    printk("initrd_start: %016lx\n", (ulong)initrd_start);    printk("initrd_len:   %016lx\n", (ulong)initrd_len);    printk("dom0: %016llx\n", *(unsigned long long *)dom0_addr);#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;    /* 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();    if ((dom0_addr == 0) || (dom0_len == 0))        panic("No domain 0 found.\n");    if (construct_dom0(dom0, dom0_addr, dom0_len,                       initrd_start, initrd_len,                       dom0_cmdline) != 0) {        panic("Could not set up DOM0 guest OS\n");    }    init_xenheap_pages(ALIGN_UP(dom0_addr, PAGE_SIZE),                       ALIGN_DOWN(dom0_addr + 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();}static void ofd_bootargs(void){    static const char *sepr[] = {" -- ", " || "};    char *p;    ofdn_t chosen;    int sepr_index;    int rc;    if (builtin_cmdline[0] == '\0') {        chosen = ofd_node_find((void *)oftree, "/chosen");        rc = ofd_getprop((void *)oftree, chosen, "bootargs", builtin_cmdline,                         CONFIG_CMDLINE_SIZE);    }    /* look for delimiter: "--" or "||" */    for (sepr_index = 0; sepr_index < ARRAY_SIZE(sepr); sepr_index++){        p = strstr(builtin_cmdline, sepr[sepr_index]);        if (p != NULL) {            /* Xen proper should never know about the dom0 args.  */            *p = '\0';            p += strlen(sepr[sepr_index]);            dom0_cmdline = p;            break;        }    }    xen_cmdline = builtin_cmdline;}void __init __start_xen_ppc(ulong, ulong, ulong, ulong, ulong, ulong);void __init __start_xen_ppc(    ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr){    /* clear bss */    memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);    if (r5) {        /* We came from Open Firmware. */        boot_of_init(r5, orig_msr);        oftree = (ulong)boot_of_devtree(); /* Copy the device tree. */        /* Use the device tree to find the Xen console. */        boot_of_serial((void *)oftree);        boot_of_finish(); /* End firmware. */    } else {        /* XXX handle flat device tree here */        __builtin_trap();    }    ofd_bootargs();    if (r3 == MB2_BOOTLOADER_MAGIC) {        /* Get dom0 info from multiboot structures. */        parse_multiboot(r4);    }    if ((dom0_len == 0) && r3 && r4) {        /* Maybe dom0's location handed to us in registers. */        dom0_addr = r3;        dom0_len = r4;    }    if (dom0_len == 0) {        /* Dom0 had better be built in. */        dom0_addr = (ulong)dom0_start;        dom0_len = (ulong)dom0_size;    }    __start_xen();}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: */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?