diff options
Diffstat (limited to 'memtestEDK/Memtest/SingleComponents/smp.c')
-rw-r--r-- | memtestEDK/Memtest/SingleComponents/smp.c | 700 |
1 files changed, 0 insertions, 700 deletions
diff --git a/memtestEDK/Memtest/SingleComponents/smp.c b/memtestEDK/Memtest/SingleComponents/smp.c deleted file mode 100644 index aecefc1..0000000 --- a/memtestEDK/Memtest/SingleComponents/smp.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * MemTest86+ V5 Specific code (GPL V2.0) - * By Samuel DEMEULEMEESTER, sdemeule@memtest.org - * http://www.canardpc.com - http://www.memtest.org - * ------------------------------------------------ - * smp.c - MemTest-86 Version 3.5 - * - * Released under version 2 of the Gnu Public License. - * By Chris Brady - */ - -#include <Library/UefiLib.h> - - -#include "stddef.h" -#include "stdint.h" -#include "cpuid.h" -#include "smp.h" -#include "test.h" -#include "environment.h" - -#define DELAY_FACTOR 1 -unsigned num_cpus = 1; // There is at least one cpu, the BSP -int act_cpus; -unsigned found_cpus = 0; - -extern void memcpy(void *dst, void *src , int len); -extern void test_start(void); -extern int run_cpus; -extern int maxcpus; -extern char cpu_mask[]; -extern struct cpu_ident cpu_id; - -struct barrier_s *barr; - -void smp_find_cpus(); - -void barrier_init(int max) -{ - /* Set the adddress of the barrier structure */ - barr = (struct barrier_s *)0x9ff00; - barr->lck.slock = 1; - barr->mutex.slock = 1; - barr->maxproc = max; - barr->count = max; - barr->st1.slock = 1; - barr->st2.slock = 0; -} - -void s_barrier_init(int max) -{ - barr->s_lck.slock = 1; - barr->s_maxproc = max; - barr->s_count = max; - barr->s_st1.slock = 1; - barr->s_st2.slock = 0; -} - -void barrier() -{ - if (num_cpus == 1 || vv->fail_safe & 3) { - return; - } - spin_wait(&barr->st1); /* Wait if the barrier is active */ - spin_lock(&barr->lck); /* Get lock for barr struct */ - if (--barr->count == 0) { /* Last process? */ - barr->st1.slock = 0; /* Hold up any processes re-entering */ - barr->st2.slock = 1; /* Release the other processes */ - barr->count++; - spin_unlock(&barr->lck); - } else { - spin_unlock(&barr->lck); - spin_wait(&barr->st2); /* wait for peers to arrive */ - spin_lock(&barr->lck); - if (++barr->count == barr->maxproc) { - barr->st1.slock = 1; - barr->st2.slock = 0; - } - spin_unlock(&barr->lck); - } -} - -void s_barrier() -{ - if (run_cpus == 1 || vv->fail_safe & 3) { - return; - } - spin_wait(&barr->s_st1); /* Wait if the barrier is active */ - spin_lock(&barr->s_lck); /* Get lock for barr struct */ - if (--barr->s_count == 0) { /* Last process? */ - barr->s_st1.slock = 0; /* Hold up any processes re-entering */ - barr->s_st2.slock = 1; /* Release the other processes */ - barr->s_count++; - spin_unlock(&barr->s_lck); - } else { - spin_unlock(&barr->s_lck); - spin_wait(&barr->s_st2); /* wait for peers to arrive */ - spin_lock(&barr->s_lck); - if (++barr->s_count == barr->s_maxproc) { - barr->s_st1.slock = 1; - barr->s_st2.slock = 0; - } - spin_unlock(&barr->s_lck); - } -} - -typedef struct { - bool started; -} ap_info_t; - -volatile apic_register_t *APIC = NULL; -/* CPU number to APIC ID mapping table. CPU 0 is the BSP. */ -static unsigned cpu_num_to_apic_id[MAX_CPUS]; -volatile ap_info_t AP[MAX_CPUS]; - -void PUT_MEM16(uintptr_t addr, uint16_t val) -{ - *((volatile uint16_t *)(MAX_BLOCK_SIZE)addr) = val; -} - -void PUT_MEM32(uintptr_t addr, uint32_t val) -{ - *((volatile uint32_t *)(MAX_BLOCK_SIZE)addr) = val; -} - -static void inline -APIC_WRITE(unsigned reg, uint32_t val) -{ - APIC[reg][0] = val; -} - -static inline uint32_t -APIC_READ(unsigned reg) -{ - return APIC[reg][0]; -} - - -static void -SEND_IPI(unsigned apic_id, unsigned trigger, unsigned level, unsigned mode, - uint8_t vector) -{ - uint32_t v; - - v = APIC_READ(APICR_ICRHI) & 0x00ffffff; - APIC_WRITE(APICR_ICRHI, v | (apic_id << 24)); - - v = APIC_READ(APICR_ICRLO) & ~0xcdfff; - v |= (APIC_DEST_DEST << APIC_ICRLO_DEST_OFFSET) - | (trigger << APIC_ICRLO_TRIGGER_OFFSET) - | (level << APIC_ICRLO_LEVEL_OFFSET) - | (mode << APIC_ICRLO_DELMODE_OFFSET) - | (vector); - APIC_WRITE(APICR_ICRLO, v); -} - - -// Silly way of busywaiting, but we don't have a timer -void delay(unsigned us) -{ - unsigned freq = 1000; // in MHz, assume 1GHz CPU speed - uint64_t cycles = us * freq; - uint64_t t0 = RDTSC(); - uint64_t t1; - volatile unsigned k; - - do { - for (k = 0; k < 1000; k++) continue; - t1 = RDTSC(); - } while (t1 - t0 < cycles); -} - -static inline void -memset (volatile void *dst, - char value, - int len) -{ - int i; - for (i = 0 ; i < len ; i++ ) { - *((char *) dst + i) = value; - } -} -void initialise_cpus(void) -{ - int i; - - act_cpus = 0; - - if (maxcpus > 1) { - smp_find_cpus(); - /* The total number of CPUs may be limited */ - if (num_cpus > maxcpus) { - num_cpus = maxcpus; - } - /* Determine how many cpus have been selected */ - for(i = 0; i < num_cpus; i++) { - if (cpu_mask[i]) { - act_cpus++; - } - } - } else { - act_cpus = found_cpus = num_cpus = 1; - } - - /* Initialize the barrier before starting AP's */ - barrier_init(act_cpus); - - /* let the BSP initialise the APs. */ - for(i = 1; i < num_cpus; i++) { - /* Only start this CPU if it is selected by the mask */ - if (cpu_mask[i]) { - smp_boot_ap(i); - } - } - -} -void kick_cpu(unsigned cpu_num) -{ - unsigned num_sipi, apic_id; - apic_id = cpu_num_to_apic_id[cpu_num]; - - // clear the APIC ESR register - APIC_WRITE(APICR_ESR, 0); - APIC_READ(APICR_ESR); - - // asserting the INIT IPI - SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0); - delay(100000 / DELAY_FACTOR); - - // de-assert the INIT IPI - SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0); - - for (num_sipi = 0; num_sipi < 2; num_sipi++) { - unsigned timeout; - bool send_pending; - unsigned err; - - APIC_WRITE(APICR_ESR, 0); - - SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (unsigned)(MAX_BLOCK_SIZE)startup_32 >> 12); - - timeout = 0; - do { - delay(10); - timeout++; - send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0; - } while (send_pending && timeout < 1000); - - if (send_pending) { - cprint(LINE_STATUS+3, 0, "SMP: STARTUP IPI was never sent"); - } - - delay(100000 / DELAY_FACTOR); - - err = APIC_READ(APICR_ESR) & 0xef; - if (err) { - cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x"); - hprint(LINE_STATUS+3, COL_MID, err); - } - } -} - -// These memory locations are used for the trampoline code and data. - -#define BOOTCODESTART 0x9000 -#define GDTPOINTERADDR 0x9100 -#define GDTADDR 0x9110 - -void boot_ap(unsigned cpu_num) -{ - unsigned num_sipi, apic_id; - extern uint8_t gdt; - extern uint8_t _ap_trampoline_start; - extern uint8_t _ap_trampoline_protmode; - unsigned len = &_ap_trampoline_protmode - &_ap_trampoline_start; - apic_id = cpu_num_to_apic_id[cpu_num]; - - - memcpy((uint8_t*)BOOTCODESTART, &_ap_trampoline_start, len); - - // Fixup the LGDT instruction to point to GDT pointer. - PUT_MEM16(BOOTCODESTART + 3, GDTPOINTERADDR); - - // Copy a pointer to the temporary GDT to addr GDTPOINTERADDR. - // The temporary gdt is at addr GDTADDR - PUT_MEM16(GDTPOINTERADDR, 4 * 8); - PUT_MEM32(GDTPOINTERADDR + 2, GDTADDR); - - // Copy the first 4 gdt entries from the currently used GDT to the - // temporary GDT. - memcpy((uint8_t *)GDTADDR, &gdt, 32); - - // clear the APIC ESR register - APIC_WRITE(APICR_ESR, 0); - APIC_READ(APICR_ESR); - - // asserting the INIT IPI - SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0); - delay(100000 / DELAY_FACTOR); - - // de-assert the INIT IPI - SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0); - - for (num_sipi = 0; num_sipi < 2; num_sipi++) { - unsigned timeout; - bool send_pending; - unsigned err; - - APIC_WRITE(APICR_ESR, 0); - - SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, BOOTCODESTART >> 12); - - timeout = 0; - do { - delay(10); - timeout++; - send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0; - } while (send_pending && timeout < 1000); - - if (send_pending) { - cprint(LINE_STATUS+3, 0, "SMP: STARTUP IPI was never sent"); - } - - delay(100000 / DELAY_FACTOR); - - err = APIC_READ(APICR_ESR) & 0xef; - if (err) { - cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x"); - hprint(LINE_STATUS+3, COL_MID, err); - } - } -} - -static int checksum(unsigned char *mp, int len) -{ - int sum = 0; - - while (len--) { - sum += *mp++; - } - return (sum & 0xFF); -} - -/* Parse an MP config table for CPU information */ -bool read_mp_config_table(uintptr_t addr) -{ - mp_config_table_header_t *mpc = (mp_config_table_header_t*)(MAX_BLOCK_SIZE)addr; - uint8_t *tab_entry_ptr; - uint8_t *mpc_table_end; - - if (mpc->signature != MPCSignature) { - return FALSE; - } - if (checksum((unsigned char*)mpc, mpc->length) != 0) { - return FALSE; - } - - /* FIXME: the uintptr_t cast here works around a compilation problem on - * AMD64, but it ignores the real problem, which is that lapic_addr - * is only 32 bits. Maybe that's OK, but it should be investigated. - */ - APIC = (volatile apic_register_t*)(MAX_BLOCK_SIZE)(uintptr_t)mpc->lapic_addr; - - tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t); - mpc_table_end = ((uint8_t*)mpc) + mpc->length; - - while (tab_entry_ptr < mpc_table_end) { - switch (*tab_entry_ptr) { - case MP_PROCESSOR: { - mp_processor_entry_t *pe = (mp_processor_entry_t*)tab_entry_ptr; - - if (pe->cpu_flag & CPU_BOOTPROCESSOR) { - // BSP is CPU 0 - cpu_num_to_apic_id[0] = pe->apic_id; - } else if (num_cpus < MAX_CPUS) { - cpu_num_to_apic_id[num_cpus] = pe->apic_id; - num_cpus++; - } - found_cpus++; - - // we cannot handle non-local 82489DX apics - if ((pe->apic_ver & 0xf0) != 0x10) { - return 0; - } - - tab_entry_ptr += sizeof(mp_processor_entry_t); - break; - } - case MP_BUS: { - tab_entry_ptr += sizeof(mp_bus_entry_t); - break; - } - case MP_IOAPIC: { - tab_entry_ptr += sizeof(mp_io_apic_entry_t); - break; - } - case MP_INTSRC: - tab_entry_ptr += sizeof(mp_interrupt_entry_t); - break; - case MP_LINTSRC: - tab_entry_ptr += sizeof(mp_local_interrupt_entry_t); - break; - default: - return FALSE; - } - } - return TRUE; -} - -/* Search for a Floating Pointer structure */ -floating_pointer_struct_t * -scan_for_floating_ptr_struct(uintptr_t addr, uint32_t length) -{ - floating_pointer_struct_t *fp; - uintptr_t end = addr + length; - - - while ((uintptr_t)addr < end) { - fp = (floating_pointer_struct_t*)(MAX_BLOCK_SIZE)addr; - if (*(unsigned int *)(MAX_BLOCK_SIZE)addr == FPSignature && fp->length == 1 - && checksum((unsigned char*)(MAX_BLOCK_SIZE)addr, 16) == 0 - && ((fp->spec_rev == 1) || (fp->spec_rev == 4))) { - return fp; - } - addr += 4; - } - return NULL; -} - -/* Search for a Root System Descriptor Pointer */ -rsdp_t *scan_for_rsdp(uintptr_t addr, uint32_t length) -{ - rsdp_t *rp; - uintptr_t end = addr + length; - - - while ((uintptr_t)addr < end) { - rp = (rsdp_t*)(MAX_BLOCK_SIZE)addr; - if (*(unsigned int *)(MAX_BLOCK_SIZE)addr == RSDPSignature && - checksum((unsigned char*)(MAX_BLOCK_SIZE)addr, rp->length) == 0) { - return rp; - } - addr += 4; - } - return NULL; -} - -/* Parse a MADT table for processor entries */ -int parse_madt(uintptr_t addr) { - - mp_config_table_header_t *mpc = (mp_config_table_header_t*)(MAX_BLOCK_SIZE)addr; - uint8_t *tab_entry_ptr; - uint8_t *mpc_table_end; - - if (checksum((unsigned char*)mpc, mpc->length) != 0) { - return FALSE; - } - - APIC = (volatile apic_register_t*)(MAX_BLOCK_SIZE)(uintptr_t)mpc->lapic_addr; - - tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t); - mpc_table_end = ((uint8_t*)mpc) + mpc->length; - while (tab_entry_ptr < mpc_table_end) { - - madt_processor_entry_t *pe = (madt_processor_entry_t*)tab_entry_ptr; - if (pe->type == MP_PROCESSOR) { - if (pe->enabled) { - if (num_cpus < MAX_CPUS) { - cpu_num_to_apic_id[num_cpus] = pe->apic_id; - - /* the first CPU is the BSP, don't increment */ - if (found_cpus) { - num_cpus++; - } - } - found_cpus++; - } - } - tab_entry_ptr += pe->length; - } - return TRUE; -} - -/* This is where we search for SMP information in the following order - * look for a floating MP pointer - * found: - * check for a default configuration - * found: - * setup config, return - * check for a MP config table - * found: - * validate: - * good: - * parse the MP config table - * good: - * setup config, return - * - * find & validate ACPI RSDP (Root System Descriptor Pointer) - * found: - * find & validate RSDT (Root System Descriptor Table) - * found: - * find & validate MSDT - * found: - * parse the MADT table - * good: - * setup config, return - */ -void smp_find_cpus() -{ - floating_pointer_struct_t *fp; - rsdp_t *rp; - rsdt_t *rt; - uint8_t *tab_ptr, *tab_end; - unsigned int *ptr; - unsigned int uiptr; - - Print(L"fail_safe: %d\n", vv->fail_safe); - - if(vv->fail_safe & 3) { return; } - - memset(&AP, 0, sizeof AP); - - if(vv->fail_safe & 8) - { - // Search for the Floating MP structure pointer - fp = scan_for_floating_ptr_struct(0x0, 0x400); - if (fp == NULL) { - fp = scan_for_floating_ptr_struct(639*0x400, 0x400); - } - if (fp == NULL) { - fp = scan_for_floating_ptr_struct(0xf0000, 0x10000); - } - if (fp == NULL) { - // Search the BIOS ESDS area - unsigned int address = *(unsigned short *)0x40E; - address <<= 4; - if (address) { - fp = scan_for_floating_ptr_struct(address, 0x400); - } - } - - if (fp != NULL) { - // We have a floating MP pointer - // Is this a default configuration? - - if (fp->feature[0] > 0 && fp->feature[0] <=7) { - // This is a default config so plug in the numbers - num_cpus = 2; - APIC = (volatile apic_register_t*)0xFEE00000; - cpu_num_to_apic_id[0] = 0; - cpu_num_to_apic_id[1] = 1; - return; - } - - // Do we have a pointer to a MP configuration table? - if ( fp->phys_addr != 0) { - if (read_mp_config_table(fp->phys_addr)) { - // Found a good MP table, done - return; - } - } - } - } - - - /* No MP table so far, try to find an ACPI MADT table - * We try to use the MP table first since there is no way to distinguish - * real cores from hyper-threads in the MADT */ - - /* Search for the RSDP */ - rp = scan_for_rsdp(0xE0000, 0x20000); - if (rp == NULL) { - /* Search the BIOS ESDS area */ - unsigned int address = *(unsigned short *)0x40E; - address <<= 4; - if (address) { - rp = scan_for_rsdp(address, 0x400); - } - } - - if (rp == NULL) { - /* RSDP not found, give up */ - return; - } - - /* Found the RSDP, now get either the RSDT or XSDT */ - if (rp->revision >= 2) { - rt = (rsdt_t *)(MAX_BLOCK_SIZE)rp->xrsdt[0]; - - if (rt == 0) { - return; - } - // Validate the XSDT - if (*(unsigned int *)rt != XSDTSignature) { - return; - } - if ( checksum((unsigned char*)rt, rt->length) != 0) { - return; - } - - } else { - rt = (rsdt_t *)(MAX_BLOCK_SIZE)rp->rsdt; - if (rt == 0) { - return; - } - /* Validate the RSDT */ - if (*(unsigned int *)rt != RSDTSignature) { - return; - } - if ( checksum((unsigned char*)rt, rt->length) != 0) { - return; - } - } - - /* Scan the RSDT or XSDT for a pointer to the MADT */ - tab_ptr = ((uint8_t*)rt) + sizeof(rsdt_t); - tab_end = ((uint8_t*)rt) + rt->length; - - while (tab_ptr < tab_end) { - - uiptr = *((unsigned int *)tab_ptr); - ptr = (unsigned int *)(MAX_BLOCK_SIZE)uiptr; - - /* Check for the MADT signature */ - if (ptr && *ptr == MADTSignature) { - /* Found it, now parse it */ - if (parse_madt((uintptr_t)(MAX_BLOCK_SIZE)ptr)) { - return; - } - } - tab_ptr += 4; - } -} - -unsigned my_apic_id() -{ - return (APIC[APICR_ID][0]) >> 24; -} - -void smp_ap_booted(unsigned cpu_num) -{ - AP[cpu_num].started = TRUE; -} - -void smp_boot_ap(unsigned cpu_num) -{ - unsigned timeout; - - boot_ap(cpu_num); - timeout = 0; - do { - delay(1000 / DELAY_FACTOR); - timeout++; - } while (!AP[cpu_num].started && timeout < 100000 / DELAY_FACTOR); - - if (!AP[cpu_num].started) { - cprint(LINE_STATUS+3, 0, "SMP: Boot timeout for"); - dprint(LINE_STATUS+3, COL_MID, cpu_num,2,1); - cprint(LINE_STATUS+3, 26, "Turning off SMP"); - } -} - -unsigned smp_my_cpu_num() -{ - unsigned apicid = my_apic_id(); - unsigned i; - - for (i = 0; i < MAX_CPUS; i++) { - if (apicid == cpu_num_to_apic_id[i]) { - break; - } - } - if (i == MAX_CPUS) { - i = 0; - } - return i; -} - -/* A set of simple functions used to preserve assigned CPU ordinals since - * they are lost after relocation (the stack is reloaded). - */ -int num_to_ord[MAX_CPUS]; -void smp_set_ordinal(int me, int ord) -{ - num_to_ord[me] = ord; -} - -int smp_my_ord_num(int me) -{ - return num_to_ord[me]; -} - -int smp_ord_to_cpu(int me) -{ - int i; - for (i=0; i<MAX_CPUS; i++) { - if (num_to_ord[i] == me) return i; - } - return -1; -} |