X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/5d5c5d0d5b79ade9a973d55186ffda2638ba2b6e..935ed37a5c468c8a1c07408573c08b8b7ef80e8b:/osfmk/i386/machine_routines.c diff --git a/osfmk/i386/machine_routines.c b/osfmk/i386/machine_routines.c index de4200e6e..4ffb4ddc3 100644 --- a/osfmk/i386/machine_routines.c +++ b/osfmk/i386/machine_routines.c @@ -1,36 +1,36 @@ /* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2007 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the - * License may not be used to create, or enable the creation or - * redistribution of, unlawful or unlicensed copies of an Apple operating - * system, or to circumvent, violate, or enable the circumvention or - * violation of, any terms of an Apple operating system software license - * agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and * limitations under the License. - * - * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ + #include #include #include #include +#include #include #include #include @@ -40,11 +40,12 @@ #include #include #include -#include #include #include #include #include +#include +#include #include #if MACH_KDB #include @@ -57,23 +58,21 @@ #include #endif -#define MIN(a,b) ((a)<(b)? (a) : (b)) - #if DEBUG #define DBG(x...) kprintf("DBG: " x) #else #define DBG(x...) #endif -extern void initialize_screen(Boot_Video *, unsigned int); extern thread_t Shutdown_context(thread_t thread, void (*doshutdown)(processor_t),processor_t processor); extern void wakeup(void *); extern unsigned KernelRelocOffset; static int max_cpus_initialized = 0; -unsigned int LockTimeOut = 12500000; -unsigned int MutexSpin = 0; +unsigned int LockTimeOut; +unsigned int LockTimeOutTSC; +unsigned int MutexSpin; #define MAX_CPUS_SET 0x1 #define MAX_CPUS_WAIT 0x2 @@ -139,6 +138,12 @@ ml_static_mfree( vaddr_cur += PAGE_SIZE) { ppn = pmap_find_phys(kernel_pmap, (addr64_t)vaddr_cur); if (ppn != (vm_offset_t)NULL) { + kernel_pmap->stats.resident_count++; + if (kernel_pmap->stats.resident_count > + kernel_pmap->stats.resident_max) { + kernel_pmap->stats.resident_max = + kernel_pmap->stats.resident_count; + } pmap_remove(kernel_pmap, (addr64_t)vaddr_cur, (addr64_t)(vaddr_cur+PAGE_SIZE)); vm_page_create(ppn,(ppn+1)); vm_page_wire_count--; @@ -154,6 +159,46 @@ vm_offset_t ml_vtophys( return kvtophys(vaddr); } +/* + * Routine: ml_nofault_copy + * Function: Perform a physical mode copy if the source and + * destination have valid translations in the kernel pmap. + * If translations are present, they are assumed to + * be wired; i.e. no attempt is made to guarantee that the + * translations obtained remained valid for + * the duration of the copy process. + */ + +vm_size_t ml_nofault_copy( + vm_offset_t virtsrc, vm_offset_t virtdst, vm_size_t size) +{ + addr64_t cur_phys_dst, cur_phys_src; + uint32_t count, nbytes = 0; + + while (size > 0) { + if (!(cur_phys_src = kvtophys(virtsrc))) + break; + if (!(cur_phys_dst = kvtophys(virtdst))) + break; + if (!pmap_valid_page(i386_btop(cur_phys_dst)) || !pmap_valid_page(i386_btop(cur_phys_src))) + break; + count = PAGE_SIZE - (cur_phys_src & PAGE_MASK); + if (count > (PAGE_SIZE - (cur_phys_dst & PAGE_MASK))) + count = PAGE_SIZE - (cur_phys_dst & PAGE_MASK); + if (count > size) + count = size; + + bcopy_phys(cur_phys_src, cur_phys_dst, count); + + nbytes += count; + virtsrc += count; + virtdst += count; + size -= count; + } + + return nbytes; +} + /* Interrupt handling */ /* Initialize Interrupts */ @@ -211,12 +256,9 @@ void ml_cause_interrupt(void) void ml_thread_policy( thread_t thread, - unsigned policy_id, +__unused unsigned policy_id, unsigned policy_info) { - if (policy_id == MACHINE_GROUP) - thread_bind(thread, master_processor); - if (policy_info & MACHINE_NETWORK_WORKLOOP) { spl_t s = splsched(); @@ -246,14 +288,15 @@ void ml_install_interrupt_handler( (void) ml_set_interrupts_enabled(current_state); - initialize_screen(0, kPEAcquireScreen); + initialize_screen(NULL, kPEAcquireScreen); } void machine_idle(void) { - cpu_core_t *my_core = cpu_core(); + x86_core_t *my_core = x86_core(); + cpu_data_t *my_cpu = current_cpu_datap(); int others_active; /* @@ -263,18 +306,23 @@ machine_idle(void) * core doesn't go into a low-power mode. * For 4/4, we set a null "active cr3" while idle. */ + if (my_core == NULL || my_cpu == NULL) + goto out; + others_active = !atomic_decl_and_test( - (long *) &my_core->active_threads, 1); + (long *) &my_core->active_lcpus, 1); + my_cpu->lcpu.idle = TRUE; if (idlehalt || others_active) { DBGLOG(cpu_handle, cpu_number(), MP_IDLE); MARK_CPU_IDLE(cpu_number()); - machine_idle_cstate(); + machine_idle_cstate(FALSE); MARK_CPU_ACTIVE(cpu_number()); DBGLOG(cpu_handle, cpu_number(), MP_UNIDLE); - } else { - __asm__ volatile("sti"); } - atomic_incl((long *) &my_core->active_threads, 1); + my_cpu->lcpu.idle = FALSE; + atomic_incl((long *) &my_core->active_lcpus, 1); + out: + __asm__ volatile("sti"); } void @@ -286,11 +334,12 @@ machine_signal_idle( thread_t machine_processor_shutdown( - thread_t thread, - void (*doshutdown)(processor_t), - processor_t processor) + thread_t thread, + void (*doshutdown)(processor_t), + processor_t processor) { - fpu_save_context(thread); + vmx_suspend(); + fpu_save_context(thread); return(Shutdown_context(thread, doshutdown, processor)); } @@ -327,7 +376,11 @@ ml_processor_register( goto failed; if (!boot_cpu) { - this_cpu_datap->cpu_core = cpu_thread_alloc(target_cpu); + this_cpu_datap->lcpu.core = cpu_thread_alloc(this_cpu_datap->cpu_number); + if (this_cpu_datap->lcpu.core == NULL) + goto failed; + + pmCPUStateInit(); this_cpu_datap->cpu_pmap = pmap_cpu_alloc(boot_cpu); if (this_cpu_datap->cpu_pmap == NULL) @@ -336,12 +389,25 @@ ml_processor_register( this_cpu_datap->cpu_processor = cpu_processor_alloc(boot_cpu); if (this_cpu_datap->cpu_processor == NULL) goto failed; - processor_init(this_cpu_datap->cpu_processor, target_cpu); + /* + * processor_init() deferred to topology start + * because "slot numbers" a.k.a. logical processor numbers + * are not yet finalized. + */ } *processor_out = this_cpu_datap->cpu_processor; *ipi_handler = NULL; + if (target_cpu == machine_info.max_cpus - 1) { + /* + * All processors are now registered but not started (except + * for this "in-limbo" boot processor). We call to the machine + * topology code to finalize and activate the topology. + */ + cpu_topology_start(); + } + return KERN_SUCCESS; failed: @@ -366,7 +432,11 @@ ml_cpu_get_info(ml_cpu_info_t *cpu_infop) * As distinct from whether the cpu has these capabilities. */ os_supports_sse = get_cr4() & CR4_XMM; - if ((cpuid_features() & CPUID_FEATURE_MNI) && os_supports_sse) + if ((cpuid_features() & CPUID_FEATURE_SSE4_2) && os_supports_sse) + cpu_infop->vector_unit = 8; + else if ((cpuid_features() & CPUID_FEATURE_SSE4_1) && os_supports_sse) + cpu_infop->vector_unit = 7; + else if ((cpuid_features() & CPUID_FEATURE_SSSE3) && os_supports_sse) cpu_infop->vector_unit = 6; else if ((cpuid_features() & CPUID_FEATURE_SSE3) && os_supports_sse) cpu_infop->vector_unit = 5; @@ -412,7 +482,7 @@ ml_init_max_cpus(unsigned long max_cpus) if (max_cpus_initialized != MAX_CPUS_SET) { if (max_cpus > 0 && max_cpus <= MAX_CPUS) { /* - * Note: max_cpus is the number of enable processors + * Note: max_cpus is the number of enabled processors * that ACPI found; max_ncpus is the maximum number * that the kernel supports or that the "cpus=" * boot-arg has set. Here we take int minimum. @@ -451,13 +521,10 @@ ml_init_lock_timeout(void) uint64_t abstime; uint32_t mtxspin; - /* - * XXX As currently implemented for x86, LockTimeOut should be a - * cycle (tsc) count not an absolute time (nanoseconds) - - * but it's of the right order. - */ + /* LockTimeOut is absolutetime, LockTimeOutTSC is in TSC ticks */ nanoseconds_to_absolutetime(NSEC_PER_SEC>>2, &abstime); - LockTimeOut = (unsigned int)abstime; + LockTimeOut = (uint32_t) abstime; + LockTimeOutTSC = (uint32_t) tmrCvt(abstime, tscFCvtn2t); if (PE_parse_boot_arg("mtxspin", &mtxspin)) { if (mtxspin > USEC_PER_SEC>>4) @@ -489,29 +556,6 @@ ml_cpu_down(void) return; } -/* Stubs for pc tracing mechanism */ - -int *pc_trace_buf; -int pc_trace_cnt = 0; - -int -set_be_bit(void) -{ - return(0); -} - -int -clr_be_bit(void) -{ - return(0); -} - -int -be_tracing(void) -{ - return(0); -} - /* * The following are required for parts of the kernel * that cannot resolve these functions as inlines: @@ -531,52 +575,6 @@ current_thread(void) return(current_thread_fast()); } -/* - * Set the worst-case time for the C4 to C2 transition. - * The maxdelay parameter is in nanoseconds. - */ - -void -ml_set_maxsnoop(uint32_t maxdelay) -{ - C4C2SnoopDelay = maxdelay; /* Set the transition time */ - machine_nap_policy(); /* Adjust the current nap state */ -} - - -/* - * Get the worst-case time for the C4 to C2 transition. Returns nanoseconds. - */ - -unsigned -ml_get_maxsnoop(void) -{ - return C4C2SnoopDelay; /* Set the transition time */ -} - - -uint32_t -ml_get_maxbusdelay(void) -{ - return maxBusDelay; -} - -/* - * Set the maximum delay time allowed for snoop on the bus. - * - * Note that this value will be compared to the amount of time that it takes - * to transition from a non-snooping power state (C4) to a snooping state (C2). - * If maxBusDelay is less than C4C2SnoopDelay, - * we will not enter the lowest power state. - */ - -void -ml_set_maxbusdelay(uint32_t mdelay) -{ - maxBusDelay = mdelay; /* Set the delay */ - machine_nap_policy(); /* Adjust the current nap state */ -} - boolean_t ml_is64bit(void) { @@ -620,6 +618,12 @@ void ml_fp_setvalid(boolean_t value) fp_setvalid(value); } +uint64_t ml_cpu_int_event_time(void) +{ + return current_cpu_datap()->cpu_int_event_time; +} + + #if MACH_KDB /*