summaryrefslogtreecommitdiff
path: root/src/cpu/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/x86')
-rw-r--r--src/cpu/x86/lapic/lapic_cpu_init.c57
-rw-r--r--src/cpu/x86/lapic/secondary.S10
-rw-r--r--src/cpu/x86/pae/pgtbl.c22
3 files changed, 81 insertions, 8 deletions
diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c
index 4e7e696c47..aa62e244b8 100644
--- a/src/cpu/x86/lapic/lapic_cpu_init.c
+++ b/src/cpu/x86/lapic/lapic_cpu_init.c
@@ -1,3 +1,8 @@
+/*
+ 2005.12 yhlu add linuxbios_ram cross the vga font buffer handling
+ 2005.12 yhlu add _RAMBASE above 1M support for SMP
+*/
+
#include <cpu/x86/lapic.h>
#include <delay.h>
#include <string.h>
@@ -9,7 +14,6 @@
#include <smp/spinlock.h>
#include <cpu/cpu.h>
-
#if CONFIG_SMP == 1
/* This is a lot more paranoid now, since Linux can NOT handle
@@ -19,6 +23,32 @@
* We actually handling that case by noting which cpus startup
* and not telling anyone about the ones that dont.
*/
+static unsigned long get_valid_start_eip(unsigned long orig_start_eip)
+{
+ return (unsigned long)orig_start_eip & 0xfffff; // 20 bit
+}
+
+static void copy_secondary_start_to_1m_below(void)
+{
+#if _RAMBASE > 0x100000
+ extern char _secondary_start[];
+ extern char _secondary_start_end[];
+ unsigned long code_size;
+ unsigned long start_eip;
+
+ /* _secondary_start need to be masked 20 above bit, because 16 bit code in secondary.S
+ Also We need to copy the _secondary_start to the below 1M region
+ */
+ start_eip = get_valid_start_eip((unsigned long)_secondary_start);
+ code_size = (unsigned long)_secondary_start_end - (unsigned long)_secondary_start;
+
+ /* copy the _secondary_start to the ram below 1M*/
+ memcpy(start_eip, (unsigned long)_secondary_start, code_size);
+
+ printk_debug("start_eip=0x%08lx, offset=0x%08lx, code_size=0x%08lx\n", start_eip, ((unsigned long)_secondary_start - start_eip), code_size);
+#endif
+}
+
static int lapic_start_cpu(unsigned long apicid)
{
int timeout;
@@ -87,8 +117,8 @@ static int lapic_start_cpu(unsigned long apicid)
return 0;
}
- start_eip = (unsigned long)_secondary_start;
- printk_spew("start_eip=0x%08lx\n", start_eip);
+ start_eip = get_valid_start_eip((unsigned long)_secondary_start);
+ printk_debug("start_eip=0x%08lx\n", start_eip);
num_starts = 2;
@@ -193,7 +223,25 @@ int start_cpu(device_t cpu)
index = ++last_cpu_index;
/* Find end of the new processors stack */
+#if (CONFIG_LB_MEM_TOPK>1024) && (_RAMBASE < 0x100000) && ((CONFIG_CONSOLE_VGA==1) || (CONFIG_PCI_ROM_RUN == 1))
+ if(index<1) { // only keep bsp on low
+ stack_end = ((unsigned long)_estack) - (STACK_SIZE*index) - sizeof(struct cpu_info);
+ } else {
+ // for all APs, let use stack after pgtbl, 20480 is the pgtbl size for every cpu
+ stack_end = 0x100000+(20480 + STACK_SIZE)*CONFIG_MAX_CPUS - (STACK_SIZE*index);
+#if (0x100000+(20480 + STACK_SIZE)*CONFIG_MAX_CPU) > (CONFIG_LB_MEM_TOPK<<10)
+ #warning "We may need to increase CONFIG_LB_MEM_TOPK, it need to be more than (0x100000+(20480 + STACK_SIZE)*CONFIG_MAX_CPU)\n"
+#endif
+ if(stack_end > (CONFIG_LB_MEM_TOPK<<10)) {
+ printk_debug("start_cpu: Please increase the CONFIG_LB_MEM_TOPK more than %dK\n", stack_end>>10);
+ die("Can not go on\n");
+ }
+ stack_end -= sizeof(struct cpu_info);
+ }
+#else
stack_end = ((unsigned long)_estack) - (STACK_SIZE*index) - sizeof(struct cpu_info);
+#endif
+
/* Record the index and which cpu structure we are using */
info = (struct cpu_info *)stack_end;
@@ -251,6 +299,7 @@ static void initialize_other_cpus(struct bus *cpu_bus)
int old_active_count, active_count;
device_t cpu;
/* Loop through the cpus once getting them started */
+
for(cpu = cpu_bus->children; cpu ; cpu = cpu->sibling) {
if (cpu->path.type != DEVICE_PATH_APIC) {
continue;
@@ -327,6 +376,8 @@ void initialize_cpus(struct bus *cpu_bus)
/* Find the device structure for the boot cpu */
info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
+
+ copy_secondary_start_to_1m_below(); // why here? In case some day we can start core1 in amd_sibling_init
/* Initialize the bootstrap processor */
cpu_initialize();
diff --git a/src/cpu/x86/lapic/secondary.S b/src/cpu/x86/lapic/secondary.S
index b212f43b38..e531eed46e 100644
--- a/src/cpu/x86/lapic/secondary.S
+++ b/src/cpu/x86/lapic/secondary.S
@@ -3,7 +3,7 @@
#include <cpu/x86/mtrr.h>
#include <cpu/x86/lapic_def.h>
.text
- .globl _secondary_start
+ .globl _secondary_start, _secondary_start_end
.balign 4096
_secondary_start:
.code16
@@ -48,9 +48,9 @@ _secondary_start:
1: hlt
jmp 1b
-gdtaddr:
- .word gdt_limit /* the table limit */
- .long gdt /* we know the offset */
-
+ gdtaddr:
+ .word gdt_limit /* the table limit */
+ .long gdt /* we know the offset */
+_secondary_start_end:
.code32
diff --git a/src/cpu/x86/pae/pgtbl.c b/src/cpu/x86/pae/pgtbl.c
index 8297281ba3..53db758ce2 100644
--- a/src/cpu/x86/pae/pgtbl.c
+++ b/src/cpu/x86/pae/pgtbl.c
@@ -1,3 +1,7 @@
+/*
+ 2005.12 yhlu add linuxbios_ram cross the vga font buffer handling
+*/
+
#include <console/console.h>
#include <cpu/cpu.h>
#include <cpu/x86/pae.h>
@@ -49,7 +53,25 @@ void *map_2M_page(unsigned long page)
struct pde pd[2048];
struct pde pdp[512];
} __attribute__ ((packed));
+
+#if (CONFIG_LB_MEM_TOPK>1024) && (_RAMBASE<0x100000) && ((CONFIG_CONSOLE_VGA==1) || (CONFIG_PCI_ROM_RUN == 1))
+ /*
+ pgtbl is too big, so use last one 1M before CONFIG_LB_MEM_TOP, otherwise for 8 way dual core with vga support will push stack and heap cross 0xa0000,
+ and that region need to be used as vga font buffer. Please make sure set CONFIG_LB_MEM_TOPK=2048 in MB Config
+ */
+ struct pg_table *pgtbl = 0x100000; //1M
+
+ unsigned x_end = 0x100000 + sizeof(struct pg_table) * CONFIG_MAX_CPUS;
+#if (0x100000+20480*CONFIG_MAX_CPU) > (CONFIG_LB_MEM_TOPK<<10)
+ #warning "We may need to increase CONFIG_LB_MEM_TOPK, it need to be more than (0x100000+20480*CONFIG_MAX_CPU)\n"
+#endif
+ if(x_end > (CONFIG_LB_MEM_TOPK<<10)) {
+ printk_debug("map_2M_page: Please increase the CONFIG_LB_MEM_TOPK more than %dK\n", x_end>>10);
+ die("Can not go on");
+ }
+#else
static struct pg_table pgtbl[CONFIG_MAX_CPUS] __attribute__ ((aligned(4096)));
+#endif
static unsigned long mapped_window[CONFIG_MAX_CPUS];
unsigned long index;
unsigned long window;