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 + -
显示快捷键?