Пример #1
0
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();
}
Пример #2
0
/* Bring up a remote CPU */
int __cpu_up(unsigned int cpu)
{
    int rc;

    printk("Bringing up CPU%d\n", cpu);

    rc = init_secondary_pagetables(cpu);
    if ( rc < 0 )
        return rc;

    console_start_sync(); /* Secondary may use early_printk */

    /* Tell the remote CPU which stack to boot on. */
    init_data.stack = idle_vcpu[cpu]->arch.stack;

    /* Tell the remote CPU what is it's logical CPU ID */
    init_data.cpuid = cpu;

    /* Open the gate for this CPU */
    smp_up_cpu = cpu_logical_map(cpu);
    flush_xen_dcache(smp_up_cpu);

    rc = arch_cpu_up(cpu);

    console_end_sync();

    if ( rc < 0 )
    {
        printk("Failed to bring up CPU%d\n", cpu);
        return rc;
    }

    while ( !cpu_online(cpu) )
    {
        cpu_relax();
        process_pending_softirqs();
    }

    return 0;
}
Пример #3
0
/* Main interface to do xen specific suspend/resume */
static int enter_state(u32 state)
{
    unsigned long flags;
    int error;
    unsigned long cr4;

    if ( (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) )
        return -EINVAL;

    if ( !spin_trylock(&pm_lock) )
        return -EBUSY;

    BUG_ON(system_state != SYS_STATE_active);
    system_state = SYS_STATE_suspend;

    printk(XENLOG_INFO "Preparing system for ACPI S%d state.\n", state);

    freeze_domains();

    acpi_dmar_reinstate();

    if ( (error = disable_nonboot_cpus()) )
    {
        system_state = SYS_STATE_resume;
        goto enable_cpu;
    }

    cpufreq_del_cpu(0);

    hvm_cpu_down();

    acpi_sleep_prepare(state);

    console_start_sync();
    printk("Entering ACPI S%d state.\n", state);

    local_irq_save(flags);
    spin_debug_disable();

    if ( (error = device_power_down()) )
    {
        printk(XENLOG_ERR "Some devices failed to power down.");
        system_state = SYS_STATE_resume;
        goto done;
    }

    ACPI_FLUSH_CPU_CACHE();

    switch ( state )
    {
    case ACPI_STATE_S3:
        do_suspend_lowlevel();
        system_reset_counter++;
        error = tboot_s3_resume();
        break;
    case ACPI_STATE_S5:
        acpi_enter_sleep_state(ACPI_STATE_S5);
        break;
    default:
        error = -EINVAL;
        break;
    }

    system_state = SYS_STATE_resume;

    /* Restore CR4 and EFER from cached values. */
    cr4 = read_cr4();
    write_cr4(cr4 & ~X86_CR4_MCE);
    write_efer(read_efer());

    device_power_up();

    mcheck_init(&boot_cpu_data, 0);
    write_cr4(cr4);

    printk(XENLOG_INFO "Finishing wakeup from ACPI S%d state.\n", state);

    if ( (state == ACPI_STATE_S3) && error )
        tboot_s3_error(error);

 done:
    spin_debug_enable();
    local_irq_restore(flags);
    console_end_sync();
    acpi_sleep_post(state);
    if ( hvm_cpu_up() )
        BUG();

 enable_cpu:
    cpufreq_add_cpu(0);
    microcode_resume_cpu(0);
    rcu_barrier();
    mtrr_aps_sync_begin();
    enable_nonboot_cpus();
    mtrr_aps_sync_end();
    adjust_vtd_irq_affinities();
    acpi_dmar_zap();
    thaw_domains();
    system_state = SYS_STATE_active;
    spin_unlock(&pm_lock);
    return error;
}
Пример #4
0
/* trap handler: main entry point */
int 
__trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
{
    int rc = 0;
    unsigned long flags;

    if ( gdb_ctx->serhnd < 0 )
    {
        printk("Debugging connection not set up.\n");
        return -EBUSY;
    }

    /* We rely on our caller to ensure we're only on one processor
     * at a time... We should probably panic here, but given that
     * we're a debugger we should probably be a little tolerant of
     * things going wrong. */
    /* We don't want to use a spin lock here, because we're doing
       two distinct things:

       1 -- we don't want to run on more than one processor at a time,
            and
       2 -- we want to do something sensible if we re-enter ourselves.

       Spin locks are good for 1, but useless for 2. */
    if ( !atomic_dec_and_test(&gdb_ctx->running) )
    {
        printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n");
        atomic_inc(&gdb_ctx->running);
        return -EBUSY;
    }

    if ( !gdb_ctx->connected )
    {
        printk("GDB connection activated.\n");
        gdb_arch_print_state(regs);
        gdb_ctx->connected = 1;
    }

    gdb_smp_pause();

    local_irq_save(flags);

    watchdog_disable();
    console_start_sync();

    /* Shouldn't really do this, but otherwise we stop for no
       obvious reason, which is Bad */
    printk("Waiting for GDB to attach...\n");

    gdb_arch_enter(regs);
    gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);

    /* If gdb is already attached, tell it we've stopped again. */
    if ( gdb_ctx->currently_attached )
    {
        gdb_start_packet(gdb_ctx);
        gdb_cmd_signum(gdb_ctx);
    }

    do {
        if ( receive_command(gdb_ctx) < 0 )
        {
            dbg_printk("Error in GDB session...\n");
            rc = -EIO;
            break;
        }
    } while ( process_command(regs, gdb_ctx) == 0 );

    gdb_smp_resume();

    gdb_arch_exit(regs);
    console_end_sync();
    watchdog_enable();
    atomic_inc(&gdb_ctx->running);

    local_irq_restore(flags);

    return rc;
}
Пример #5
0
/* Bring up a remote CPU */
int __cpu_up(unsigned int cpu)
{
    int rc;
    s_time_t deadline;

    printk("Bringing up CPU%d\n", cpu);

    rc = init_secondary_pagetables(cpu);
    if ( rc < 0 )
        return rc;

    console_start_sync(); /* Secondary may use early_printk */

    /* Tell the remote CPU which stack to boot on. */
    init_data.stack = idle_vcpu[cpu]->arch.stack;

    /* Tell the remote CPU what its logical CPU ID is. */
    init_data.cpuid = cpu;

    /* Open the gate for this CPU */
    smp_up_cpu = cpu_logical_map(cpu);
    clean_dcache(smp_up_cpu);

    rc = arch_cpu_up(cpu);

    console_end_sync();

    if ( rc < 0 )
    {
        printk("Failed to bring up CPU%d\n", cpu);
        return rc;
    }

    deadline = NOW() + MILLISECS(1000);

    while ( !cpu_online(cpu) && NOW() < deadline )
    {
        cpu_relax();
        process_pending_softirqs();
    }

    /*
     * Nuke start of day info before checking one last time if the CPU
     * actually came online. If it is not online it may still be
     * trying to come up and may show up later unexpectedly.
     *
     * This doesn't completely avoid the possibility of the supposedly
     * failed CPU trying to progress with another CPUs stack settings
     * etc, but better than nothing, hopefully.
     */
    init_data.stack = NULL;
    init_data.cpuid = ~0;
    smp_up_cpu = MPIDR_INVALID;
    clean_dcache(smp_up_cpu);

    if ( !cpu_online(cpu) )
    {
        printk("CPU%d never came online\n", cpu);
        return -EIO;
    }

    return 0;
}
Пример #6
0
/* Main interface to do xen specific suspend/resume */
static int enter_state(u32 state)
{
    unsigned long flags;
    int error;

    if ( (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) )
        return -EINVAL;

    if ( !spin_trylock(&pm_lock) )
        return -EBUSY;

    printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state);

    freeze_domains();

    disable_nonboot_cpus();
    if ( num_online_cpus() != 1 )
    {
        error = -EBUSY;
        goto enable_cpu;
    }

    cpufreq_del_cpu(0);

    hvm_cpu_down();

    acpi_sleep_prepare(state);

    console_start_sync();
    printk("Entering ACPI S%d state.\n", state);

    local_irq_save(flags);
    spin_debug_disable();

    if ( (error = device_power_down()) )
    {
        printk(XENLOG_ERR "Some devices failed to power down.");
        goto done;
    }

    ACPI_FLUSH_CPU_CACHE();

    switch ( state )
    {
    case ACPI_STATE_S3:
        do_suspend_lowlevel();
        system_reset_counter++;
        error = tboot_s3_resume();
        break;
    case ACPI_STATE_S5:
        acpi_enter_sleep_state(ACPI_STATE_S5);
        break;
    default:
        error = -EINVAL;
        break;
    }

    /* Restore CR4 and EFER from cached values. */
    write_cr4(read_cr4());
    if ( cpu_has_efer )
        write_efer(read_efer());

    device_power_up();

    printk(XENLOG_INFO "Finishing wakeup from ACPI S%d state.\n", state);

    if ( (state == ACPI_STATE_S3) && error )
        panic("Memory integrity was lost on resume (%d)\n", error);

 done:
    spin_debug_enable();
    local_irq_restore(flags);
    console_end_sync();
    acpi_sleep_post(state);
    if ( !hvm_cpu_up() )
        BUG();

 enable_cpu:
    cpufreq_add_cpu(0);
    microcode_resume_cpu(0);
    enable_nonboot_cpus();
    thaw_domains();
    spin_unlock(&pm_lock);
    return error;
}
Пример #7
0
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();
}