From b7084442324199e2691f822d6a08dc865f521be1 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 10 Oct 2002 19:02:37 +0000 Subject: [PATCH] src/arch/i386/boot/boot.c - Tone down the severity of error messages src/arch/i386/lib/console.inc - Preserve morre registers in __CONSOLE_INLINE_TX_HEX8 src/arch/i386/lib/hardwaremain.c - Fixup the cmos option to handle multiple cpus - Move pci setup before ramsize initialization - Renable keyboard_on src/arch/i386/smp/Config Add secondary.S src/arch/i386/smp/secondary.S - add src/arch/i386/smp/secondary.inc - remove src/arch/i386/smp/start_stop.c - Remove unused variables src/config/Config - Cleanup the cross compiling options - Rename cmos.conf cmos.layout as the previous name was too confusing src/cpu/p6/mtrr.c - Create subroutines to enable/disable caching - Call them in all of the appropriate places - Add an extra argument to range_to_mtrr to allow for future optimizations --- src/arch/i386/boot/boot.c | 14 +++--- src/arch/i386/lib/console.inc | 25 +++-------- src/arch/i386/lib/hardwaremain.c | 42 +++++++++--------- src/arch/i386/smp/Config | 2 + src/arch/i386/smp/secondary.S | 76 ++++++++++++++++++++++++++++++++ src/arch/i386/smp/start_stop.c | 2 - src/config/Config | 11 +++-- src/cpu/p6/mtrr.c | 69 ++++++++++++++++------------- 8 files changed, 154 insertions(+), 87 deletions(-) create mode 100644 src/arch/i386/smp/secondary.S diff --git a/src/arch/i386/boot/boot.c b/src/arch/i386/boot/boot.c index bbcc1f7206..730ab2aedc 100644 --- a/src/arch/i386/boot/boot.c +++ b/src/arch/i386/boot/boot.c @@ -85,13 +85,13 @@ void jmp_to_elf_entry(void *entry, unsigned long buffer) adjusted_boot_notes = (unsigned long)&elf_boot_notes; adjusted_boot_notes += adjust; - printk_info("entry = 0x%08lx\n", (unsigned long)entry); - printk_info("lb_start = 0x%08lx\n", lb_start); - printk_info("lb_size = 0x%08lx\n", lb_size); - printk_info("adjust = 0x%08lx\n", adjust); - printk_info("buffer = 0x%08lx\n", buffer); - printk_info(" elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes); - printk_info("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes); + printk_spew("entry = 0x%08lx\n", (unsigned long)entry); + printk_spew("lb_start = 0x%08lx\n", lb_start); + printk_spew("lb_size = 0x%08lx\n", lb_size); + printk_spew("adjust = 0x%08lx\n", adjust); + printk_spew("buffer = 0x%08lx\n", buffer); + printk_spew(" elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes); + printk_spew("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes); /* Jump to kernel */ __asm__ __volatile__( diff --git a/src/arch/i386/lib/console.inc b/src/arch/i386/lib/console.inc index 985d414460..c673cb6e95 100644 --- a/src/arch/i386/lib/console.inc +++ b/src/arch/i386/lib/console.inc @@ -42,7 +42,8 @@ console_test: /* uses: byte, ax, dx */ #define __CONSOLE_INLINE_TX_HEX8(byte) \ - mov byte, %al ; \ + movb byte, %dl ; \ + shll $16, %edx ; \ shr $4, %al ; \ add $'0', %al ; \ cmp $'9', %al ; \ @@ -50,7 +51,8 @@ console_test: add $39, %al ; \ 9: ; \ __CONSOLE_INLINE_TX_AL ; \ - mov byte, %al ; \ + shrl $16, %edx ; \ + movb %dl, %al ; \ and $0x0f, %al ; \ add $'0', %al ; \ cmp $'9', %al ; \ @@ -423,24 +425,7 @@ console_tx_al: /* uses: esp, ax, edx */ console_tx_hex8: - movb %al, %dl - shll $16, %edx - shr $4, %al - add $'0', %al - cmp $'9', %al - jle 9f - add $39, %al -9: - __CONSOLE_INLINE_TX_AL - shrl $16, %edx - movb %dl, %al - and $0x0f, %al - add $'0', %al - cmp $'9', %al - jle 9f - add $39, %al -9: - __CONSOLE_INLINE_TX_AL + __CONSOLE_INLINE_TX_HEX8(%al) RETSP diff --git a/src/arch/i386/lib/hardwaremain.c b/src/arch/i386/lib/hardwaremain.c index e1bb377719..850617eff0 100644 --- a/src/arch/i386/lib/hardwaremain.c +++ b/src/arch/i386/lib/hardwaremain.c @@ -153,8 +153,7 @@ static void wait_for_other_cpus(void) old_active_count = 1; active_count = atomic_read(&active_cpus); - - while (active_count > 1) { + while(active_count > 1) { if (active_count != old_active_count) { printk_info("Waiting for %d CPUS to stop\n", active_count); old_active_count = active_count; @@ -180,15 +179,16 @@ static void remove_logical_cpus(void) /* To turn off hyperthreading just remove the logical * cpus from the processor map. */ - int cnt; - cnt=0; - if (get_option(&cnt,"logical_cpus")==0) { - if (cnt) { + int disable_logical_cpus = !CONFIG_LOGICAL_CPUS; + if (get_option(&disable_logical_cpus,"hyper_threading")) { + disable_logical_cpus = !CONFIG_LOGICAL_CPUS; + } + if (disable_logical_cpus) { /* disable logical cpus */ - for(cnt=MAX_PHYSICAL_CPUS;cnt +#include +#include +#include + .text + .globl _secondary_start + .balign 4096 +_secondary_start: + .code16 + cli + xorl %eax, %eax + movl %eax, %cr3 /* Invalidate TLB*/ + + /* On hyper threaded cpus invalidating the cache here is + * very very bad. Don't. + */ + + /* setup the data segment */ + movw %cs, %ax + movw %ax, %ds + + data32 lgdt gdtaddr - _secondary_start + + movl %cr0, %eax + andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ + orl $0x60000001, %eax /* CD, NW, PE = 1 */ + movl %eax, %cr0 + + ljmpl $0x10, $1f +1: + .code32 + movw $0x18, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + /* Enable the local apic, and map it where we expext it */ + movl $APIC_BASE_MSR, %ecx + rdmsr + orl $APIC_BASE_MSR_ENABLE, %eax + andl $(~APIC_BASE_MSR_ADDR_MASK), %eax + orl $APIC_DEFAULT_BASE, %eax + wrmsr + + /* Get the apic_id */ + movl (APIC_ID + APIC_DEFAULT_BASE), %edi + shrl $24, %edi + + /* Get the cpu index (MAX_CPUS on error) */ + movl $-4, %ebx +1: addl $4, %ebx + cmpl $(MAX_CPUS << 2), %ebx + je 2 + cmpl %edi, EXT(initial_apicid)(%ebx) + jne 1b +2: shrl $2, %ebx + + /* set the stack pointer */ + movl $_estack, %esp + movl %ebx, %eax + movl $STACK_SIZE, %ebx + mull %ebx + subl %eax, %esp + + call EXT(secondary_cpu_init) +1: hlt + jmp 1b + +gdtaddr: + .word gdt_limit /* the table limit */ + .long gdt /* we know the offset */ + + +.code32 diff --git a/src/arch/i386/smp/start_stop.c b/src/arch/i386/smp/start_stop.c index 5da316f098..e03ea56e81 100644 --- a/src/arch/i386/smp/start_stop.c +++ b/src/arch/i386/smp/start_stop.c @@ -88,8 +88,6 @@ int start_cpu(unsigned long apicid) int timeout; unsigned long send_status, accept_status, start_eip; int j, num_starts, maxlvt; - //extern char _start[], _estart[]; - //extern char reboot_halt[]; extern char _secondary_start[]; /* diff --git a/src/config/Config b/src/config/Config index 32c4c3f19a..6a3ae15b69 100644 --- a/src/config/Config +++ b/src/config/Config @@ -2,18 +2,17 @@ option LINUXBIOS_VERSION=1.0.0 -option CROSS_COMPILE= +option CC=$(CROSS_COMPILE)gcc +option HOSTCC=$(CROSS_COMPILE)gcc +option OBJCOPY=objcopy -makedefine CC:=$(CROSS_COMPILE)gcc -makedefine CPP:= $(CROSS_COMPILE)gcc -x assembler-with-cpp -DASSEMBLY -E -makedefine OBJCOPY:=$(CROSS_COMPILE)objcopy +makedefine CPP:= $(CC) -x assembler-with-cpp -DASSEMBLY -E makedefine LIBGCC_FILE_NAME := $(shell $(CC) -print-libgcc-file-name) makedefine GCC_INC_DIR := $(shell $(CC) -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp") makedefine CPPFLAGS := -I$(TOP)/src/include -I$(TOP)/src/arch/$(ARCH)/include -I$(GCC_INC_DIR) $(CPUFLAGS) makedefine CFLAGS := $(CPU_OPT) $(CPPFLAGS) -Os -nostdinc -nostdlib -fno-builtin -Wall -makedefine HOSTCC:=gcc makedefine HOSTCFLAGS:= -Os -Wall option LINUXBIOS_BUILD = $(shell date) @@ -60,7 +59,7 @@ makerule documentation: $(SOURCES) ; doxygen LinuxBIOSDoc.config makerule build_opt_tbl: $(TOP)/util/options/build_opt_tbl.c ; $(HOSTCC) $(HOSTCFLAGS) $< -o $@ -makerule /$(TARGET_DIR)/option_table.c : build_opt_tbl $(MAINBOARD)/cmos.conf ; ./build_opt_tbl -b --config $(MAINBOARD)/cmos.conf +makerule /$(TARGET_DIR)/option_table.c : build_opt_tbl $(MAINBOARD)/cmos.layout ; ./build_opt_tbl -b --config $(MAINBOARD)/cmos.layout object /$(TARGET_DIR)/option_table.o HAVE_OPTION_TABLE diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c index de1af8650c..de02884fd3 100644 --- a/src/cpu/p6/mtrr.c +++ b/src/cpu/p6/mtrr.c @@ -63,11 +63,36 @@ static void intel_enable_var_mtrr(void) wrmsr(MTRRdefType_MSR, low, high); } +static inline void disable_cache(void) +{ + unsigned int tmp; + /* Disable cache */ + /* Write back the cache and flush TLB */ + asm volatile ( + "movl %%cr0, %0\n\t" + "orl $0x40000000, %0\n\t" + "wbinvd\n\t" + "movl %0, %%cr0\n\t" + "wbinvd\n\t" + :"=r" (tmp) + ::"memory"); +} + +static inline void enable_cache(void) +{ + unsigned int tmp; + // turn cache back on. + asm volatile ( + "movl %%cr0, %0\n\t" + "andl $0x9fffffff, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (tmp) + ::"memory"); +} /* setting variable mtrr, comes from linux kernel source */ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, unsigned char type) { - unsigned int tmp; unsigned long base_high, base_low; unsigned long mask_high, mask_low; @@ -88,14 +113,7 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l // it is recommended that we disable and enable cache when we // do this. - /* Disable cache */ - /* Write back the cache and flush TLB */ - asm volatile ("movl %%cr0, %0\n\t" - "orl $0x40000000, %0\n\t" - "wbinvd\n\t" - "movl %0, %%cr0\n\t" - "wbinvd\n\t":"=r" (tmp)::"memory"); - + disable_cache(); if (sizek == 0) { /* The invalid bit is kept in the mask, so we simply clear the relevant mask register to disable a range. */ @@ -105,12 +123,7 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l wrmsr (MTRRphysBase_MSR(reg), base_low | type, base_high); wrmsr (MTRRphysMask_MSR(reg), mask_low | 0x800, mask_high); } - - // turn cache back on. - asm volatile ("movl %%cr0, %0\n\t" - "andl $0x9fffffff, %0\n\t" - "movl %0, %%cr0\n\t":"=r" (tmp)::"memory"); - + enable_cache(); } /* setting variable mtrr, comes from linux kernel source */ @@ -123,15 +136,7 @@ void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsi // it is recommended that we disable and enable cache when we // do this. - /* Disable cache */ - /* Write back the cache and flush TLB */ - asm volatile ( - "movl %%cr0, %0\n\t" - "orl $0x40000000, %0\n\t" - "movl %0, %%cr0\n\t" - :"=r" (tmp) - ::"memory"); - + disable_cache(); if (size == 0) { /* The invalid bit is kept in the mask, so we simply clear the relevant mask register to disable a range. */ @@ -143,10 +148,7 @@ void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsi } // turn cache back on. - asm volatile ("movl %%cr0, %0\n\t" - "andl $0x9fffffff, %0\n\t" - "movl %0, %%cr0\n\t":"=r" (tmp)::"memory"); - + enable_cache(); } /* fms: find most sigificant bit set, stolen from Linux Kernel Source. */ @@ -211,7 +213,9 @@ static void set_fixed_mtrrs(unsigned int first, unsigned int last, unsigned char if (fixed_msr != i >> 3) { /* But first write out the old msr */ if (fixed_msr < (NUM_FIXED_RANGES >> 3)) { + disable_cache(); wrmsr(mtrr_msr[fixed_msr], low, high); + enable_cache(); } fixed_msr = i>>3; rdmsr(mtrr_msr[fixed_msr], low, high); @@ -226,7 +230,9 @@ static void set_fixed_mtrrs(unsigned int first, unsigned int last, unsigned char } /* Write out the final msr */ if (fixed_msr < (NUM_FIXED_RANGES >> 3)) { + disable_cache(); wrmsr(mtrr_msr[fixed_msr], low, high); + enable_cache(); } } @@ -247,7 +253,8 @@ static unsigned fixed_mtrr_index(unsigned long addrk) } static unsigned int range_to_mtrr(unsigned int reg, - unsigned long range_startk, unsigned long range_sizek) + unsigned long range_startk, unsigned long range_sizek, + unsigned long next_range_startk) { if (!range_sizek || (reg >= BIOS_MTRRS)) { return reg; @@ -323,7 +330,7 @@ void setup_mtrrs(struct mem_range *mem) } /* Write the range mtrrs */ if (range_sizek != 0) { - reg = range_to_mtrr(reg, range_startk, range_sizek); + reg = range_to_mtrr(reg, range_startk, range_sizek, memp->basek); range_startk = 0; range_sizek = 0; if (reg >= BIOS_MTRRS) @@ -334,7 +341,7 @@ void setup_mtrrs(struct mem_range *mem) range_sizek = memp->sizek; } /* Write the last range */ - reg = range_to_mtrr(reg, range_startk, range_sizek); + reg = range_to_mtrr(reg, range_startk, range_sizek, 0); printk_debug("DONE variable MTRRs\n"); printk_debug("Clear out the extra MTRR's\n"); /* Clear out the extra MTRR's */