coreboot-v3/arch/x86/geodelx/stage0.S
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
   5 * Copyright (C) 2005 Eswar Nallusamy, LANL
   6 * Copyright (C) 2005 Tyan
   7 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
   8 * Copyright (C) 2007 coresystems GmbH
   9 * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
  10 * Copyright (C) 2007 Advanced Micro Devices, Inc.
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; version 2 of the License.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  24 */
  25
  26/* Init code - Switch CPU to protected mode and enable Cache-as-Ram (CAR). */
  27
  28#include <macros.h>
  29#include <amd_geodelx.h>
  30
  31        .code16
  32        .globl _stage0
  33_stage0:
  34        cli
  35
  36        /* Save the BIST result. */
  37        movl    %eax, %ebp;
  38
  39        /* IMMEDIATELY invalidate the translation lookaside buffer (TLB) before
  40         * executing any further code. Even though paging is disabled we
  41         * could still get false address translations due to the TLB if we
  42         * didn't invalidate it.
  43         */
  44        xorl    %eax, %eax
  45        movl    %eax, %cr3      /* Invalidate TLB. */
  46
  47        /* Switch to protected mode. */
  48
  49        /* NOTE: With GNU assembler version 2.15.94.0.2.2 (i386-redhat-linux)
  50         * using BFD version 2.15.94.0.2.2 20041220 this works fine without
  51         * all the ld hackery and so on. So leave it as is with this comment.
  52         */
  53
  54        data32  lgdt %cs:gdtptr
  55
  56        movl    %cr0, %eax
  57        andl    $0x7FFAFFD1, %eax /* PG, AM, WP, NE, TS, EM, MP = 0 */
  58        orl     $0x60000001, %eax /* CD, NW, PE = 1 */
  59        movl    %eax, %cr0
  60
  61        /* Restore BIST result. */
  62        movl    %ebp, %eax
  63
  64        // port80_post(0x23)
  65
  66        /* Now we are in protected mode. Jump to a 32 bit code segment. */
  67        data32  ljmp $ROM_CODE_SEG, $protected_stage0
  68
  69        /* I am leaving this weird jump in here in the event that future gas
  70         * bugs force it to be used.
  71         */
  72        /* .byte 0x66 */
  73        .code32
  74        /* ljmp $ROM_CODE_SEG, $protected_stage0 */
  75
  76        /* .code16 */
  77        .align 4
  78        .globl gdt16
  79gdt16 = . - _stage0
  80gdt16x:
  81        .word   gdt16xend - gdt16x -1   /* Compute the table limit. */
  82        .long   gdt16x
  83        .word   0
  84
  85        /* selgdt 0x08, flat code segment */
  86        .word   0xffff, 0x0000
  87        .byte   0x00, 0x9b, 0xcf, 0x00
  88
  89        /* selgdt 0x10, flat data segment */
  90        .word   0xffff, 0x0000
  91        .byte   0x00, 0x93, 0xcf, 0x00
  92gdt16xend:
  93
  94        /* From now on we are 32bit. */
  95        .code32
  96
  97        /* We have two gdts where we could have one. That is ok.
  98         *
  99         * Let's not worry about this -- optimizing gdt is pointless since
 100         * we're only in it for a little bit.
 101         *
 102         * Btw. note the trick below: The GDT points to ITSELF, and the first
 103         * good descriptor is at offset 8. So you word-align the table, and
 104         * then because you chose 8, you get a nice 64-bit aligned GDT entry,
 105         * which is good as this is the size of the entry.
 106         *
 107         * Just in case you ever wonder why people do this.
 108         */
 109        .align 4
 110        .globl gdtptr
 111        .globl gdt_limit
 112gdt_limit = gdt_end - gdt - 1           /* Compute the table limit. */
 113
 114gdt:
 115gdtptr:
 116        .word   gdt_end - gdt -1        /* Compute the table limit. */
 117        .long   gdt                     /* We know the offset. */
 118        .word   0
 119
 120        /* selgdt 0x08, flat code segment */
 121        .word   0xffff, 0x0000
 122        .byte   0x00, 0x9b, 0xcf, 0x00
 123
 124        /* selgdt 0x10, flat data segment */
 125        .word   0xffff, 0x0000
 126        .byte   0x00, 0x93, 0xcf, 0x00
 127
 128        /* selgdt 0x18, flat code segment for CAR */
 129        .word   0xffff, 0x0000
 130        .byte   0x00, 0x9b, 0xcf, 0x00
 131
 132        /* selgdt 0x20, flat data segment for CAR */
 133        .word   0xffff, 0x0000
 134        .byte   0x00, 0x93, 0xcf, 0x00
 135gdt_end:
 136
 137        /* When we come here we are in protected mode. We expand the stack
 138         * and copy the data segment from ROM to the memory.
 139         *
 140         * After that, we call the chipset bootstrap routine that
 141         * does what is left of the chipset initialization.
 142         *
 143         * Note: Aligned to 4 so that we are sure that the prefetch
 144         * cache will be reloaded.
 145         */
 146
 147        .align  4
 148        .globl protected_stage0
 149protected_stage0:
 150        /* This code was used by v2. TODO. */
 151        lgdt    %cs:gdtptr
 152        ljmp    $ROM_CODE_SEG, $__protected_stage0
 153
 154.globl __protected_stage0
 155__protected_stage0:
 156        /* Save the BIST value. */
 157        movl    %eax, %ebp
 158
 159        port80_post(0x01)
 160
 161        movw    $ROM_DATA_SEG, %ax
 162        movw    %ax, %ds
 163        movw    %ax, %es
 164        movw    %ax, %ss
 165        movw    %ax, %fs
 166        movw    %ax, %gs
 167
 168        /* Restore the BIST value to %eax. */
 169        movl    %ebp, %eax
 170
 171        .align 4
 172        /* Here begins CAR support. */
 173        /* This particular code is straight from coreboot v2. */
 174
 175        /* DCacheSetup: Setup data cache for use as RAM for a stack. */
 176DCacheSetup:
 177        invd
 178
 179        /* Set cache properties. */
 180        movl    $CPU_RCONF_DEFAULT, %ecx
 181        rdmsr
 182
 183        /* 1MB system memory in write back 1|00100|00. */
 184        movl    $0x010010000, %eax
 185        wrmsr
 186
 187        /* In LX DCDIS is set after POR which disables the cache..., clear
 188         * this bit.
 189         */
 190        movl    $CPU_DM_CONFIG0,%ecx
 191        rdmsr
 192
 193        /* TODO: Make consistent with i$ init, either whole reg = 0, or just
 194         * this bit...
 195         */
 196        andl    $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax
 197        wrmsr
 198
 199        /* Get cache timing params from BIOS config data locations and apply. */
 200        /* Fix delay controls for DM and IM arrays. */
 201        movl    $CPU_BC_MSS_ARRAY_CTL0, %ecx
 202        xorl    %edx, %edx
 203        movl    $0x2814D352, %eax
 204        wrmsr
 205
 206        movl    $CPU_BC_MSS_ARRAY_CTL1, %ecx
 207        xorl    %edx, %edx
 208        movl    $0x1068334D, %eax
 209        wrmsr
 210
 211        movl    $CPU_BC_MSS_ARRAY_CTL2, %ecx
 212        movl    $0x00000106, %edx
 213        movl    $0x83104104, %eax
 214        wrmsr
 215
 216        movl    $GLCP_FIFOCTL, %ecx
 217        rdmsr
 218        movl    $0x00000005, %edx
 219        wrmsr
 220
 221        /* Enable setting. */
 222        movl    $CPU_BC_MSS_ARRAY_CTL_ENA, %ecx
 223        xorl    %edx, %edx
 224        movl    $0x01, %eax
 225        wrmsr
 226
 227        /* Get cleaned up. */
 228        xorl    %edi, %edi
 229        xorl    %esi, %esi
 230        xorl    %ebp, %ebp
 231
 232        /* DCache Ways0 through Ways7 will be tagged for
 233         * LX_STACK_BASE + DCACHE_RAM_SIZE for holding stack.
 234         */
 235        /* Remember, there is NO stack yet... */
 236
 237        /* Tell cache we want to fill Way 0 starting at the top. */
 238        xorl    %edx, %edx
 239        xorl    %eax, %eax
 240        movl    $CPU_DC_INDEX, %ecx
 241        wrmsr
 242
 243        /* Start address for tag of Way0: ebp will hold the incrementing
 244         * address. Don't destroy!
 245         */
 246        movl    $LX_STACK_BASE, %ebp    /* Init to start address. */
 247
 248        /* Set valid bit and tag for this Way (B[31:12]: Cache tag value for
 249         * line/way curr. selected by CPU_DC_INDEX.
 250         */
 251        orl     $1, %ebp
 252
 253        /* Start tag Ways 0 with 128 lines with 32 bytes each: edi will hold
 254         * the line counter. Don't destroy!
 255         */
 256        movl    $LX_NUM_CACHELINES, %edi
 257
 258DCacheSetupFillWay:
 259        /* Fill with dummy data: zero it so we can tell it from PCI memory
 260         * space (returns FFs).
 261         */
 262        /* We will now store a line (32 bytes = 4 x 8 bytes = 4 quad-words). */
 263        movw    $0x04, %si
 264        xorl    %edx, %edx
 265        xorl    %eax, %eax
 266        movl    $CPU_DC_DATA, %ecx
 267
 268DCacheSetup_quadWordLoop:
 269        wrmsr
 270        decw    %si
 271        jnz     DCacheSetup_quadWordLoop
 272
 273        /* Set the tag for this line, need to do this for every new cache
 274         * line to validate it!
 275         */
 276        /* Accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX
 277         * increment and thus continue in the next cache line...
 278         */
 279        xorl    %edx, %edx
 280        movl    %ebp, %eax
 281        movl    $CPU_DC_TAG, %ecx
 282        wrmsr
 283
 284        /* Switch to next line. Lines are in bits 10:4. */
 285        /* When index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is
 286         * not a valid CL anymore!
 287         */
 288        movl    $CPU_DC_INDEX, %ecx
 289        rdmsr
 290
 291        /* TODO: Probably would be more elegant to calculate this from
 292         * counter var edi...
 293         */
 294        addl    $0x010, %eax
 295        wrmsr
 296
 297        decl    %edi
 298        jnz     DCacheSetupFillWay
 299
 300        /* 1 Way has been filled, forward start address for next Way,
 301         * terminate if we have reached end of desired address range.
 302         */
 303        addl    $LX_CACHEWAY_SIZE, %ebp
 304        cmpl    $LX_STACK_END, %ebp
 305        jge     leave_DCacheSetup
 306        movl    $LX_NUM_CACHELINES, %edi
 307
 308        /* Switch to next way. */
 309        movl    $CPU_DC_INDEX, %ecx
 310        rdmsr
 311        addl    $0x01, %eax
 312
 313        /* Let's be sure: reset line index bits 10:4. */
 314        andl    $0xFFFFF80F, %eax
 315        wrmsr
 316
 317        jmp     DCacheSetupFillWay
 318
 319leave_DCacheSetup:
 320        xorl    %edi, %edi
 321        xorl    %esi, %esi
 322        xorl    %ebp, %ebp
 323
 324        /* Disable the cache, but... DO NOT INVALIDATE the tags. */
 325        /* Memory reads and writes will all hit in the cache. */
 326        /* Cache updates and memory write-backs will not occur! */
 327        movl    %cr0, %eax
 328        orl     $(CR0_CD + CR0_NW), %eax        /* Set the CD and NW bits. */
 329        movl    %eax, %cr0
 330
 331        /* Now point sp to the cached stack. */
 332        /* The stack will be fully functional at this location. No system
 333         * memory is required at all!
 334         */
 335        /* Set up the stack pointer. */
 336        movl    $LX_STACK_END, %eax
 337        movl    %eax, %esp
 338
 339        /* Test the stack. */
 340        movl    $0x0F0F05A5A, %edx
 341        pushl   %edx
 342        popl    %ecx
 343        cmpl    %ecx, %edx
 344        je      DCacheSetupGood
 345        movb    $0xC5, %al
 346        outb    %al, $0x80
 347
 348DCacheSetupBad:
 349        hlt             /* Issues */
 350        jmp DCacheSetupBad
 351
 352DCacheSetupGood:
 353        /* At this point, CAR should be working. */
 354        movl    $(LX_STACK_END), %eax
 355        movl    %eax, %esp
 356
 357        /* Load a different set of data segments. */
 358        movw    $CACHE_RAM_DATA_SEG, %ax
 359        movw    %ax, %ds
 360        movw    %ax, %es
 361        movw    %ax, %ss
 362
 363lout:
 364#ifdef CONFIG_CONSOLE_BUFFER
 365        /* Store pointer to start of printk buffer, should really use
 366         * PRINTK_BUF_ADDR_CAR instead.
 367         */
 368        movl    $CONFIG_CARBASE, %eax
 369        pushl   %eax  /* printk buffer */
 370#endif
 371        /* Restore the BIST result. */
 372        movl    %ebp, %eax
 373
 374        /* We need to set ebp? No need. */
 375        movl    %esp, %ebp
 376        pushl   %eax            /* BIST */
 377        jmp     stage1_main
 378        /* We will not go back. */
 379
 380/* Reset vector. */
 381
 382/*
 383 * RVECTOR: Size of reset vector, default is 0x10.
 384 * RESRVED: Size of vpd code, default is 0xf0.
 385 * BOOTBLK: Size of bootblock code, default is 0x1f00 (8k-256b).
 386 */
 387
 388SEGMENT_SIZE = 0x10000
 389RVECTOR      = 0x00010
 390
 391/* Due to YET ANOTHER BUG in GNU bintools, you can NOT have a code16 here.
 392 * I think we should leave it this way forever, as the bugs come and
 393 * go -- and come again.
 394 *
 395 *      .code16
 396 *      .section ".rom.text"
 397 */
 398.section ".reset", "ax"
 399        .globl _resetjump
 400_resetjump:
 401        /* GNU bintools bugs again. This jumps to stage0 - 2. Sigh. */
 402        /* jmp _stage0 */
 403        .byte   0xe9
 404        .int    _stage0 - ( . + 2 )
 405
 406        /* Note: The above jump is hand coded to work around bugs in binutils.
 407         * 5 bytes are used for a 3 byte instruction. This works because x86
 408         * is little endian and allows us to use supported 32 bit relocations
 409         * instead of the weird 16 bit relocations that binutils does not
 410         * handle consistenly between versions because they are used so rarely.
 411         */
 412.byte   0
 413
 414/* Date? ID string? We might want to put something else in here. */
 415.ascii DATE
 416
 417/* Checksum. */
 418/* .word 0 */
 419
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.