Print this page
    
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/i86pc/dboot/dboot_startkern.c
          +++ new/usr/src/uts/i86pc/dboot/dboot_startkern.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   *
  26   26   * Copyright 2013 Joyent, Inc.  All rights reserved.
  27   27   */
  28   28  
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
  29   29  
  30   30  #include <sys/types.h>
  31   31  #include <sys/machparam.h>
  32   32  #include <sys/x86_archext.h>
  33   33  #include <sys/systm.h>
  34   34  #include <sys/mach_mmu.h>
  35   35  #include <sys/multiboot.h>
  36   36  #include <sys/multiboot2.h>
  37   37  #include <sys/multiboot2_impl.h>
  38   38  #include <sys/sysmacros.h>
       39 +#include <sys/framebuffer.h>
  39   40  #include <sys/sha1.h>
  40   41  #include <util/string.h>
  41   42  #include <util/strtolctype.h>
  42   43  #include <sys/efi.h>
  43   44  
  44   45  #if defined(__xpv)
  45   46  
  46   47  #include <sys/hypervisor.h>
  47   48  uintptr_t xen_virt_start;
  48   49  pfn_t *mfn_to_pfn_mapping;
  49   50  
  50   51  #else /* !__xpv */
  51   52  
  52   53  extern multiboot_header_t mb_header;
  53   54  extern uint32_t mb2_load_addr;
  54   55  extern int have_cpuid(void);
  55   56  
  56   57  #endif /* !__xpv */
  57   58  
  58   59  #include <sys/inttypes.h>
  59   60  #include <sys/bootinfo.h>
  60   61  #include <sys/mach_mmu.h>
  61   62  #include <sys/boot_console.h>
  62   63  
  63   64  #include "dboot_asm.h"
  64   65  #include "dboot_printf.h"
  65   66  #include "dboot_xboot.h"
  66   67  #include "dboot_elfload.h"
  67   68  
  68   69  #define SHA1_ASCII_LENGTH       (SHA1_DIGEST_LENGTH * 2)
  69   70  
  70   71  /*
  71   72   * This file contains code that runs to transition us from either a multiboot
  72   73   * compliant loader (32 bit non-paging) or a XPV domain loader to
  73   74   * regular kernel execution. Its task is to setup the kernel memory image
  74   75   * and page tables.
  75   76   *
  76   77   * The code executes as:
  77   78   *      - 32 bits under GRUB (for 32 or 64 bit Solaris)
  78   79   *      - a 32 bit program for the 32-bit PV hypervisor
  79   80   *      - a 64 bit program for the 64-bit PV hypervisor (at least for now)
  80   81   *
  81   82   * Under the PV hypervisor, we must create mappings for any memory beyond the
  82   83   * initial start of day allocation (such as the kernel itself).
  83   84   *
  84   85   * When on the metal, the mapping between maddr_t and paddr_t is 1:1.
  85   86   * Since we are running in real mode, so all such memory is accessible.
  86   87   */
  87   88  
  88   89  /*
  89   90   * Standard bits used in PTE (page level) and PTP (internal levels)
  90   91   */
  91   92  x86pte_t ptp_bits = PT_VALID | PT_REF | PT_WRITABLE | PT_USER;
  92   93  x86pte_t pte_bits = PT_VALID | PT_REF | PT_WRITABLE | PT_MOD | PT_NOCONSIST;
  93   94  
  94   95  /*
  95   96   * This is the target addresses (physical) where the kernel text and data
  96   97   * nucleus pages will be unpacked. On the hypervisor this is actually a
  97   98   * virtual address.
  98   99   */
  99  100  paddr_t ktext_phys;
 100  101  uint32_t ksize = 2 * FOUR_MEG;  /* kernel nucleus is 8Meg */
 101  102  
 102  103  static uint64_t target_kernel_text;     /* value to use for KERNEL_TEXT */
 103  104  
 104  105  /*
 105  106   * The stack is setup in assembler before entering startup_kernel()
 106  107   */
 107  108  char stack_space[STACK_SIZE];
 108  109  
 109  110  /*
 110  111   * Used to track physical memory allocation
 111  112   */
 112  113  static paddr_t next_avail_addr = 0;
 113  114  
 114  115  #if defined(__xpv)
 115  116  /*
 116  117   * Additional information needed for hypervisor memory allocation.
 117  118   * Only memory up to scratch_end is mapped by page tables.
 118  119   * mfn_base is the start of the hypervisor virtual image. It's ONE_GIG, so
 119  120   * to derive a pfn from a pointer, you subtract mfn_base.
 120  121   */
 121  122  
 122  123  static paddr_t scratch_end = 0; /* we can't write all of mem here */
 123  124  static paddr_t mfn_base;                /* addr corresponding to mfn_list[0] */
 124  125  start_info_t *xen_info;
 125  126  
 126  127  #else   /* __xpv */
 127  128  
 128  129  /*
 129  130   * If on the metal, then we have a multiboot loader.
  
    | 
      ↓ open down ↓ | 
    81 lines elided | 
    
      ↑ open up ↑ | 
  
 130  131   */
 131  132  uint32_t mb_magic;                      /* magic from boot loader */
 132  133  uint32_t mb_addr;                       /* multiboot info package from loader */
 133  134  int multiboot_version;
 134  135  multiboot_info_t *mb_info;
 135  136  multiboot2_info_header_t *mb2_info;
 136  137  multiboot_tag_mmap_t *mb2_mmap_tagp;
 137  138  int num_entries;                        /* mmap entry count */
 138  139  boolean_t num_entries_set;              /* is mmap entry count set */
 139  140  uintptr_t load_addr;
      141 +static boot_framebuffer_t framebuffer[2];
      142 +static boot_framebuffer_t *fb;
 140  143  
 141  144  /* can not be automatic variables because of alignment */
 142  145  static efi_guid_t smbios3 = SMBIOS3_TABLE_GUID;
 143  146  static efi_guid_t smbios = SMBIOS_TABLE_GUID;
 144  147  static efi_guid_t acpi2 = EFI_ACPI_TABLE_GUID;
 145  148  static efi_guid_t acpi1 = ACPI_10_TABLE_GUID;
 146  149  #endif  /* __xpv */
 147  150  
 148  151  /*
 149  152   * This contains information passed to the kernel
 150  153   */
 151  154  struct xboot_info boot_info[2]; /* extra space to fix alignement for amd64 */
 152  155  struct xboot_info *bi;
 153  156  
 154  157  /*
 155  158   * Page table and memory stuff.
 156  159   */
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
 157  160  static paddr_t max_mem;                 /* maximum memory address */
 158  161  
 159  162  /*
 160  163   * Information about processor MMU
 161  164   */
 162  165  int amd64_support = 0;
 163  166  int largepage_support = 0;
 164  167  int pae_support = 0;
 165  168  int pge_support = 0;
 166  169  int NX_support = 0;
      170 +int PAT_support = 0;
 167  171  
 168  172  /*
 169  173   * Low 32 bits of kernel entry address passed back to assembler.
 170  174   * When running a 64 bit kernel, the high 32 bits are 0xffffffff.
 171  175   */
 172  176  uint32_t entry_addr_low;
 173  177  
 174  178  /*
 175  179   * Memlists for the kernel. We shouldn't need a lot of these.
 176  180   */
 177  181  #define MAX_MEMLIST (50)
 178  182  struct boot_memlist memlists[MAX_MEMLIST];
 179  183  uint_t memlists_used = 0;
 180  184  struct boot_memlist pcimemlists[MAX_MEMLIST];
 181  185  uint_t pcimemlists_used = 0;
 182  186  struct boot_memlist rsvdmemlists[MAX_MEMLIST];
 183  187  uint_t rsvdmemlists_used = 0;
 184  188  
 185  189  /*
 186  190   * This should match what's in the bootloader.  It's arbitrary, but GRUB
 187  191   * in particular has limitations on how much space it can use before it
 188  192   * stops working properly.  This should be enough.
 189  193   */
 190  194  struct boot_modules modules[MAX_BOOT_MODULES];
 191  195  uint_t modules_used = 0;
 192  196  
 193  197  #ifdef __xpv
 194  198  /*
 195  199   * Xen strips the size field out of the mb_memory_map_t, see struct e820entry
 196  200   * definition in Xen source.
 197  201   */
 198  202  typedef struct {
 199  203          uint32_t        base_addr_low;
 200  204          uint32_t        base_addr_high;
 201  205          uint32_t        length_low;
 202  206          uint32_t        length_high;
 203  207          uint32_t        type;
 204  208  } mmap_t;
 205  209  
 206  210  /*
 207  211   * There is 512KB of scratch area after the boot stack page.
 208  212   * We'll use that for everything except the kernel nucleus pages which are too
 209  213   * big to fit there and are allocated last anyway.
 210  214   */
 211  215  #define MAXMAPS 100
 212  216  static mmap_t map_buffer[MAXMAPS];
 213  217  #else
 214  218  typedef mb_memory_map_t mmap_t;
 215  219  #endif
 216  220  
 217  221  /*
 218  222   * Debugging macros
 219  223   */
 220  224  uint_t prom_debug = 0;
 221  225  uint_t map_debug = 0;
 222  226  
 223  227  static char noname[2] = "-";
 224  228  
 225  229  /*
 226  230   * Either hypervisor-specific or grub-specific code builds the initial
 227  231   * memlists. This code does the sort/merge/link for final use.
 228  232   */
 229  233  static void
 230  234  sort_physinstall(void)
 231  235  {
 232  236          int i;
 233  237  #if !defined(__xpv)
 234  238          int j;
 235  239          struct boot_memlist tmp;
 236  240  
 237  241          /*
 238  242           * Now sort the memlists, in case they weren't in order.
 239  243           * Yeah, this is a bubble sort; small, simple and easy to get right.
 240  244           */
 241  245          DBG_MSG("Sorting phys-installed list\n");
 242  246          for (j = memlists_used - 1; j > 0; --j) {
 243  247                  for (i = 0; i < j; ++i) {
 244  248                          if (memlists[i].addr < memlists[i + 1].addr)
 245  249                                  continue;
 246  250                          tmp = memlists[i];
 247  251                          memlists[i] = memlists[i + 1];
 248  252                          memlists[i + 1] = tmp;
 249  253                  }
 250  254          }
 251  255  
 252  256          /*
 253  257           * Merge any memlists that don't have holes between them.
 254  258           */
 255  259          for (i = 0; i <= memlists_used - 1; ++i) {
 256  260                  if (memlists[i].addr + memlists[i].size != memlists[i + 1].addr)
 257  261                          continue;
 258  262  
 259  263                  if (prom_debug)
 260  264                          dboot_printf(
 261  265                              "merging mem segs %" PRIx64 "...%" PRIx64
 262  266                              " w/ %" PRIx64 "...%" PRIx64 "\n",
 263  267                              memlists[i].addr,
 264  268                              memlists[i].addr + memlists[i].size,
 265  269                              memlists[i + 1].addr,
 266  270                              memlists[i + 1].addr + memlists[i + 1].size);
 267  271  
 268  272                  memlists[i].size += memlists[i + 1].size;
 269  273                  for (j = i + 1; j < memlists_used - 1; ++j)
 270  274                          memlists[j] = memlists[j + 1];
 271  275                  --memlists_used;
 272  276                  DBG(memlists_used);
 273  277                  --i;    /* after merging we need to reexamine, so do this */
 274  278          }
 275  279  #endif  /* __xpv */
 276  280  
 277  281          if (prom_debug) {
 278  282                  dboot_printf("\nFinal memlists:\n");
 279  283                  for (i = 0; i < memlists_used; ++i) {
 280  284                          dboot_printf("\t%d: addr=%" PRIx64 " size=%"
 281  285                              PRIx64 "\n", i, memlists[i].addr, memlists[i].size);
 282  286                  }
 283  287          }
 284  288  
 285  289          /*
 286  290           * link together the memlists with native size pointers
 287  291           */
 288  292          memlists[0].next = 0;
 289  293          memlists[0].prev = 0;
 290  294          for (i = 1; i < memlists_used; ++i) {
 291  295                  memlists[i].prev = (native_ptr_t)(uintptr_t)(memlists + i - 1);
 292  296                  memlists[i].next = 0;
 293  297                  memlists[i - 1].next = (native_ptr_t)(uintptr_t)(memlists + i);
 294  298          }
 295  299          bi->bi_phys_install = (native_ptr_t)(uintptr_t)memlists;
 296  300          DBG(bi->bi_phys_install);
 297  301  }
 298  302  
 299  303  /*
 300  304   * build bios reserved memlists
 301  305   */
 302  306  static void
 303  307  build_rsvdmemlists(void)
 304  308  {
 305  309          int i;
 306  310  
 307  311          rsvdmemlists[0].next = 0;
 308  312          rsvdmemlists[0].prev = 0;
 309  313          for (i = 1; i < rsvdmemlists_used; ++i) {
 310  314                  rsvdmemlists[i].prev =
 311  315                      (native_ptr_t)(uintptr_t)(rsvdmemlists + i - 1);
 312  316                  rsvdmemlists[i].next = 0;
 313  317                  rsvdmemlists[i - 1].next =
 314  318                      (native_ptr_t)(uintptr_t)(rsvdmemlists + i);
 315  319          }
 316  320          bi->bi_rsvdmem = (native_ptr_t)(uintptr_t)rsvdmemlists;
 317  321          DBG(bi->bi_rsvdmem);
 318  322  }
 319  323  
 320  324  #if defined(__xpv)
 321  325  
 322  326  /*
 323  327   * halt on the hypervisor after a delay to drain console output
 324  328   */
 325  329  void
 326  330  dboot_halt(void)
 327  331  {
 328  332          uint_t i = 10000;
 329  333  
 330  334          while (--i)
 331  335                  (void) HYPERVISOR_yield();
 332  336          (void) HYPERVISOR_shutdown(SHUTDOWN_poweroff);
 333  337  }
 334  338  
 335  339  /*
 336  340   * From a machine address, find the corresponding pseudo-physical address.
 337  341   * Pseudo-physical address are contiguous and run from mfn_base in each VM.
 338  342   * Machine addresses are the real underlying hardware addresses.
 339  343   * These are needed for page table entries. Note that this routine is
 340  344   * poorly protected. A bad value of "ma" will cause a page fault.
 341  345   */
 342  346  paddr_t
 343  347  ma_to_pa(maddr_t ma)
 344  348  {
 345  349          ulong_t pgoff = ma & MMU_PAGEOFFSET;
 346  350          ulong_t pfn = mfn_to_pfn_mapping[mmu_btop(ma)];
 347  351          paddr_t pa;
 348  352  
 349  353          if (pfn >= xen_info->nr_pages)
 350  354                  return (-(paddr_t)1);
 351  355          pa = mfn_base + mmu_ptob((paddr_t)pfn) + pgoff;
 352  356  #ifdef DEBUG
 353  357          if (ma != pa_to_ma(pa))
 354  358                  dboot_printf("ma_to_pa(%" PRIx64 ") got %" PRIx64 ", "
 355  359                      "pa_to_ma() says %" PRIx64 "\n", ma, pa, pa_to_ma(pa));
 356  360  #endif
 357  361          return (pa);
 358  362  }
 359  363  
 360  364  /*
 361  365   * From a pseudo-physical address, find the corresponding machine address.
 362  366   */
 363  367  maddr_t
 364  368  pa_to_ma(paddr_t pa)
 365  369  {
 366  370          pfn_t pfn;
 367  371          ulong_t mfn;
 368  372  
 369  373          pfn = mmu_btop(pa - mfn_base);
 370  374          if (pa < mfn_base || pfn >= xen_info->nr_pages)
 371  375                  dboot_panic("pa_to_ma(): illegal address 0x%lx", (ulong_t)pa);
 372  376          mfn = ((ulong_t *)xen_info->mfn_list)[pfn];
 373  377  #ifdef DEBUG
 374  378          if (mfn_to_pfn_mapping[mfn] != pfn)
 375  379                  dboot_printf("pa_to_ma(pfn=%lx) got %lx ma_to_pa() says %lx\n",
 376  380                      pfn, mfn, mfn_to_pfn_mapping[mfn]);
 377  381  #endif
 378  382          return (mfn_to_ma(mfn) | (pa & MMU_PAGEOFFSET));
 379  383  }
 380  384  
 381  385  #endif  /* __xpv */
 382  386  
 383  387  x86pte_t
 384  388  get_pteval(paddr_t table, uint_t index)
 385  389  {
 386  390          if (pae_support)
 387  391                  return (((x86pte_t *)(uintptr_t)table)[index]);
 388  392          return (((x86pte32_t *)(uintptr_t)table)[index]);
 389  393  }
 390  394  
 391  395  /*ARGSUSED*/
 392  396  void
 393  397  set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval)
 394  398  {
 395  399  #ifdef __xpv
 396  400          mmu_update_t t;
 397  401          maddr_t mtable = pa_to_ma(table);
 398  402          int retcnt;
 399  403  
 400  404          t.ptr = (mtable + index * pte_size) | MMU_NORMAL_PT_UPDATE;
 401  405          t.val = pteval;
 402  406          if (HYPERVISOR_mmu_update(&t, 1, &retcnt, DOMID_SELF) || retcnt != 1)
 403  407                  dboot_panic("HYPERVISOR_mmu_update() failed");
 404  408  #else /* __xpv */
 405  409          uintptr_t tab_addr = (uintptr_t)table;
 406  410  
 407  411          if (pae_support)
 408  412                  ((x86pte_t *)tab_addr)[index] = pteval;
 409  413          else
 410  414                  ((x86pte32_t *)tab_addr)[index] = (x86pte32_t)pteval;
 411  415          if (level == top_level && level == 2)
 412  416                  reload_cr3();
 413  417  #endif /* __xpv */
 414  418  }
 415  419  
 416  420  paddr_t
 417  421  make_ptable(x86pte_t *pteval, uint_t level)
 418  422  {
 419  423          paddr_t new_table = (paddr_t)(uintptr_t)mem_alloc(MMU_PAGESIZE);
 420  424  
 421  425          if (level == top_level && level == 2)
 422  426                  *pteval = pa_to_ma((uintptr_t)new_table) | PT_VALID;
 423  427          else
 424  428                  *pteval = pa_to_ma((uintptr_t)new_table) | ptp_bits;
 425  429  
 426  430  #ifdef __xpv
 427  431          /* Remove write permission to the new page table. */
 428  432          if (HYPERVISOR_update_va_mapping(new_table,
 429  433              *pteval & ~(x86pte_t)PT_WRITABLE, UVMF_INVLPG | UVMF_LOCAL))
 430  434                  dboot_panic("HYP_update_va_mapping error");
 431  435  #endif
 432  436  
 433  437          if (map_debug)
 434  438                  dboot_printf("new page table lvl=%d paddr=0x%lx ptp=0x%"
 435  439                      PRIx64 "\n", level, (ulong_t)new_table, *pteval);
 436  440          return (new_table);
 437  441  }
 438  442  
 439  443  x86pte_t *
 440  444  map_pte(paddr_t table, uint_t index)
 441  445  {
 442  446          return ((x86pte_t *)(uintptr_t)(table + index * pte_size));
 443  447  }
 444  448  
 445  449  /*
 446  450   * dump out the contents of page tables...
 447  451   */
 448  452  static void
 449  453  dump_tables(void)
 450  454  {
 451  455          uint_t save_index[4];   /* for recursion */
 452  456          char *save_table[4];    /* for recursion */
 453  457          uint_t  l;
 454  458          uint64_t va;
 455  459          uint64_t pgsize;
 456  460          int index;
 457  461          int i;
 458  462          x86pte_t pteval;
 459  463          char *table;
 460  464          static char *tablist = "\t\t\t";
 461  465          char *tabs = tablist + 3 - top_level;
 462  466          uint_t pa, pa1;
 463  467  #if !defined(__xpv)
 464  468  #define maddr_t paddr_t
 465  469  #endif /* !__xpv */
 466  470  
 467  471          dboot_printf("Finished pagetables:\n");
 468  472          table = (char *)(uintptr_t)top_page_table;
 469  473          l = top_level;
 470  474          va = 0;
 471  475          for (index = 0; index < ptes_per_table; ++index) {
 472  476                  pgsize = 1ull << shift_amt[l];
 473  477                  if (pae_support)
 474  478                          pteval = ((x86pte_t *)table)[index];
 475  479                  else
 476  480                          pteval = ((x86pte32_t *)table)[index];
 477  481                  if (pteval == 0)
 478  482                          goto next_entry;
 479  483  
 480  484                  dboot_printf("%s %p[0x%x] = %" PRIx64 ", va=%" PRIx64,
 481  485                      tabs + l, (void *)table, index, (uint64_t)pteval, va);
 482  486                  pa = ma_to_pa(pteval & MMU_PAGEMASK);
 483  487                  dboot_printf(" physaddr=%x\n", pa);
 484  488  
 485  489                  /*
 486  490                   * Don't try to walk hypervisor private pagetables
 487  491                   */
 488  492                  if ((l > 1 || (l == 1 && (pteval & PT_PAGESIZE) == 0))) {
 489  493                          save_table[l] = table;
 490  494                          save_index[l] = index;
 491  495                          --l;
 492  496                          index = -1;
 493  497                          table = (char *)(uintptr_t)
 494  498                              ma_to_pa(pteval & MMU_PAGEMASK);
 495  499                          goto recursion;
 496  500                  }
 497  501  
 498  502                  /*
 499  503                   * shorten dump for consecutive mappings
 500  504                   */
 501  505                  for (i = 1; index + i < ptes_per_table; ++i) {
 502  506                          if (pae_support)
 503  507                                  pteval = ((x86pte_t *)table)[index + i];
 504  508                          else
 505  509                                  pteval = ((x86pte32_t *)table)[index + i];
 506  510                          if (pteval == 0)
 507  511                                  break;
 508  512                          pa1 = ma_to_pa(pteval & MMU_PAGEMASK);
 509  513                          if (pa1 != pa + i * pgsize)
 510  514                                  break;
 511  515                  }
 512  516                  if (i > 2) {
 513  517                          dboot_printf("%s...\n", tabs + l);
 514  518                          va += pgsize * (i - 2);
 515  519                          index += i - 2;
 516  520                  }
 517  521  next_entry:
 518  522                  va += pgsize;
 519  523                  if (l == 3 && index == 256)     /* VA hole */
 520  524                          va = 0xffff800000000000ull;
 521  525  recursion:
 522  526                  ;
 523  527          }
 524  528          if (l < top_level) {
 525  529                  ++l;
 526  530                  index = save_index[l];
 527  531                  table = save_table[l];
 528  532                  goto recursion;
 529  533          }
 530  534  }
 531  535  
 532  536  /*
 533  537   * Add a mapping for the machine page at the given virtual address.
 534  538   */
 535  539  static void
 536  540  map_ma_at_va(maddr_t ma, native_ptr_t va, uint_t level)
 537  541  {
 538  542          x86pte_t *ptep;
 539  543          x86pte_t pteval;
 540  544  
 541  545          pteval = ma | pte_bits;
 542  546          if (level > 0)
 543  547                  pteval |= PT_PAGESIZE;
 544  548          if (va >= target_kernel_text && pge_support)
 545  549                  pteval |= PT_GLOBAL;
 546  550  
 547  551          if (map_debug && ma != va)
 548  552                  dboot_printf("mapping ma=0x%" PRIx64 " va=0x%" PRIx64
 549  553                      " pte=0x%" PRIx64 " l=%d\n",
 550  554                      (uint64_t)ma, (uint64_t)va, pteval, level);
 551  555  
 552  556  #if defined(__xpv)
 553  557          /*
 554  558           * see if we can avoid find_pte() on the hypervisor
 555  559           */
 556  560          if (HYPERVISOR_update_va_mapping(va, pteval,
 557  561              UVMF_INVLPG | UVMF_LOCAL) == 0)
 558  562                  return;
 559  563  #endif
 560  564  
 561  565          /*
 562  566           * Find the pte that will map this address. This creates any
 563  567           * missing intermediate level page tables
 564  568           */
 565  569          ptep = find_pte(va, NULL, level, 0);
 566  570  
 567  571          /*
 568  572           * When paravirtualized, we must use hypervisor calls to modify the
 569  573           * PTE, since paging is active. On real hardware we just write to
 570  574           * the pagetables which aren't in use yet.
 571  575           */
 572  576  #if defined(__xpv)
 573  577          ptep = ptep;    /* shut lint up */
 574  578          if (HYPERVISOR_update_va_mapping(va, pteval, UVMF_INVLPG | UVMF_LOCAL))
 575  579                  dboot_panic("mmu_update failed-map_pa_at_va va=0x%" PRIx64
 576  580                      " l=%d ma=0x%" PRIx64 ", pte=0x%" PRIx64 "",
 577  581                      (uint64_t)va, level, (uint64_t)ma, pteval);
 578  582  #else
 579  583          if (va < 1024 * 1024)
 580  584                  pteval |= PT_NOCACHE;           /* for video RAM */
 581  585          if (pae_support)
 582  586                  *ptep = pteval;
 583  587          else
 584  588                  *((x86pte32_t *)ptep) = (x86pte32_t)pteval;
 585  589  #endif
 586  590  }
 587  591  
 588  592  /*
 589  593   * Add a mapping for the physical page at the given virtual address.
 590  594   */
 591  595  static void
 592  596  map_pa_at_va(paddr_t pa, native_ptr_t va, uint_t level)
 593  597  {
 594  598          map_ma_at_va(pa_to_ma(pa), va, level);
 595  599  }
 596  600  
 597  601  /*
 598  602   * This is called to remove start..end from the
 599  603   * possible range of PCI addresses.
 600  604   */
 601  605  const uint64_t pci_lo_limit = 0x00100000ul;
 602  606  const uint64_t pci_hi_limit = 0xfff00000ul;
 603  607  static void
 604  608  exclude_from_pci(uint64_t start, uint64_t end)
 605  609  {
 606  610          int i;
 607  611          int j;
 608  612          struct boot_memlist *ml;
 609  613  
 610  614          for (i = 0; i < pcimemlists_used; ++i) {
 611  615                  ml = &pcimemlists[i];
 612  616  
 613  617                  /* delete the entire range? */
 614  618                  if (start <= ml->addr && ml->addr + ml->size <= end) {
 615  619                          --pcimemlists_used;
 616  620                          for (j = i; j < pcimemlists_used; ++j)
 617  621                                  pcimemlists[j] = pcimemlists[j + 1];
 618  622                          --i;    /* to revisit the new one at this index */
 619  623                  }
 620  624  
 621  625                  /* split a range? */
 622  626                  else if (ml->addr < start && end < ml->addr + ml->size) {
 623  627  
 624  628                          ++pcimemlists_used;
 625  629                          if (pcimemlists_used > MAX_MEMLIST)
 626  630                                  dboot_panic("too many pcimemlists");
 627  631  
 628  632                          for (j = pcimemlists_used - 1; j > i; --j)
 629  633                                  pcimemlists[j] = pcimemlists[j - 1];
 630  634                          ml->size = start - ml->addr;
 631  635  
 632  636                          ++ml;
 633  637                          ml->size = (ml->addr + ml->size) - end;
 634  638                          ml->addr = end;
 635  639                          ++i;    /* skip on to next one */
 636  640                  }
 637  641  
 638  642                  /* cut memory off the start? */
 639  643                  else if (ml->addr < end && end < ml->addr + ml->size) {
 640  644                          ml->size -= end - ml->addr;
 641  645                          ml->addr = end;
 642  646                  }
 643  647  
 644  648                  /* cut memory off the end? */
 645  649                  else if (ml->addr <= start && start < ml->addr + ml->size) {
 646  650                          ml->size = start - ml->addr;
 647  651                  }
 648  652          }
 649  653  }
 650  654  
 651  655  /*
 652  656   * During memory allocation, find the highest address not used yet.
 653  657   */
 654  658  static void
 655  659  check_higher(paddr_t a)
 656  660  {
 657  661          if (a < next_avail_addr)
 658  662                  return;
 659  663          next_avail_addr = RNDUP(a + 1, MMU_PAGESIZE);
 660  664          DBG(next_avail_addr);
 661  665  }
 662  666  
 663  667  static int
 664  668  dboot_loader_mmap_entries(void)
 665  669  {
 666  670  #if !defined(__xpv)
 667  671          if (num_entries_set == B_TRUE)
 668  672                  return (num_entries);
 669  673  
 670  674          switch (multiboot_version) {
 671  675          case 1:
 672  676                  DBG(mb_info->flags);
 673  677                  if (mb_info->flags & 0x40) {
 674  678                          mb_memory_map_t *mmap;
 675  679  
 676  680                          DBG(mb_info->mmap_addr);
 677  681                          DBG(mb_info->mmap_length);
 678  682                          check_higher(mb_info->mmap_addr + mb_info->mmap_length);
 679  683  
 680  684                          for (mmap = (mb_memory_map_t *)mb_info->mmap_addr;
 681  685                              (uint32_t)mmap < mb_info->mmap_addr +
 682  686                              mb_info->mmap_length;
 683  687                              mmap = (mb_memory_map_t *)((uint32_t)mmap +
 684  688                              mmap->size + sizeof (mmap->size)))
 685  689                                  ++num_entries;
 686  690  
 687  691                          num_entries_set = B_TRUE;
 688  692                  }
 689  693                  break;
 690  694          case 2:
 691  695                  num_entries_set = B_TRUE;
 692  696                  num_entries = dboot_multiboot2_mmap_nentries(mb2_info,
 693  697                      mb2_mmap_tagp);
 694  698                  break;
 695  699          default:
 696  700                  dboot_panic("Unknown multiboot version: %d\n",
 697  701                      multiboot_version);
 698  702                  break;
 699  703          }
 700  704          return (num_entries);
 701  705  #else
 702  706          return (MAXMAPS);
 703  707  #endif
 704  708  }
 705  709  
 706  710  static uint32_t
 707  711  dboot_loader_mmap_get_type(int index)
 708  712  {
 709  713  #if !defined(__xpv)
 710  714          mb_memory_map_t *mp, *mpend;
 711  715          int i;
 712  716  
 713  717          switch (multiboot_version) {
 714  718          case 1:
 715  719                  mp = (mb_memory_map_t *)mb_info->mmap_addr;
 716  720                  mpend = (mb_memory_map_t *)
 717  721                      (mb_info->mmap_addr + mb_info->mmap_length);
 718  722  
 719  723                  for (i = 0; mp < mpend && i != index; i++)
 720  724                          mp = (mb_memory_map_t *)((uint32_t)mp + mp->size +
 721  725                              sizeof (mp->size));
 722  726                  if (mp >= mpend) {
 723  727                          dboot_panic("dboot_loader_mmap_get_type(): index "
 724  728                              "out of bounds: %d\n", index);
 725  729                  }
 726  730                  return (mp->type);
 727  731  
 728  732          case 2:
 729  733                  return (dboot_multiboot2_mmap_get_type(mb2_info,
 730  734                      mb2_mmap_tagp, index));
 731  735  
 732  736          default:
 733  737                  dboot_panic("Unknown multiboot version: %d\n",
 734  738                      multiboot_version);
 735  739                  break;
 736  740          }
 737  741          return (0);
 738  742  #else
 739  743          return (map_buffer[index].type);
 740  744  #endif
 741  745  }
 742  746  
 743  747  static uint64_t
 744  748  dboot_loader_mmap_get_base(int index)
 745  749  {
 746  750  #if !defined(__xpv)
 747  751          mb_memory_map_t *mp, *mpend;
 748  752          int i;
 749  753  
 750  754          switch (multiboot_version) {
 751  755          case 1:
 752  756                  mp = (mb_memory_map_t *)mb_info->mmap_addr;
 753  757                  mpend = (mb_memory_map_t *)
 754  758                      (mb_info->mmap_addr + mb_info->mmap_length);
 755  759  
 756  760                  for (i = 0; mp < mpend && i != index; i++)
 757  761                          mp = (mb_memory_map_t *)((uint32_t)mp + mp->size +
 758  762                              sizeof (mp->size));
 759  763                  if (mp >= mpend) {
 760  764                          dboot_panic("dboot_loader_mmap_get_base(): index "
 761  765                              "out of bounds: %d\n", index);
 762  766                  }
 763  767                  return (((uint64_t)mp->base_addr_high << 32) +
 764  768                      (uint64_t)mp->base_addr_low);
 765  769  
 766  770          case 2:
 767  771                  return (dboot_multiboot2_mmap_get_base(mb2_info,
 768  772                      mb2_mmap_tagp, index));
 769  773  
 770  774          default:
 771  775                  dboot_panic("Unknown multiboot version: %d\n",
 772  776                      multiboot_version);
 773  777                  break;
 774  778          }
 775  779          return (0);
 776  780  #else
 777  781          return (((uint64_t)map_buffer[index].base_addr_high << 32) +
 778  782              (uint64_t)map_buffer[index].base_addr_low);
 779  783  #endif
 780  784  }
 781  785  
 782  786  static uint64_t
 783  787  dboot_loader_mmap_get_length(int index)
 784  788  {
 785  789  #if !defined(__xpv)
 786  790          mb_memory_map_t *mp, *mpend;
 787  791          int i;
 788  792  
 789  793          switch (multiboot_version) {
 790  794          case 1:
 791  795                  mp = (mb_memory_map_t *)mb_info->mmap_addr;
 792  796                  mpend = (mb_memory_map_t *)
 793  797                      (mb_info->mmap_addr + mb_info->mmap_length);
 794  798  
 795  799                  for (i = 0; mp < mpend && i != index; i++)
 796  800                          mp = (mb_memory_map_t *)((uint32_t)mp + mp->size +
 797  801                              sizeof (mp->size));
 798  802                  if (mp >= mpend) {
 799  803                          dboot_panic("dboot_loader_mmap_get_length(): index "
 800  804                              "out of bounds: %d\n", index);
 801  805                  }
 802  806                  return (((uint64_t)mp->length_high << 32) +
 803  807                      (uint64_t)mp->length_low);
 804  808  
 805  809          case 2:
 806  810                  return (dboot_multiboot2_mmap_get_length(mb2_info,
 807  811                      mb2_mmap_tagp, index));
 808  812  
 809  813          default:
 810  814                  dboot_panic("Unknown multiboot version: %d\n",
 811  815                      multiboot_version);
 812  816                  break;
 813  817          }
 814  818          return (0);
 815  819  #else
 816  820          return (((uint64_t)map_buffer[index].length_high << 32) +
 817  821              (uint64_t)map_buffer[index].length_low);
 818  822  #endif
 819  823  }
 820  824  
 821  825  static void
 822  826  build_pcimemlists(void)
 823  827  {
 824  828          uint64_t page_offset = MMU_PAGEOFFSET;  /* needs to be 64 bits */
 825  829          uint64_t start;
 826  830          uint64_t end;
 827  831          int i, num;
 828  832  
 829  833          /*
 830  834           * initialize
 831  835           */
 832  836          pcimemlists[0].addr = pci_lo_limit;
 833  837          pcimemlists[0].size = pci_hi_limit - pci_lo_limit;
 834  838          pcimemlists_used = 1;
 835  839  
 836  840          num = dboot_loader_mmap_entries();
 837  841          /*
 838  842           * Fill in PCI memlists.
 839  843           */
 840  844          for (i = 0; i < num; ++i) {
 841  845                  start = dboot_loader_mmap_get_base(i);
 842  846                  end = start + dboot_loader_mmap_get_length(i);
 843  847  
 844  848                  if (prom_debug)
 845  849                          dboot_printf("\ttype: %d %" PRIx64 "..%"
 846  850                              PRIx64 "\n", dboot_loader_mmap_get_type(i),
 847  851                              start, end);
 848  852  
 849  853                  /*
 850  854                   * page align start and end
 851  855                   */
 852  856                  start = (start + page_offset) & ~page_offset;
 853  857                  end &= ~page_offset;
 854  858                  if (end <= start)
 855  859                          continue;
 856  860  
 857  861                  exclude_from_pci(start, end);
 858  862          }
 859  863  
 860  864          /*
 861  865           * Finish off the pcimemlist
 862  866           */
 863  867          if (prom_debug) {
 864  868                  for (i = 0; i < pcimemlists_used; ++i) {
 865  869                          dboot_printf("pcimemlist entry 0x%" PRIx64 "..0x%"
 866  870                              PRIx64 "\n", pcimemlists[i].addr,
 867  871                              pcimemlists[i].addr + pcimemlists[i].size);
 868  872                  }
 869  873          }
 870  874          pcimemlists[0].next = 0;
 871  875          pcimemlists[0].prev = 0;
 872  876          for (i = 1; i < pcimemlists_used; ++i) {
 873  877                  pcimemlists[i].prev =
 874  878                      (native_ptr_t)(uintptr_t)(pcimemlists + i - 1);
 875  879                  pcimemlists[i].next = 0;
 876  880                  pcimemlists[i - 1].next =
 877  881                      (native_ptr_t)(uintptr_t)(pcimemlists + i);
 878  882          }
 879  883          bi->bi_pcimem = (native_ptr_t)(uintptr_t)pcimemlists;
 880  884          DBG(bi->bi_pcimem);
 881  885  }
 882  886  
 883  887  #if defined(__xpv)
 884  888  /*
 885  889   * Initialize memory allocator stuff from hypervisor-supplied start info.
 886  890   */
 887  891  static void
 888  892  init_mem_alloc(void)
 889  893  {
 890  894          int     local;  /* variables needed to find start region */
 891  895          paddr_t scratch_start;
 892  896          xen_memory_map_t map;
 893  897  
 894  898          DBG_MSG("Entered init_mem_alloc()\n");
 895  899  
 896  900          /*
 897  901           * Free memory follows the stack. There's at least 512KB of scratch
 898  902           * space, rounded up to at least 2Mb alignment.  That should be enough
 899  903           * for the page tables we'll need to build.  The nucleus memory is
 900  904           * allocated last and will be outside the addressible range.  We'll
 901  905           * switch to new page tables before we unpack the kernel
 902  906           */
 903  907          scratch_start = RNDUP((paddr_t)(uintptr_t)&local, MMU_PAGESIZE);
 904  908          DBG(scratch_start);
 905  909          scratch_end = RNDUP((paddr_t)scratch_start + 512 * 1024, TWO_MEG);
 906  910          DBG(scratch_end);
 907  911  
 908  912          /*
 909  913           * For paranoia, leave some space between hypervisor data and ours.
 910  914           * Use 500 instead of 512.
 911  915           */
 912  916          next_avail_addr = scratch_end - 500 * 1024;
 913  917          DBG(next_avail_addr);
 914  918  
 915  919          /*
 916  920           * The domain builder gives us at most 1 module
 917  921           */
 918  922          DBG(xen_info->mod_len);
 919  923          if (xen_info->mod_len > 0) {
 920  924                  DBG(xen_info->mod_start);
 921  925                  modules[0].bm_addr =
 922  926                      (native_ptr_t)(uintptr_t)xen_info->mod_start;
 923  927                  modules[0].bm_size = xen_info->mod_len;
 924  928                  bi->bi_module_cnt = 1;
 925  929                  bi->bi_modules = (native_ptr_t)(uintptr_t)modules;
 926  930          } else {
 927  931                  bi->bi_module_cnt = 0;
 928  932                  bi->bi_modules = (native_ptr_t)(uintptr_t)NULL;
 929  933          }
 930  934          DBG(bi->bi_module_cnt);
 931  935          DBG(bi->bi_modules);
 932  936  
 933  937          DBG(xen_info->mfn_list);
 934  938          DBG(xen_info->nr_pages);
 935  939          max_mem = (paddr_t)xen_info->nr_pages << MMU_PAGESHIFT;
 936  940          DBG(max_mem);
 937  941  
 938  942          /*
 939  943           * Using pseudo-physical addresses, so only 1 memlist element
 940  944           */
 941  945          memlists[0].addr = 0;
 942  946          DBG(memlists[0].addr);
 943  947          memlists[0].size = max_mem;
 944  948          DBG(memlists[0].size);
 945  949          memlists_used = 1;
 946  950          DBG(memlists_used);
 947  951  
 948  952          /*
 949  953           * finish building physinstall list
 950  954           */
 951  955          sort_physinstall();
 952  956  
 953  957          /*
 954  958           * build bios reserved memlists
 955  959           */
 956  960          build_rsvdmemlists();
 957  961  
 958  962          if (DOMAIN_IS_INITDOMAIN(xen_info)) {
 959  963                  /*
 960  964                   * build PCI Memory list
 961  965                   */
 962  966                  map.nr_entries = MAXMAPS;
 963  967                  /*LINTED: constant in conditional context*/
 964  968                  set_xen_guest_handle(map.buffer, map_buffer);
 965  969                  if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &map) != 0)
  
    | 
      ↓ open down ↓ | 
    789 lines elided | 
    
      ↑ open up ↑ | 
  
 966  970                          dboot_panic("getting XENMEM_machine_memory_map failed");
 967  971                  build_pcimemlists();
 968  972          }
 969  973  }
 970  974  
 971  975  #else   /* !__xpv */
 972  976  
 973  977  static void
 974  978  dboot_multiboot1_xboot_consinfo(void)
 975  979  {
 976      -        bi->bi_framebuffer = NULL;
      980 +        fb->framebuffer = 0;
 977  981  }
 978  982  
 979  983  static void
 980  984  dboot_multiboot2_xboot_consinfo(void)
 981  985  {
 982      -        multiboot_tag_framebuffer_t *fb;
 983      -        fb = dboot_multiboot2_find_tag(mb2_info,
      986 +        multiboot_tag_framebuffer_t *fbtag;
      987 +        fbtag = dboot_multiboot2_find_tag(mb2_info,
 984  988              MULTIBOOT_TAG_TYPE_FRAMEBUFFER);
 985      -        bi->bi_framebuffer = (native_ptr_t)(uintptr_t)fb;
      989 +        fb->framebuffer = (uint64_t)(uintptr_t)fbtag;
      990 +        fb->boot_fb_virt = 0;
 986  991  }
 987  992  
 988  993  static int
 989  994  dboot_multiboot_modcount(void)
 990  995  {
 991  996          switch (multiboot_version) {
 992  997          case 1:
 993  998                  return (mb_info->mods_count);
 994  999  
 995 1000          case 2:
 996 1001                  return (dboot_multiboot2_modcount(mb2_info));
 997 1002  
 998 1003          default:
 999 1004                  dboot_panic("Unknown multiboot version: %d\n",
1000 1005                      multiboot_version);
1001 1006                  break;
1002 1007          }
1003 1008          return (0);
1004 1009  }
1005 1010  
1006 1011  static uint32_t
1007 1012  dboot_multiboot_modstart(int index)
1008 1013  {
1009 1014          switch (multiboot_version) {
1010 1015          case 1:
1011 1016                  return (((mb_module_t *)mb_info->mods_addr)[index].mod_start);
1012 1017  
1013 1018          case 2:
1014 1019                  return (dboot_multiboot2_modstart(mb2_info, index));
1015 1020  
1016 1021          default:
1017 1022                  dboot_panic("Unknown multiboot version: %d\n",
1018 1023                      multiboot_version);
1019 1024                  break;
1020 1025          }
1021 1026          return (0);
1022 1027  }
1023 1028  
1024 1029  static uint32_t
1025 1030  dboot_multiboot_modend(int index)
1026 1031  {
1027 1032          switch (multiboot_version) {
1028 1033          case 1:
1029 1034                  return (((mb_module_t *)mb_info->mods_addr)[index].mod_end);
1030 1035  
1031 1036          case 2:
1032 1037                  return (dboot_multiboot2_modend(mb2_info, index));
1033 1038  
1034 1039          default:
1035 1040                  dboot_panic("Unknown multiboot version: %d\n",
1036 1041                      multiboot_version);
1037 1042                  break;
1038 1043          }
1039 1044          return (0);
1040 1045  }
1041 1046  
1042 1047  static char *
1043 1048  dboot_multiboot_modcmdline(int index)
1044 1049  {
1045 1050          switch (multiboot_version) {
1046 1051          case 1:
1047 1052                  return ((char *)((mb_module_t *)
1048 1053                      mb_info->mods_addr)[index].mod_name);
1049 1054  
1050 1055          case 2:
1051 1056                  return (dboot_multiboot2_modcmdline(mb2_info, index));
  
    | 
      ↓ open down ↓ | 
    56 lines elided | 
    
      ↑ open up ↑ | 
  
1052 1057  
1053 1058          default:
1054 1059                  dboot_panic("Unknown multiboot version: %d\n",
1055 1060                      multiboot_version);
1056 1061                  break;
1057 1062          }
1058 1063          return (0);
1059 1064  }
1060 1065  
1061 1066  /*
1062      - * Find the environment module for console setup.
     1067 + * Find the modules used by console setup.
1063 1068   * Since we need the console to print early boot messages, the console is set up
1064      - * before anything else and therefore we need to pick up the environment module
1065      - * early too.
     1069 + * before anything else and therefore we need to pick up the needed modules.
1066 1070   *
1067      - * Note, we just will search for and if found, will pass the env
1068      - * module to console setup, the proper module list processing will happen later.
     1071 + * Note, we just will search for and if found, will pass the modules
     1072 + * to console setup, the proper module list processing will happen later.
     1073 + * Currenly used modules are boot environment and consoler font.
1069 1074   */
1070 1075  static void
1071      -dboot_find_env(void)
     1076 +dboot_find_console_modules(void)
1072 1077  {
1073 1078          int i, modcount;
1074 1079          uint32_t mod_start, mod_end;
1075 1080          char *cmdline;
1076 1081  
1077 1082          modcount = dboot_multiboot_modcount();
1078      -
     1083 +        bi->bi_module_cnt = 0;
1079 1084          for (i = 0; i < modcount; ++i) {
1080 1085                  cmdline = dboot_multiboot_modcmdline(i);
1081 1086                  if (cmdline == NULL)
1082 1087                          continue;
1083 1088  
1084      -                if (strstr(cmdline, "type=environment") == NULL)
     1089 +                if (strstr(cmdline, "type=console-font") != NULL)
     1090 +                        modules[bi->bi_module_cnt].bm_type = BMT_FONT;
     1091 +                else if (strstr(cmdline, "type=environment") != NULL)
     1092 +                        modules[bi->bi_module_cnt].bm_type = BMT_ENV;
     1093 +                else
1085 1094                          continue;
1086 1095  
1087 1096                  mod_start = dboot_multiboot_modstart(i);
1088 1097                  mod_end = dboot_multiboot_modend(i);
1089      -                modules[0].bm_addr = (native_ptr_t)(uintptr_t)mod_start;
1090      -                modules[0].bm_size = mod_end - mod_start;
1091      -                modules[0].bm_name = (native_ptr_t)(uintptr_t)NULL;
1092      -                modules[0].bm_hash = (native_ptr_t)(uintptr_t)NULL;
1093      -                modules[0].bm_type = BMT_ENV;
1094      -                bi->bi_modules = (native_ptr_t)(uintptr_t)modules;
1095      -                bi->bi_module_cnt = 1;
1096      -                return;
     1098 +                modules[bi->bi_module_cnt].bm_addr =
     1099 +                    (native_ptr_t)(uintptr_t)mod_start;
     1100 +                modules[bi->bi_module_cnt].bm_size = mod_end - mod_start;
     1101 +                modules[bi->bi_module_cnt].bm_name =
     1102 +                    (native_ptr_t)(uintptr_t)NULL;
     1103 +                modules[bi->bi_module_cnt].bm_hash =
     1104 +                    (native_ptr_t)(uintptr_t)NULL;
     1105 +                bi->bi_module_cnt++;
1097 1106          }
     1107 +        if (bi->bi_module_cnt != 0)
     1108 +                bi->bi_modules = (native_ptr_t)(uintptr_t)modules;
1098 1109  }
1099 1110  
1100 1111  static boolean_t
1101 1112  dboot_multiboot_basicmeminfo(uint32_t *lower, uint32_t *upper)
1102 1113  {
1103 1114          boolean_t rv = B_FALSE;
1104 1115  
1105 1116          switch (multiboot_version) {
1106 1117          case 1:
1107 1118                  if (mb_info->flags & 0x01) {
1108 1119                          *lower = mb_info->mem_lower;
1109 1120                          *upper = mb_info->mem_upper;
1110 1121                          rv = B_TRUE;
1111 1122                  }
1112 1123                  break;
1113 1124  
1114 1125          case 2:
1115 1126                  return (dboot_multiboot2_basicmeminfo(mb2_info, lower, upper));
1116 1127  
1117 1128          default:
1118 1129                  dboot_panic("Unknown multiboot version: %d\n",
1119 1130                      multiboot_version);
1120 1131                  break;
1121 1132          }
1122 1133          return (rv);
1123 1134  }
1124 1135  
1125 1136  static uint8_t
1126 1137  dboot_a2h(char v)
1127 1138  {
1128 1139          if (v >= 'a')
1129 1140                  return (v - 'a' + 0xa);
1130 1141          else if (v >= 'A')
1131 1142                  return (v - 'A' + 0xa);
1132 1143          else if (v >= '0')
1133 1144                  return (v - '0');
1134 1145          else
1135 1146                  dboot_panic("bad ASCII hex character %c\n", v);
1136 1147  
1137 1148          return (0);
1138 1149  }
1139 1150  
1140 1151  static void
1141 1152  digest_a2h(const char *ascii, uint8_t *digest)
1142 1153  {
1143 1154          unsigned int i;
1144 1155  
1145 1156          for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
1146 1157                  digest[i] = dboot_a2h(ascii[i * 2]) << 4;
1147 1158                  digest[i] |= dboot_a2h(ascii[i * 2 + 1]);
1148 1159          }
1149 1160  }
1150 1161  
1151 1162  /*
1152 1163   * Generate a SHA-1 hash of the first len bytes of image, and compare it with
1153 1164   * the ASCII-format hash found in the 40-byte buffer at ascii.  If they
1154 1165   * match, return 0, otherwise -1.  This works only for images smaller than
1155 1166   * 4 GB, which should not be a problem.
1156 1167   */
1157 1168  static int
1158 1169  check_image_hash(uint_t midx)
1159 1170  {
1160 1171          const char *ascii;
1161 1172          const void *image;
1162 1173          size_t len;
1163 1174          SHA1_CTX ctx;
1164 1175          uint8_t digest[SHA1_DIGEST_LENGTH];
1165 1176          uint8_t baseline[SHA1_DIGEST_LENGTH];
1166 1177          unsigned int i;
1167 1178  
1168 1179          ascii = (const char *)(uintptr_t)modules[midx].bm_hash;
1169 1180          image = (const void *)(uintptr_t)modules[midx].bm_addr;
1170 1181          len = (size_t)modules[midx].bm_size;
1171 1182  
1172 1183          digest_a2h(ascii, baseline);
1173 1184  
1174 1185          SHA1Init(&ctx);
1175 1186          SHA1Update(&ctx, image, len);
1176 1187          SHA1Final(digest, &ctx);
1177 1188  
1178 1189          for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
1179 1190                  if (digest[i] != baseline[i])
1180 1191                          return (-1);
1181 1192          }
1182 1193  
1183 1194          return (0);
1184 1195  }
1185 1196  
1186 1197  static const char *
1187 1198  type_to_str(boot_module_type_t type)
  
    | 
      ↓ open down ↓ | 
    80 lines elided | 
    
      ↑ open up ↑ | 
  
1188 1199  {
1189 1200          switch (type) {
1190 1201          case BMT_ROOTFS:
1191 1202                  return ("rootfs");
1192 1203          case BMT_FILE:
1193 1204                  return ("file");
1194 1205          case BMT_HASH:
1195 1206                  return ("hash");
1196 1207          case BMT_ENV:
1197 1208                  return ("environment");
     1209 +        case BMT_FONT:
     1210 +                return ("console-font");
1198 1211          default:
1199 1212                  return ("unknown");
1200 1213          }
1201 1214  }
1202 1215  
1203 1216  static void
1204 1217  check_images(void)
1205 1218  {
1206 1219          uint_t i;
1207 1220          char displayhash[SHA1_ASCII_LENGTH + 1];
1208 1221  
1209 1222          for (i = 0; i < modules_used; i++) {
1210 1223                  if (prom_debug) {
1211 1224                          dboot_printf("module #%d: name %s type %s "
1212 1225                              "addr %lx size %lx\n",
1213 1226                              i, (char *)(uintptr_t)modules[i].bm_name,
1214 1227                              type_to_str(modules[i].bm_type),
1215 1228                              (ulong_t)modules[i].bm_addr,
1216 1229                              (ulong_t)modules[i].bm_size);
1217 1230                  }
1218 1231  
1219 1232                  if (modules[i].bm_type == BMT_HASH ||
1220 1233                      modules[i].bm_hash == (native_ptr_t)(uintptr_t)NULL) {
1221 1234                          DBG_MSG("module has no hash; skipping check\n");
1222 1235                          continue;
1223 1236                  }
1224 1237                  (void) memcpy(displayhash,
1225 1238                      (void *)(uintptr_t)modules[i].bm_hash,
1226 1239                      SHA1_ASCII_LENGTH);
1227 1240                  displayhash[SHA1_ASCII_LENGTH] = '\0';
1228 1241                  if (prom_debug) {
1229 1242                          dboot_printf("checking expected hash [%s]: ",
1230 1243                              displayhash);
1231 1244                  }
1232 1245  
1233 1246                  if (check_image_hash(i) != 0)
1234 1247                          dboot_panic("hash mismatch!\n");
1235 1248                  else
1236 1249                          DBG_MSG("OK\n");
1237 1250          }
1238 1251  }
1239 1252  
1240 1253  /*
1241 1254   * Determine the module's starting address, size, name, and type, and fill the
1242 1255   * boot_modules structure.  This structure is used by the bop code, except for
1243 1256   * hashes which are checked prior to transferring control to the kernel.
1244 1257   */
1245 1258  static void
1246 1259  process_module(int midx)
1247 1260  {
1248 1261          uint32_t mod_start = dboot_multiboot_modstart(midx);
1249 1262          uint32_t mod_end = dboot_multiboot_modend(midx);
1250 1263          char *cmdline = dboot_multiboot_modcmdline(midx);
1251 1264          char *p, *q;
1252 1265  
1253 1266          check_higher(mod_end);
1254 1267          if (prom_debug) {
1255 1268                  dboot_printf("\tmodule #%d: '%s' at 0x%lx, end 0x%lx\n",
1256 1269                      midx, cmdline, (ulong_t)mod_start, (ulong_t)mod_end);
1257 1270          }
1258 1271  
1259 1272          if (mod_start > mod_end) {
1260 1273                  dboot_panic("module #%d: module start address 0x%lx greater "
1261 1274                      "than end address 0x%lx", midx,
1262 1275                      (ulong_t)mod_start, (ulong_t)mod_end);
1263 1276          }
1264 1277  
1265 1278          /*
1266 1279           * A brief note on lengths and sizes: GRUB, for reasons unknown, passes
1267 1280           * the address of the last valid byte in a module plus 1 as mod_end.
1268 1281           * This is of course a bug; the multiboot specification simply states
1269 1282           * that mod_start and mod_end "contain the start and end addresses of
1270 1283           * the boot module itself" which is pretty obviously not what GRUB is
1271 1284           * doing.  However, fixing it requires that not only this code be
1272 1285           * changed but also that other code consuming this value and values
1273 1286           * derived from it be fixed, and that the kernel and GRUB must either
1274 1287           * both have the bug or neither.  While there are a lot of combinations
1275 1288           * that will work, there are also some that won't, so for simplicity
1276 1289           * we'll just cope with the bug.  That means we won't actually hash the
1277 1290           * byte at mod_end, and we will expect that mod_end for the hash file
1278 1291           * itself is one greater than some multiple of 41 (40 bytes of ASCII
1279 1292           * hash plus a newline for each module).  We set bm_size to the true
1280 1293           * correct number of bytes in each module, achieving exactly this.
1281 1294           */
1282 1295  
1283 1296          modules[midx].bm_addr = (native_ptr_t)(uintptr_t)mod_start;
1284 1297          modules[midx].bm_size = mod_end - mod_start;
1285 1298          modules[midx].bm_name = (native_ptr_t)(uintptr_t)cmdline;
1286 1299          modules[midx].bm_hash = (native_ptr_t)(uintptr_t)NULL;
1287 1300          modules[midx].bm_type = BMT_FILE;
1288 1301  
1289 1302          if (cmdline == NULL) {
1290 1303                  modules[midx].bm_name = (native_ptr_t)(uintptr_t)noname;
1291 1304                  return;
1292 1305          }
1293 1306  
1294 1307          p = cmdline;
1295 1308          modules[midx].bm_name =
1296 1309              (native_ptr_t)(uintptr_t)strsep(&p, " \t\f\n\r");
1297 1310  
1298 1311          while (p != NULL) {
1299 1312                  q = strsep(&p, " \t\f\n\r");
1300 1313                  if (strncmp(q, "name=", 5) == 0) {
1301 1314                          if (q[5] != '\0' && !isspace(q[5])) {
1302 1315                                  modules[midx].bm_name =
1303 1316                                      (native_ptr_t)(uintptr_t)(q + 5);
1304 1317                          }
1305 1318                          continue;
1306 1319                  }
1307 1320  
  
    | 
      ↓ open down ↓ | 
    100 lines elided | 
    
      ↑ open up ↑ | 
  
1308 1321                  if (strncmp(q, "type=", 5) == 0) {
1309 1322                          if (q[5] == '\0' || isspace(q[5]))
1310 1323                                  continue;
1311 1324                          q += 5;
1312 1325                          if (strcmp(q, "rootfs") == 0) {
1313 1326                                  modules[midx].bm_type = BMT_ROOTFS;
1314 1327                          } else if (strcmp(q, "hash") == 0) {
1315 1328                                  modules[midx].bm_type = BMT_HASH;
1316 1329                          } else if (strcmp(q, "environment") == 0) {
1317 1330                                  modules[midx].bm_type = BMT_ENV;
     1331 +                        } else if (strcmp(q, "console-font") == 0) {
     1332 +                                modules[midx].bm_type = BMT_FONT;
1318 1333                          } else if (strcmp(q, "file") != 0) {
1319 1334                                  dboot_printf("\tmodule #%d: unknown module "
1320 1335                                      "type '%s'; defaulting to 'file'",
1321 1336                                      midx, q);
1322 1337                          }
1323 1338                          continue;
1324 1339                  }
1325 1340  
1326 1341                  if (strncmp(q, "hash=", 5) == 0) {
1327 1342                          if (q[5] != '\0' && !isspace(q[5])) {
1328 1343                                  modules[midx].bm_hash =
1329 1344                                      (native_ptr_t)(uintptr_t)(q + 5);
1330 1345                          }
1331 1346                          continue;
1332 1347                  }
1333 1348  
1334 1349                  dboot_printf("ignoring unknown option '%s'\n", q);
1335 1350          }
1336 1351  }
1337 1352  
1338 1353  /*
1339 1354   * Backward compatibility: if there are exactly one or two modules, both
1340 1355   * of type 'file' and neither with an embedded hash value, we have been
1341 1356   * given the legacy style modules.  In this case we need to treat the first
1342 1357   * module as a rootfs and the second as a hash referencing that module.
1343 1358   * Otherwise, even if the configuration is invalid, we assume that the
1344 1359   * operator knows what he's doing or at least isn't being bitten by this
1345 1360   * interface change.
1346 1361   */
1347 1362  static void
1348 1363  fixup_modules(void)
1349 1364  {
1350 1365          if (modules_used == 0 || modules_used > 2)
1351 1366                  return;
1352 1367  
1353 1368          if (modules[0].bm_type != BMT_FILE ||
1354 1369              modules_used > 1 && modules[1].bm_type != BMT_FILE) {
1355 1370                  return;
1356 1371          }
1357 1372  
1358 1373          if (modules[0].bm_hash != (native_ptr_t)(uintptr_t)NULL ||
1359 1374              modules_used > 1 &&
1360 1375              modules[1].bm_hash != (native_ptr_t)(uintptr_t)NULL) {
1361 1376                  return;
1362 1377          }
1363 1378  
1364 1379          modules[0].bm_type = BMT_ROOTFS;
1365 1380          if (modules_used > 1) {
1366 1381                  modules[1].bm_type = BMT_HASH;
1367 1382                  modules[1].bm_name = modules[0].bm_name;
1368 1383          }
1369 1384  }
1370 1385  
1371 1386  /*
1372 1387   * For modules that do not have assigned hashes but have a separate hash module,
1373 1388   * find the assigned hash module and set the primary module's bm_hash to point
1374 1389   * to the hash data from that module.  We will then ignore modules of type
1375 1390   * BMT_HASH from this point forward.
1376 1391   */
1377 1392  static void
1378 1393  assign_module_hashes(void)
1379 1394  {
1380 1395          uint_t i, j;
1381 1396  
1382 1397          for (i = 0; i < modules_used; i++) {
1383 1398                  if (modules[i].bm_type == BMT_HASH ||
1384 1399                      modules[i].bm_hash != (native_ptr_t)(uintptr_t)NULL) {
1385 1400                          continue;
1386 1401                  }
1387 1402  
1388 1403                  for (j = 0; j < modules_used; j++) {
1389 1404                          if (modules[j].bm_type != BMT_HASH ||
1390 1405                              strcmp((char *)(uintptr_t)modules[j].bm_name,
1391 1406                              (char *)(uintptr_t)modules[i].bm_name) != 0) {
1392 1407                                  continue;
1393 1408                          }
1394 1409  
1395 1410                          if (modules[j].bm_size < SHA1_ASCII_LENGTH) {
1396 1411                                  dboot_printf("Short hash module of length "
1397 1412                                      "0x%lx bytes; ignoring\n",
1398 1413                                      (ulong_t)modules[j].bm_size);
1399 1414                          } else {
1400 1415                                  modules[i].bm_hash = modules[j].bm_addr;
1401 1416                          }
1402 1417                          break;
1403 1418                  }
1404 1419          }
1405 1420  }
1406 1421  
1407 1422  /*
1408 1423   * Walk through the module information finding the last used address.
1409 1424   * The first available address will become the top level page table.
1410 1425   */
1411 1426  static void
1412 1427  dboot_process_modules(void)
1413 1428  {
1414 1429          int i, modcount;
1415 1430          extern char _end[];
1416 1431  
1417 1432          DBG_MSG("\nFinding Modules\n");
1418 1433          modcount = dboot_multiboot_modcount();
1419 1434          if (modcount > MAX_BOOT_MODULES) {
1420 1435                  dboot_panic("Too many modules (%d) -- the maximum is %d.",
1421 1436                      modcount, MAX_BOOT_MODULES);
1422 1437          }
1423 1438          /*
1424 1439           * search the modules to find the last used address
1425 1440           * we'll build the module list while we're walking through here
1426 1441           */
1427 1442          check_higher((paddr_t)(uintptr_t)&_end);
1428 1443          for (i = 0; i < modcount; ++i) {
1429 1444                  process_module(i);
1430 1445                  modules_used++;
1431 1446          }
1432 1447          bi->bi_modules = (native_ptr_t)(uintptr_t)modules;
1433 1448          DBG(bi->bi_modules);
1434 1449          bi->bi_module_cnt = modcount;
1435 1450          DBG(bi->bi_module_cnt);
1436 1451  
1437 1452          fixup_modules();
1438 1453          assign_module_hashes();
1439 1454          check_images();
1440 1455  }
1441 1456  
1442 1457  /*
1443 1458   * We then build the phys_install memlist from the multiboot information.
1444 1459   */
1445 1460  static void
1446 1461  dboot_process_mmap(void)
1447 1462  {
1448 1463          uint64_t start;
1449 1464          uint64_t end;
1450 1465          uint64_t page_offset = MMU_PAGEOFFSET;  /* needs to be 64 bits */
1451 1466          uint32_t lower, upper;
1452 1467          int i, mmap_entries;
1453 1468  
1454 1469          /*
1455 1470           * Walk through the memory map from multiboot and build our memlist
1456 1471           * structures. Note these will have native format pointers.
1457 1472           */
1458 1473          DBG_MSG("\nFinding Memory Map\n");
1459 1474          num_entries = 0;
1460 1475          num_entries_set = B_FALSE;
1461 1476          max_mem = 0;
1462 1477          if ((mmap_entries = dboot_loader_mmap_entries()) > 0) {
1463 1478                  for (i = 0; i < mmap_entries; i++) {
1464 1479                          uint32_t type = dboot_loader_mmap_get_type(i);
1465 1480                          start = dboot_loader_mmap_get_base(i);
1466 1481                          end = start + dboot_loader_mmap_get_length(i);
1467 1482  
1468 1483                          if (prom_debug)
1469 1484                                  dboot_printf("\ttype: %d %" PRIx64 "..%"
1470 1485                                      PRIx64 "\n", type, start, end);
1471 1486  
1472 1487                          /*
1473 1488                           * page align start and end
1474 1489                           */
1475 1490                          start = (start + page_offset) & ~page_offset;
1476 1491                          end &= ~page_offset;
1477 1492                          if (end <= start)
1478 1493                                  continue;
1479 1494  
1480 1495                          /*
1481 1496                           * only type 1 is usable RAM
1482 1497                           */
1483 1498                          switch (type) {
1484 1499                          case 1:
1485 1500                                  if (end > max_mem)
1486 1501                                          max_mem = end;
1487 1502                                  memlists[memlists_used].addr = start;
1488 1503                                  memlists[memlists_used].size = end - start;
1489 1504                                  ++memlists_used;
1490 1505                                  if (memlists_used > MAX_MEMLIST)
1491 1506                                          dboot_panic("too many memlists");
1492 1507                                  break;
1493 1508                          case 2:
1494 1509                                  rsvdmemlists[rsvdmemlists_used].addr = start;
1495 1510                                  rsvdmemlists[rsvdmemlists_used].size =
1496 1511                                      end - start;
1497 1512                                  ++rsvdmemlists_used;
1498 1513                                  if (rsvdmemlists_used > MAX_MEMLIST)
1499 1514                                          dboot_panic("too many rsvdmemlists");
1500 1515                                  break;
1501 1516                          default:
1502 1517                                  continue;
1503 1518                          }
1504 1519                  }
1505 1520                  build_pcimemlists();
1506 1521          } else if (dboot_multiboot_basicmeminfo(&lower, &upper)) {
1507 1522                  DBG(lower);
1508 1523                  memlists[memlists_used].addr = 0;
1509 1524                  memlists[memlists_used].size = lower * 1024;
1510 1525                  ++memlists_used;
1511 1526                  DBG(upper);
1512 1527                  memlists[memlists_used].addr = 1024 * 1024;
1513 1528                  memlists[memlists_used].size = upper * 1024;
1514 1529                  ++memlists_used;
1515 1530  
1516 1531                  /*
1517 1532                   * Old platform - assume I/O space at the end of memory.
1518 1533                   */
1519 1534                  pcimemlists[0].addr = (upper * 1024) + (1024 * 1024);
1520 1535                  pcimemlists[0].size = pci_hi_limit - pcimemlists[0].addr;
1521 1536                  pcimemlists[0].next = 0;
1522 1537                  pcimemlists[0].prev = 0;
1523 1538                  bi->bi_pcimem = (native_ptr_t)(uintptr_t)pcimemlists;
1524 1539                  DBG(bi->bi_pcimem);
1525 1540          } else {
1526 1541                  dboot_panic("No memory info from boot loader!!!");
1527 1542          }
1528 1543  
1529 1544          /*
1530 1545           * finish processing the physinstall list
1531 1546           */
1532 1547          sort_physinstall();
1533 1548  
1534 1549          /*
1535 1550           * build bios reserved mem lists
1536 1551           */
1537 1552          build_rsvdmemlists();
1538 1553  }
1539 1554  
1540 1555  /*
1541 1556   * The highest address is used as the starting point for dboot's simple
1542 1557   * memory allocator.
1543 1558   *
1544 1559   * Finding the highest address in case of Multiboot 1 protocol is
1545 1560   * quite painful in the sense that some information provided by
1546 1561   * the multiboot info structure points to BIOS data, and some to RAM.
1547 1562   *
1548 1563   * The module list was processed and checked already by dboot_process_modules(),
1549 1564   * so we will check the command line string and the memory map.
1550 1565   *
1551 1566   * This list of to be checked items is based on our current knowledge of
1552 1567   * allocations made by grub1 and will need to be reviewed if there
1553 1568   * are updates about the information provided by Multiboot 1.
1554 1569   *
1555 1570   * In the case of the Multiboot 2, our life is much simpler, as the MB2
1556 1571   * information tag list is one contiguous chunk of memory.
1557 1572   */
1558 1573  static paddr_t
1559 1574  dboot_multiboot1_highest_addr(void)
1560 1575  {
1561 1576          paddr_t addr = (paddr_t)(uintptr_t)NULL;
1562 1577          char *cmdl = (char *)mb_info->cmdline;
1563 1578  
1564 1579          if (mb_info->flags & MB_INFO_CMDLINE)
1565 1580                  addr = ((paddr_t)((uintptr_t)cmdl + strlen(cmdl) + 1));
1566 1581  
1567 1582          if (mb_info->flags & MB_INFO_MEM_MAP)
1568 1583                  addr = MAX(addr,
1569 1584                      ((paddr_t)(mb_info->mmap_addr + mb_info->mmap_length)));
1570 1585          return (addr);
1571 1586  }
1572 1587  
1573 1588  static void
1574 1589  dboot_multiboot_highest_addr(void)
1575 1590  {
1576 1591          paddr_t addr;
1577 1592  
1578 1593          switch (multiboot_version) {
1579 1594          case 1:
1580 1595                  addr = dboot_multiboot1_highest_addr();
1581 1596                  if (addr != (paddr_t)(uintptr_t)NULL)
1582 1597                          check_higher(addr);
1583 1598                  break;
1584 1599          case 2:
1585 1600                  addr = dboot_multiboot2_highest_addr(mb2_info);
1586 1601                  if (addr != (paddr_t)(uintptr_t)NULL)
1587 1602                          check_higher(addr);
1588 1603                  break;
1589 1604          default:
1590 1605                  dboot_panic("Unknown multiboot version: %d\n",
1591 1606                      multiboot_version);
1592 1607                  break;
1593 1608          }
1594 1609  }
1595 1610  
1596 1611  /*
1597 1612   * Walk the boot loader provided information and find the highest free address.
1598 1613   */
1599 1614  static void
1600 1615  init_mem_alloc(void)
1601 1616  {
1602 1617          DBG_MSG("Entered init_mem_alloc()\n");
1603 1618          dboot_process_modules();
1604 1619          dboot_process_mmap();
1605 1620          dboot_multiboot_highest_addr();
1606 1621  }
1607 1622  
1608 1623  static int
1609 1624  dboot_same_guids(efi_guid_t *g1, efi_guid_t *g2)
1610 1625  {
1611 1626          int i;
1612 1627  
1613 1628          if (g1->time_low != g2->time_low)
1614 1629                  return (0);
1615 1630          if (g1->time_mid != g2->time_mid)
1616 1631                  return (0);
1617 1632          if (g1->time_hi_and_version != g2->time_hi_and_version)
1618 1633                  return (0);
1619 1634          if (g1->clock_seq_hi_and_reserved != g2->clock_seq_hi_and_reserved)
1620 1635                  return (0);
1621 1636          if (g1->clock_seq_low != g2->clock_seq_low)
1622 1637                  return (0);
1623 1638  
1624 1639          for (i = 0; i < 6; i++) {
1625 1640                  if (g1->node_addr[i] != g2->node_addr[i])
1626 1641                          return (0);
1627 1642          }
1628 1643          return (1);
1629 1644  }
1630 1645  
1631 1646  static void
1632 1647  process_efi32(EFI_SYSTEM_TABLE32 *efi)
1633 1648  {
1634 1649          uint32_t entries;
1635 1650          EFI_CONFIGURATION_TABLE32 *config;
1636 1651          int i;
1637 1652  
1638 1653          entries = efi->NumberOfTableEntries;
1639 1654          config = (EFI_CONFIGURATION_TABLE32 *)(uintptr_t)
1640 1655              efi->ConfigurationTable;
1641 1656  
1642 1657          for (i = 0; i < entries; i++) {
1643 1658                  if (dboot_same_guids(&config[i].VendorGuid, &smbios3)) {
1644 1659                          bi->bi_smbios = (native_ptr_t)(uintptr_t)
1645 1660                              config[i].VendorTable;
1646 1661                  }
1647 1662                  if (bi->bi_smbios == NULL &&
1648 1663                      dboot_same_guids(&config[i].VendorGuid, &smbios)) {
1649 1664                          bi->bi_smbios = (native_ptr_t)(uintptr_t)
1650 1665                              config[i].VendorTable;
1651 1666                  }
1652 1667                  if (dboot_same_guids(&config[i].VendorGuid, &acpi2)) {
1653 1668                          bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
1654 1669                              config[i].VendorTable;
1655 1670                  }
1656 1671                  if (bi->bi_acpi_rsdp == NULL &&
1657 1672                      dboot_same_guids(&config[i].VendorGuid, &acpi1)) {
1658 1673                          bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
1659 1674                              config[i].VendorTable;
1660 1675                  }
1661 1676          }
1662 1677  }
1663 1678  
1664 1679  static void
1665 1680  process_efi64(EFI_SYSTEM_TABLE64 *efi)
1666 1681  {
1667 1682          uint64_t entries;
1668 1683          EFI_CONFIGURATION_TABLE64 *config;
1669 1684          int i;
1670 1685  
1671 1686          entries = efi->NumberOfTableEntries;
1672 1687          config = (EFI_CONFIGURATION_TABLE64 *)(uintptr_t)
1673 1688              efi->ConfigurationTable;
1674 1689  
1675 1690          for (i = 0; i < entries; i++) {
1676 1691                  if (dboot_same_guids(&config[i].VendorGuid, &smbios3)) {
1677 1692                          bi->bi_smbios = (native_ptr_t)(uintptr_t)
1678 1693                              config[i].VendorTable;
1679 1694                  }
1680 1695                  if (bi->bi_smbios == NULL &&
1681 1696                      dboot_same_guids(&config[i].VendorGuid, &smbios)) {
1682 1697                          bi->bi_smbios = (native_ptr_t)(uintptr_t)
1683 1698                              config[i].VendorTable;
1684 1699                  }
1685 1700                  /* Prefer acpi v2+ over v1. */
1686 1701                  if (dboot_same_guids(&config[i].VendorGuid, &acpi2)) {
1687 1702                          bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
1688 1703                              config[i].VendorTable;
1689 1704                  }
1690 1705                  if (bi->bi_acpi_rsdp == NULL &&
1691 1706                      dboot_same_guids(&config[i].VendorGuid, &acpi1)) {
1692 1707                          bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
1693 1708                              config[i].VendorTable;
1694 1709                  }
1695 1710          }
1696 1711  }
1697 1712  
1698 1713  static void
1699 1714  dboot_multiboot_get_fwtables(void)
1700 1715  {
1701 1716          multiboot_tag_new_acpi_t *nacpitagp;
1702 1717          multiboot_tag_old_acpi_t *oacpitagp;
1703 1718          multiboot_tag_efi64_t *efi64tagp = NULL;
1704 1719          multiboot_tag_efi32_t *efi32tagp = NULL;
1705 1720  
1706 1721          /* no fw tables from multiboot 1 */
1707 1722          if (multiboot_version != 2)
1708 1723                  return;
1709 1724  
1710 1725          efi64tagp = (multiboot_tag_efi64_t *)
1711 1726              dboot_multiboot2_find_tag(mb2_info, MULTIBOOT_TAG_TYPE_EFI64);
1712 1727          if (efi64tagp != NULL) {
1713 1728                  bi->bi_uefi_arch = XBI_UEFI_ARCH_64;
1714 1729                  bi->bi_uefi_systab = (native_ptr_t)(uintptr_t)
1715 1730                      efi64tagp->mb_pointer;
1716 1731                  process_efi64((EFI_SYSTEM_TABLE64 *)(uintptr_t)
1717 1732                      efi64tagp->mb_pointer);
1718 1733          } else {
1719 1734                  efi32tagp = (multiboot_tag_efi32_t *)
1720 1735                      dboot_multiboot2_find_tag(mb2_info,
1721 1736                      MULTIBOOT_TAG_TYPE_EFI32);
1722 1737                  if (efi32tagp != NULL) {
1723 1738                          bi->bi_uefi_arch = XBI_UEFI_ARCH_32;
1724 1739                          bi->bi_uefi_systab = (native_ptr_t)(uintptr_t)
1725 1740                              efi32tagp->mb_pointer;
1726 1741                          process_efi32((EFI_SYSTEM_TABLE32 *)(uintptr_t)
1727 1742                              efi32tagp->mb_pointer);
1728 1743                  }
1729 1744          }
1730 1745  
1731 1746          /*
1732 1747           * The ACPI RSDP can be found by scanning the BIOS memory areas or
1733 1748           * from the EFI system table. The boot loader may pass in the address
1734 1749           * it found the ACPI tables at.
1735 1750           */
1736 1751          nacpitagp = (multiboot_tag_new_acpi_t *)
1737 1752              dboot_multiboot2_find_tag(mb2_info,
1738 1753              MULTIBOOT_TAG_TYPE_ACPI_NEW);
1739 1754          oacpitagp = (multiboot_tag_old_acpi_t *)
1740 1755              dboot_multiboot2_find_tag(mb2_info,
1741 1756              MULTIBOOT_TAG_TYPE_ACPI_OLD);
1742 1757  
1743 1758          if (nacpitagp != NULL) {
1744 1759                  bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
1745 1760                      &nacpitagp->mb_rsdp[0];
1746 1761          } else if (oacpitagp != NULL) {
1747 1762                  bi->bi_acpi_rsdp = (native_ptr_t)(uintptr_t)
1748 1763                      &oacpitagp->mb_rsdp[0];
1749 1764          }
1750 1765  }
1751 1766  
1752 1767  /* print out EFI version string with newline */
1753 1768  static void
1754 1769  dboot_print_efi_version(uint32_t ver)
1755 1770  {
1756 1771          int rev;
1757 1772  
1758 1773          dboot_printf("%d.", EFI_REV_MAJOR(ver));
1759 1774  
1760 1775          rev = EFI_REV_MINOR(ver);
1761 1776          if ((rev % 10) != 0) {
1762 1777                  dboot_printf("%d.%d\n", rev / 10, rev % 10);
1763 1778          } else {
1764 1779                  dboot_printf("%d\n", rev / 10);
1765 1780          }
1766 1781  }
1767 1782  
1768 1783  static void
1769 1784  print_efi32(EFI_SYSTEM_TABLE32 *efi)
1770 1785  {
1771 1786          uint16_t *data;
1772 1787          EFI_CONFIGURATION_TABLE32 *conf;
1773 1788          int i;
1774 1789  
1775 1790          dboot_printf("EFI32 signature: %llx\n",
1776 1791              (unsigned long long)efi->Hdr.Signature);
1777 1792          dboot_printf("EFI system version: ");
1778 1793          dboot_print_efi_version(efi->Hdr.Revision);
1779 1794          dboot_printf("EFI system vendor: ");
1780 1795          data = (uint16_t *)(uintptr_t)efi->FirmwareVendor;
1781 1796          for (i = 0; data[i] != 0; i++)
1782 1797                  dboot_printf("%c", (char)data[i]);
1783 1798          dboot_printf("\nEFI firmware revision: ");
1784 1799          dboot_print_efi_version(efi->FirmwareRevision);
1785 1800          dboot_printf("EFI system table number of entries: %d\n",
1786 1801              efi->NumberOfTableEntries);
1787 1802          conf = (EFI_CONFIGURATION_TABLE32 *)(uintptr_t)
1788 1803              efi->ConfigurationTable;
1789 1804          for (i = 0; i < (int)efi->NumberOfTableEntries; i++) {
1790 1805                  dboot_printf("%d: 0x%x 0x%x 0x%x 0x%x 0x%x", i,
1791 1806                      conf[i].VendorGuid.time_low,
1792 1807                      conf[i].VendorGuid.time_mid,
1793 1808                      conf[i].VendorGuid.time_hi_and_version,
1794 1809                      conf[i].VendorGuid.clock_seq_hi_and_reserved,
1795 1810                      conf[i].VendorGuid.clock_seq_low);
1796 1811                  dboot_printf(" 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1797 1812                      conf[i].VendorGuid.node_addr[0],
1798 1813                      conf[i].VendorGuid.node_addr[1],
1799 1814                      conf[i].VendorGuid.node_addr[2],
1800 1815                      conf[i].VendorGuid.node_addr[3],
1801 1816                      conf[i].VendorGuid.node_addr[4],
1802 1817                      conf[i].VendorGuid.node_addr[5]);
1803 1818          }
1804 1819  }
1805 1820  
1806 1821  static void
1807 1822  print_efi64(EFI_SYSTEM_TABLE64 *efi)
1808 1823  {
1809 1824          uint16_t *data;
1810 1825          EFI_CONFIGURATION_TABLE64 *conf;
1811 1826          int i;
1812 1827  
1813 1828          dboot_printf("EFI64 signature: %llx\n",
1814 1829              (unsigned long long)efi->Hdr.Signature);
1815 1830          dboot_printf("EFI system version: ");
1816 1831          dboot_print_efi_version(efi->Hdr.Revision);
1817 1832          dboot_printf("EFI system vendor: ");
1818 1833          data = (uint16_t *)(uintptr_t)efi->FirmwareVendor;
1819 1834          for (i = 0; data[i] != 0; i++)
1820 1835                  dboot_printf("%c", (char)data[i]);
1821 1836          dboot_printf("\nEFI firmware revision: ");
1822 1837          dboot_print_efi_version(efi->FirmwareRevision);
1823 1838          dboot_printf("EFI system table number of entries: %lld\n",
1824 1839              efi->NumberOfTableEntries);
1825 1840          conf = (EFI_CONFIGURATION_TABLE64 *)(uintptr_t)
1826 1841              efi->ConfigurationTable;
1827 1842          for (i = 0; i < (int)efi->NumberOfTableEntries; i++) {
1828 1843                  dboot_printf("%d: 0x%x 0x%x 0x%x 0x%x 0x%x", i,
1829 1844                      conf[i].VendorGuid.time_low,
1830 1845                      conf[i].VendorGuid.time_mid,
1831 1846                      conf[i].VendorGuid.time_hi_and_version,
1832 1847                      conf[i].VendorGuid.clock_seq_hi_and_reserved,
1833 1848                      conf[i].VendorGuid.clock_seq_low);
1834 1849                  dboot_printf(" 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1835 1850                      conf[i].VendorGuid.node_addr[0],
1836 1851                      conf[i].VendorGuid.node_addr[1],
1837 1852                      conf[i].VendorGuid.node_addr[2],
1838 1853                      conf[i].VendorGuid.node_addr[3],
1839 1854                      conf[i].VendorGuid.node_addr[4],
1840 1855                      conf[i].VendorGuid.node_addr[5]);
1841 1856          }
1842 1857  }
1843 1858  #endif /* !__xpv */
1844 1859  
1845 1860  /*
1846 1861   * Simple memory allocator, allocates aligned physical memory.
1847 1862   * Note that startup_kernel() only allocates memory, never frees.
1848 1863   * Memory usage just grows in an upward direction.
1849 1864   */
1850 1865  static void *
1851 1866  do_mem_alloc(uint32_t size, uint32_t align)
1852 1867  {
1853 1868          uint_t i;
1854 1869          uint64_t best;
1855 1870          uint64_t start;
1856 1871          uint64_t end;
1857 1872  
1858 1873          /*
1859 1874           * make sure size is a multiple of pagesize
1860 1875           */
1861 1876          size = RNDUP(size, MMU_PAGESIZE);
1862 1877          next_avail_addr = RNDUP(next_avail_addr, align);
1863 1878  
1864 1879          /*
1865 1880           * XXPV fixme joe
1866 1881           *
1867 1882           * a really large bootarchive that causes you to run out of memory
1868 1883           * may cause this to blow up
1869 1884           */
1870 1885          /* LINTED E_UNEXPECTED_UINT_PROMOTION */
1871 1886          best = (uint64_t)-size;
1872 1887          for (i = 0; i < memlists_used; ++i) {
1873 1888                  start = memlists[i].addr;
1874 1889  #if defined(__xpv)
1875 1890                  start += mfn_base;
1876 1891  #endif
1877 1892                  end = start + memlists[i].size;
1878 1893  
1879 1894                  /*
1880 1895                   * did we find the desired address?
1881 1896                   */
1882 1897                  if (start <= next_avail_addr && next_avail_addr + size <= end) {
1883 1898                          best = next_avail_addr;
1884 1899                          goto done;
1885 1900                  }
1886 1901  
1887 1902                  /*
1888 1903                   * if not is this address the best so far?
1889 1904                   */
1890 1905                  if (start > next_avail_addr && start < best &&
1891 1906                      RNDUP(start, align) + size <= end)
1892 1907                          best = RNDUP(start, align);
1893 1908          }
1894 1909  
1895 1910          /*
1896 1911           * We didn't find exactly the address we wanted, due to going off the
1897 1912           * end of a memory region. Return the best found memory address.
1898 1913           */
1899 1914  done:
1900 1915          next_avail_addr = best + size;
1901 1916  #if defined(__xpv)
1902 1917          if (next_avail_addr > scratch_end)
1903 1918                  dboot_panic("Out of mem next_avail: 0x%lx, scratch_end: "
1904 1919                      "0x%lx", (ulong_t)next_avail_addr,
1905 1920                      (ulong_t)scratch_end);
1906 1921  #endif
1907 1922          (void) memset((void *)(uintptr_t)best, 0, size);
1908 1923          return ((void *)(uintptr_t)best);
1909 1924  }
1910 1925  
1911 1926  void *
1912 1927  mem_alloc(uint32_t size)
1913 1928  {
1914 1929          return (do_mem_alloc(size, MMU_PAGESIZE));
1915 1930  }
1916 1931  
1917 1932  
1918 1933  /*
1919 1934   * Build page tables to map all of memory used so far as well as the kernel.
1920 1935   */
1921 1936  static void
1922 1937  build_page_tables(void)
1923 1938  {
1924 1939          uint32_t psize;
1925 1940          uint32_t level;
1926 1941          uint32_t off;
1927 1942          uint64_t start;
1928 1943  #if !defined(__xpv)
1929 1944          uint32_t i;
1930 1945          uint64_t end;
1931 1946  #endif  /* __xpv */
1932 1947  
1933 1948          /*
1934 1949           * If we're on metal, we need to create the top level pagetable.
1935 1950           */
1936 1951  #if defined(__xpv)
1937 1952          top_page_table = (paddr_t)(uintptr_t)xen_info->pt_base;
1938 1953  #else /* __xpv */
1939 1954          top_page_table = (paddr_t)(uintptr_t)mem_alloc(MMU_PAGESIZE);
1940 1955  #endif /* __xpv */
1941 1956          DBG((uintptr_t)top_page_table);
1942 1957  
1943 1958          /*
1944 1959           * Determine if we'll use large mappings for kernel, then map it.
1945 1960           */
1946 1961          if (largepage_support) {
1947 1962                  psize = lpagesize;
1948 1963                  level = 1;
1949 1964          } else {
1950 1965                  psize = MMU_PAGESIZE;
1951 1966                  level = 0;
1952 1967          }
1953 1968  
1954 1969          DBG_MSG("Mapping kernel\n");
1955 1970          DBG(ktext_phys);
1956 1971          DBG(target_kernel_text);
1957 1972          DBG(ksize);
1958 1973          DBG(psize);
1959 1974          for (off = 0; off < ksize; off += psize)
1960 1975                  map_pa_at_va(ktext_phys + off, target_kernel_text + off, level);
1961 1976  
1962 1977          /*
1963 1978           * The kernel will need a 1 page window to work with page tables
1964 1979           */
1965 1980          bi->bi_pt_window = (native_ptr_t)(uintptr_t)mem_alloc(MMU_PAGESIZE);
1966 1981          DBG(bi->bi_pt_window);
1967 1982          bi->bi_pte_to_pt_window =
1968 1983              (native_ptr_t)(uintptr_t)find_pte(bi->bi_pt_window, NULL, 0, 0);
1969 1984          DBG(bi->bi_pte_to_pt_window);
1970 1985  
1971 1986  #if defined(__xpv)
1972 1987          if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
1973 1988                  /* If this is a domU we're done. */
1974 1989                  DBG_MSG("\nPage tables constructed\n");
1975 1990                  return;
1976 1991          }
1977 1992  #endif /* __xpv */
1978 1993  
1979 1994          /*
1980 1995           * We need 1:1 mappings for the lower 1M of memory to access
1981 1996           * BIOS tables used by a couple of drivers during boot.
1982 1997           *
1983 1998           * The following code works because our simple memory allocator
1984 1999           * only grows usage in an upwards direction.
1985 2000           *
1986 2001           * Note that by this point in boot some mappings for low memory
1987 2002           * may already exist because we've already accessed device in low
1988 2003           * memory.  (Specifically the video frame buffer and keyboard
1989 2004           * status ports.)  If we're booting on raw hardware then GRUB
1990 2005           * created these mappings for us.  If we're booting under a
1991 2006           * hypervisor then we went ahead and remapped these devices into
1992 2007           * memory allocated within dboot itself.
1993 2008           */
1994 2009          if (map_debug)
1995 2010                  dboot_printf("1:1 map pa=0..1Meg\n");
1996 2011          for (start = 0; start < 1024 * 1024; start += MMU_PAGESIZE) {
1997 2012  #if defined(__xpv)
1998 2013                  map_ma_at_va(start, start, 0);
1999 2014  #else /* __xpv */
2000 2015                  map_pa_at_va(start, start, 0);
2001 2016  #endif /* __xpv */
2002 2017          }
2003 2018  
2004 2019  #if !defined(__xpv)
2005 2020  
2006 2021          for (i = 0; i < memlists_used; ++i) {
2007 2022                  start = memlists[i].addr;
2008 2023                  end = start + memlists[i].size;
2009 2024  
2010 2025                  if (map_debug)
2011 2026                          dboot_printf("1:1 map pa=%" PRIx64 "..%" PRIx64 "\n",
2012 2027                              start, end);
2013 2028                  while (start < end && start < next_avail_addr) {
2014 2029                          map_pa_at_va(start, start, 0);
  
    | 
      ↓ open down ↓ | 
    687 lines elided | 
    
      ↑ open up ↑ | 
  
2015 2030                          start += MMU_PAGESIZE;
2016 2031                  }
2017 2032                  if (start >= next_avail_addr)
2018 2033                          break;
2019 2034          }
2020 2035  
2021 2036          /*
2022 2037           * Map framebuffer memory as PT_NOCACHE as this is memory from a
2023 2038           * device and therefore must not be cached.
2024 2039           */
2025      -        if (bi->bi_framebuffer != NULL) {
2026      -                multiboot_tag_framebuffer_t *fb;
2027      -                fb = (multiboot_tag_framebuffer_t *)(uintptr_t)
2028      -                    bi->bi_framebuffer;
     2040 +        if (fb != NULL && fb->framebuffer != 0) {
     2041 +                multiboot_tag_framebuffer_t *fb_tagp;
     2042 +                fb_tagp = (multiboot_tag_framebuffer_t *)(uintptr_t)
     2043 +                    fb->framebuffer;
2029 2044  
2030      -                start = fb->framebuffer_common.framebuffer_addr;
2031      -                end = start + fb->framebuffer_common.framebuffer_height *
2032      -                    fb->framebuffer_common.framebuffer_pitch;
     2045 +                start = fb_tagp->framebuffer_common.framebuffer_addr;
     2046 +                end = start + fb_tagp->framebuffer_common.framebuffer_height *
     2047 +                    fb_tagp->framebuffer_common.framebuffer_pitch;
2033 2048  
2034      -                pte_bits |= PT_NOCACHE;
2035      -                while (start < end) {
2036      -                        map_pa_at_va(start, start, 0);
2037      -                        start += MMU_PAGESIZE;
     2049 +                /* VGA text memory is already mapped. */
     2050 +                if (fb_tagp->framebuffer_common.framebuffer_type !=
     2051 +                    MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT) {
     2052 +                        uint64_t vaddr;
     2053 +
     2054 +#if defined(_BOOT_TARGET_amd64)
     2055 +                        vaddr = start;
     2056 +#else
     2057 +                        vaddr = (uintptr_t)mem_alloc(end - start);
     2058 +#endif
     2059 +                        fb->boot_fb_virt = vaddr;
     2060 +                        if (map_debug) {
     2061 +                                dboot_printf("FB map pa=%" PRIx64 "..%"
     2062 +                                    PRIx64 "\n", start, end);
     2063 +                        }
     2064 +
     2065 +                        pte_bits |= PT_NOCACHE;
     2066 +                        if (PAT_support != 0)
     2067 +                                pte_bits |= PT_PAT_4K;
     2068 +
     2069 +                        while (start < end) {
     2070 +                                map_pa_at_va(start, vaddr, 0);
     2071 +                                start += MMU_PAGESIZE;
     2072 +                                vaddr += MMU_PAGESIZE;
     2073 +                        }
     2074 +                        pte_bits &= ~PT_NOCACHE;
     2075 +                        if (PAT_support != 0)
     2076 +                                pte_bits &= ~PT_PAT_4K;
2038 2077                  }
2039      -                pte_bits &= ~PT_NOCACHE;
2040 2078          }
2041 2079  #endif /* !__xpv */
2042 2080  
2043 2081          DBG_MSG("\nPage tables constructed\n");
2044 2082  }
2045 2083  
2046 2084  #define NO_MULTIBOOT    \
2047 2085  "multiboot is no longer used to boot the Solaris Operating System.\n\
2048 2086  The grub entry should be changed to:\n\
2049 2087  kernel$ /platform/i86pc/kernel/$ISADIR/unix\n\
2050 2088  module$ /platform/i86pc/$ISADIR/boot_archive\n\
2051 2089  See http://illumos.org/msg/SUNOS-8000-AK for details.\n"
2052 2090  
2053 2091  static void
2054 2092  dboot_init_xboot_consinfo(void)
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
2055 2093  {
2056 2094          uintptr_t addr;
2057 2095          /*
2058 2096           * boot info must be 16 byte aligned for 64 bit kernel ABI
2059 2097           */
2060 2098          addr = (uintptr_t)boot_info;
2061 2099          addr = (addr + 0xf) & ~0xf;
2062 2100          bi = (struct xboot_info *)addr;
2063 2101  
2064 2102  #if !defined(__xpv)
     2103 +        /*
     2104 +         * fb info must be 16 byte aligned for 64 bit kernel ABI
     2105 +         */
     2106 +        addr = (uintptr_t)framebuffer;
     2107 +        addr = (addr + 0xf) & ~0xf;
     2108 +        fb = (boot_framebuffer_t *)addr;
     2109 +        bi->bi_framebuffer = (native_ptr_t)(uintptr_t)fb;
     2110 +
2065 2111          switch (multiboot_version) {
2066 2112          case 1:
2067 2113                  dboot_multiboot1_xboot_consinfo();
2068 2114                  break;
2069 2115          case 2:
2070 2116                  dboot_multiboot2_xboot_consinfo();
2071 2117                  break;
2072 2118          default:
2073 2119                  dboot_panic("Unknown multiboot version: %d\n",
2074 2120                      multiboot_version);
2075 2121                  break;
2076 2122          }
2077 2123          /*
2078 2124           * Lookup environment module for the console. Complete module list
2079 2125           * will be built after console setup.
2080 2126           */
2081      -        dboot_find_env();
     2127 +        dboot_find_console_modules();
2082 2128  #endif
2083 2129  }
2084 2130  
2085 2131  /*
2086 2132   * Set up basic data from the boot loader.
2087 2133   * The load_addr is part of AOUT kludge setup in dboot_grub.s, to support
2088 2134   * 32-bit dboot code setup used to set up and start 64-bit kernel.
2089 2135   * AOUT kludge does allow 32-bit boot loader, such as grub1, to load and
2090 2136   * start 64-bit illumos kernel.
2091 2137   */
2092 2138  static void
2093 2139  dboot_loader_init(void)
2094 2140  {
2095 2141  #if !defined(__xpv)
2096 2142          mb_info = NULL;
2097 2143          mb2_info = NULL;
2098 2144  
2099 2145          switch (mb_magic) {
2100 2146          case MB_BOOTLOADER_MAGIC:
2101 2147                  multiboot_version = 1;
2102 2148                  mb_info = (multiboot_info_t *)(uintptr_t)mb_addr;
2103 2149  #if defined(_BOOT_TARGET_amd64)
2104 2150                  load_addr = mb_header.load_addr;
2105 2151  #endif
2106 2152                  break;
2107 2153  
2108 2154          case MULTIBOOT2_BOOTLOADER_MAGIC:
2109 2155                  multiboot_version = 2;
2110 2156                  mb2_info = (multiboot2_info_header_t *)(uintptr_t)mb_addr;
2111 2157                  mb2_mmap_tagp = dboot_multiboot2_get_mmap_tagp(mb2_info);
2112 2158  #if defined(_BOOT_TARGET_amd64)
2113 2159                  load_addr = mb2_load_addr;
2114 2160  #endif
2115 2161                  break;
2116 2162  
2117 2163          default:
2118 2164                  dboot_panic("Unknown bootloader magic: 0x%x\n", mb_magic);
2119 2165                  break;
2120 2166          }
2121 2167  #endif  /* !defined(__xpv) */
2122 2168  }
2123 2169  
2124 2170  /* Extract the kernel command line from [multi]boot information. */
2125 2171  static char *
2126 2172  dboot_loader_cmdline(void)
2127 2173  {
2128 2174          char *line = NULL;
2129 2175  
2130 2176  #if defined(__xpv)
2131 2177          line = (char *)xen_info->cmd_line;
2132 2178  #else /* __xpv */
2133 2179  
2134 2180          switch (multiboot_version) {
2135 2181          case 1:
2136 2182                  if (mb_info->flags & MB_INFO_CMDLINE)
2137 2183                          line = (char *)mb_info->cmdline;
2138 2184                  break;
2139 2185  
2140 2186          case 2:
2141 2187                  line = dboot_multiboot2_cmdline(mb2_info);
2142 2188                  break;
2143 2189  
2144 2190          default:
2145 2191                  dboot_panic("Unknown multiboot version: %d\n",
2146 2192                      multiboot_version);
2147 2193                  break;
2148 2194          }
2149 2195  
2150 2196  #endif /* __xpv */
2151 2197  
2152 2198          /*
2153 2199           * Make sure we have valid pointer so the string operations
2154 2200           * will not crash us.
2155 2201           */
2156 2202          if (line == NULL)
2157 2203                  line = "";
2158 2204  
2159 2205          return (line);
2160 2206  }
2161 2207  
2162 2208  static char *
2163 2209  dboot_loader_name(void)
2164 2210  {
2165 2211  #if defined(__xpv)
2166 2212          return (NULL);
2167 2213  #else /* __xpv */
2168 2214          multiboot_tag_string_t *tag;
2169 2215  
2170 2216          switch (multiboot_version) {
2171 2217          case 1:
2172 2218                  return ((char *)mb_info->boot_loader_name);
2173 2219  
2174 2220          case 2:
2175 2221                  tag = dboot_multiboot2_find_tag(mb2_info,
2176 2222                      MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME);
2177 2223                  return (tag->mb_string);
2178 2224          default:
2179 2225                  dboot_panic("Unknown multiboot version: %d\n",
2180 2226                      multiboot_version);
2181 2227                  break;
2182 2228          }
2183 2229  
2184 2230          return (NULL);
2185 2231  #endif /* __xpv */
2186 2232  }
2187 2233  
2188 2234  /*
2189 2235   * startup_kernel has a pretty simple job. It builds pagetables which reflect
2190 2236   * 1:1 mappings for all memory in use. It then also adds mappings for
2191 2237   * the kernel nucleus at virtual address of target_kernel_text using large page
2192 2238   * mappings. The page table pages are also accessible at 1:1 mapped
2193 2239   * virtual addresses.
2194 2240   */
  
    | 
      ↓ open down ↓ | 
    103 lines elided | 
    
      ↑ open up ↑ | 
  
2195 2241  /*ARGSUSED*/
2196 2242  void
2197 2243  startup_kernel(void)
2198 2244  {
2199 2245          char *cmdline;
2200 2246          char *bootloader;
2201 2247  #if defined(__xpv)
2202 2248          physdev_set_iopl_t set_iopl;
2203 2249  #endif /* __xpv */
2204 2250  
     2251 +        bcons_init(NULL);       /* Set very early console to ttya. */
2205 2252          dboot_loader_init();
2206 2253          /*
2207 2254           * At this point we are executing in a 32 bit real mode.
2208 2255           */
2209 2256  
2210 2257          bootloader = dboot_loader_name();
2211 2258          cmdline = dboot_loader_cmdline();
2212 2259  
2213 2260  #if defined(__xpv)
2214 2261          /*
2215 2262           * For dom0, before we initialize the console subsystem we'll
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
2216 2263           * need to enable io operations, so set I/O priveldge level to 1.
2217 2264           */
2218 2265          if (DOMAIN_IS_INITDOMAIN(xen_info)) {
2219 2266                  set_iopl.iopl = 1;
2220 2267                  (void) HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
2221 2268          }
2222 2269  #endif /* __xpv */
2223 2270  
2224 2271          dboot_init_xboot_consinfo();
2225 2272          bi->bi_cmdline = (native_ptr_t)(uintptr_t)cmdline;
2226      -        bcons_init(bi);
     2273 +        bcons_init(bi);         /* Now we can set the real console. */
2227 2274  
2228 2275          prom_debug = (find_boot_prop("prom_debug") != NULL);
2229 2276          map_debug = (find_boot_prop("map_debug") != NULL);
2230 2277  
2231 2278  #if !defined(__xpv)
2232 2279          dboot_multiboot_get_fwtables();
2233 2280  #endif
2234 2281          DBG_MSG("\n\nillumos prekernel set: ");
2235 2282          DBG_MSG(cmdline);
2236 2283          DBG_MSG("\n");
2237 2284  
2238 2285          if (bootloader != NULL && prom_debug) {
2239 2286                  dboot_printf("Kernel loaded by: %s\n", bootloader);
2240 2287  #if !defined(__xpv)
2241 2288                  dboot_printf("Using multiboot %d boot protocol.\n",
2242 2289                      multiboot_version);
2243 2290  #endif
2244 2291          }
2245 2292  
2246 2293          if (strstr(cmdline, "multiboot") != NULL) {
2247 2294                  dboot_panic(NO_MULTIBOOT);
2248 2295          }
2249 2296  
2250 2297          DBG((uintptr_t)bi);
2251 2298  #if !defined(__xpv)
2252 2299          DBG((uintptr_t)mb_info);
2253 2300          DBG((uintptr_t)mb2_info);
2254 2301          if (mb2_info != NULL)
2255 2302                  DBG(mb2_info->mbi_total_size);
2256 2303          DBG(bi->bi_acpi_rsdp);
2257 2304          DBG(bi->bi_smbios);
2258 2305          DBG(bi->bi_uefi_arch);
2259 2306          DBG(bi->bi_uefi_systab);
2260 2307  
2261 2308          if (bi->bi_uefi_systab && prom_debug) {
2262 2309                  if (bi->bi_uefi_arch == XBI_UEFI_ARCH_64) {
2263 2310                          print_efi64((EFI_SYSTEM_TABLE64 *)(uintptr_t)
2264 2311                              bi->bi_uefi_systab);
2265 2312                  } else {
2266 2313                          print_efi32((EFI_SYSTEM_TABLE32 *)(uintptr_t)
2267 2314                              bi->bi_uefi_systab);
2268 2315                  }
2269 2316          }
2270 2317  #endif
2271 2318  
2272 2319          /*
2273 2320           * Need correct target_kernel_text value
2274 2321           */
2275 2322  #if defined(_BOOT_TARGET_amd64)
2276 2323          target_kernel_text = KERNEL_TEXT_amd64;
2277 2324  #elif defined(__xpv)
2278 2325          target_kernel_text = KERNEL_TEXT_i386_xpv;
2279 2326  #else
2280 2327          target_kernel_text = KERNEL_TEXT_i386;
2281 2328  #endif
2282 2329          DBG(target_kernel_text);
2283 2330  
2284 2331  #if defined(__xpv)
2285 2332  
2286 2333          /*
2287 2334           * XXPV Derive this stuff from CPUID / what the hypervisor has enabled
2288 2335           */
2289 2336  
2290 2337  #if defined(_BOOT_TARGET_amd64)
2291 2338          /*
2292 2339           * 64-bit hypervisor.
2293 2340           */
2294 2341          amd64_support = 1;
2295 2342          pae_support = 1;
2296 2343  
2297 2344  #else   /* _BOOT_TARGET_amd64 */
2298 2345  
2299 2346          /*
2300 2347           * See if we are running on a PAE Hypervisor
2301 2348           */
2302 2349          {
2303 2350                  xen_capabilities_info_t caps;
2304 2351  
2305 2352                  if (HYPERVISOR_xen_version(XENVER_capabilities, &caps) != 0)
2306 2353                          dboot_panic("HYPERVISOR_xen_version(caps) failed");
2307 2354                  caps[sizeof (caps) - 1] = 0;
2308 2355                  if (prom_debug)
2309 2356                          dboot_printf("xen capabilities %s\n", caps);
2310 2357                  if (strstr(caps, "x86_32p") != NULL)
2311 2358                          pae_support = 1;
2312 2359          }
2313 2360  
2314 2361  #endif  /* _BOOT_TARGET_amd64 */
2315 2362          {
2316 2363                  xen_platform_parameters_t p;
2317 2364  
2318 2365                  if (HYPERVISOR_xen_version(XENVER_platform_parameters, &p) != 0)
2319 2366                          dboot_panic("HYPERVISOR_xen_version(parms) failed");
2320 2367                  DBG(p.virt_start);
2321 2368                  mfn_to_pfn_mapping = (pfn_t *)(xen_virt_start = p.virt_start);
2322 2369          }
2323 2370  
2324 2371          /*
2325 2372           * The hypervisor loads stuff starting at 1Gig
2326 2373           */
2327 2374          mfn_base = ONE_GIG;
2328 2375          DBG(mfn_base);
2329 2376  
2330 2377          /*
2331 2378           * enable writable page table mode for the hypervisor
2332 2379           */
2333 2380          if (HYPERVISOR_vm_assist(VMASST_CMD_enable,
2334 2381              VMASST_TYPE_writable_pagetables) < 0)
2335 2382                  dboot_panic("HYPERVISOR_vm_assist(writable_pagetables) failed");
2336 2383  
2337 2384          /*
2338 2385           * check for NX support
2339 2386           */
2340 2387          if (pae_support) {
2341 2388                  uint32_t eax = 0x80000000;
  
    | 
      ↓ open down ↓ | 
    105 lines elided | 
    
      ↑ open up ↑ | 
  
2342 2389                  uint32_t edx = get_cpuid_edx(&eax);
2343 2390  
2344 2391                  if (eax >= 0x80000001) {
2345 2392                          eax = 0x80000001;
2346 2393                          edx = get_cpuid_edx(&eax);
2347 2394                          if (edx & CPUID_AMD_EDX_NX)
2348 2395                                  NX_support = 1;
2349 2396                  }
2350 2397          }
2351 2398  
     2399 +        /*
     2400 +         * check for PAT support
     2401 +         */
     2402 +        {
     2403 +                uint32_t eax = 1;
     2404 +                uint32_t edx = get_cpuid_edx(&eax);
     2405 +
     2406 +                if (edx & CPUID_INTC_EDX_PAT)
     2407 +                        PAT_support = 1;
     2408 +        }
2352 2409  #if !defined(_BOOT_TARGET_amd64)
2353 2410  
2354 2411          /*
2355 2412           * The 32-bit hypervisor uses segmentation to protect itself from
2356 2413           * guests. This means when a guest attempts to install a flat 4GB
2357 2414           * code or data descriptor the 32-bit hypervisor will protect itself
2358 2415           * by silently shrinking the segment such that if the guest attempts
2359 2416           * any access where the hypervisor lives a #gp fault is generated.
2360 2417           * The problem is that some applications expect a full 4GB flat
2361 2418           * segment for their current thread pointer and will use negative
2362 2419           * offset segment wrap around to access data. TLS support in linux
2363 2420           * brand is one example of this.
2364 2421           *
2365 2422           * The 32-bit hypervisor can catch the #gp fault in these cases
2366 2423           * and emulate the access without passing the #gp fault to the guest
2367 2424           * but only if VMASST_TYPE_4gb_segments is explicitly turned on.
2368 2425           * Seems like this should have been the default.
2369 2426           * Either way, we want the hypervisor -- and not Solaris -- to deal
2370 2427           * to deal with emulating these accesses.
2371 2428           */
2372 2429          if (HYPERVISOR_vm_assist(VMASST_CMD_enable,
2373 2430              VMASST_TYPE_4gb_segments) < 0)
2374 2431                  dboot_panic("HYPERVISOR_vm_assist(4gb_segments) failed");
2375 2432  #endif  /* !_BOOT_TARGET_amd64 */
2376 2433  
2377 2434  #else   /* __xpv */
2378 2435  
2379 2436          /*
2380 2437           * use cpuid to enable MMU features
2381 2438           */
2382 2439          if (have_cpuid()) {
  
    | 
      ↓ open down ↓ | 
    21 lines elided | 
    
      ↑ open up ↑ | 
  
2383 2440                  uint32_t eax, edx;
2384 2441  
2385 2442                  eax = 1;
2386 2443                  edx = get_cpuid_edx(&eax);
2387 2444                  if (edx & CPUID_INTC_EDX_PSE)
2388 2445                          largepage_support = 1;
2389 2446                  if (edx & CPUID_INTC_EDX_PGE)
2390 2447                          pge_support = 1;
2391 2448                  if (edx & CPUID_INTC_EDX_PAE)
2392 2449                          pae_support = 1;
     2450 +                if (edx & CPUID_INTC_EDX_PAT)
     2451 +                        PAT_support = 1;
2393 2452  
2394 2453                  eax = 0x80000000;
2395 2454                  edx = get_cpuid_edx(&eax);
2396 2455                  if (eax >= 0x80000001) {
2397 2456                          eax = 0x80000001;
2398 2457                          edx = get_cpuid_edx(&eax);
2399 2458                          if (edx & CPUID_AMD_EDX_LM)
2400 2459                                  amd64_support = 1;
2401 2460                          if (edx & CPUID_AMD_EDX_NX)
2402 2461                                  NX_support = 1;
2403 2462                  }
2404 2463          } else {
2405 2464                  dboot_printf("cpuid not supported\n");
2406 2465          }
2407 2466  #endif /* __xpv */
2408 2467  
2409 2468  
2410 2469  #if defined(_BOOT_TARGET_amd64)
2411 2470          if (amd64_support == 0)
2412 2471                  dboot_panic("long mode not supported, rebooting");
2413 2472          else if (pae_support == 0)
2414 2473                  dboot_panic("long mode, but no PAE; rebooting");
2415 2474  #else
2416 2475          /*
2417 2476           * Allow the command line to over-ride use of PAE for 32 bit.
2418 2477           */
2419 2478          if (strstr(cmdline, "disablePAE=true") != NULL) {
2420 2479                  pae_support = 0;
2421 2480                  NX_support = 0;
2422 2481                  amd64_support = 0;
2423 2482          }
2424 2483  #endif
2425 2484  
2426 2485          /*
2427 2486           * initialize the simple memory allocator
2428 2487           */
2429 2488          init_mem_alloc();
2430 2489  
2431 2490  #if !defined(__xpv) && !defined(_BOOT_TARGET_amd64)
2432 2491          /*
2433 2492           * disable PAE on 32 bit h/w w/o NX and < 4Gig of memory
2434 2493           */
2435 2494          if (max_mem < FOUR_GIG && NX_support == 0)
2436 2495                  pae_support = 0;
2437 2496  #endif
2438 2497  
2439 2498          /*
2440 2499           * configure mmu information
2441 2500           */
2442 2501          if (pae_support) {
2443 2502                  shift_amt = shift_amt_pae;
2444 2503                  ptes_per_table = 512;
2445 2504                  pte_size = 8;
2446 2505                  lpagesize = TWO_MEG;
2447 2506  #if defined(_BOOT_TARGET_amd64)
2448 2507                  top_level = 3;
2449 2508  #else
2450 2509                  top_level = 2;
2451 2510  #endif
  
    | 
      ↓ open down ↓ | 
    49 lines elided | 
    
      ↑ open up ↑ | 
  
2452 2511          } else {
2453 2512                  pae_support = 0;
2454 2513                  NX_support = 0;
2455 2514                  shift_amt = shift_amt_nopae;
2456 2515                  ptes_per_table = 1024;
2457 2516                  pte_size = 4;
2458 2517                  lpagesize = FOUR_MEG;
2459 2518                  top_level = 1;
2460 2519          }
2461 2520  
     2521 +        DBG(PAT_support);
2462 2522          DBG(pge_support);
2463 2523          DBG(NX_support);
2464 2524          DBG(largepage_support);
2465 2525          DBG(amd64_support);
2466 2526          DBG(top_level);
2467 2527          DBG(pte_size);
2468 2528          DBG(ptes_per_table);
2469 2529          DBG(lpagesize);
2470 2530  
2471 2531  #if defined(__xpv)
2472 2532          ktext_phys = ONE_GIG;           /* from UNIX Mapfile */
2473 2533  #else
2474 2534          ktext_phys = FOUR_MEG;          /* from UNIX Mapfile */
2475 2535  #endif
2476 2536  
2477 2537  #if !defined(__xpv) && defined(_BOOT_TARGET_amd64)
2478 2538          /*
2479 2539           * For grub, copy kernel bits from the ELF64 file to final place.
2480 2540           */
2481 2541          DBG_MSG("\nAllocating nucleus pages.\n");
2482 2542          ktext_phys = (uintptr_t)do_mem_alloc(ksize, FOUR_MEG);
2483 2543  
2484 2544          if (ktext_phys == 0)
2485 2545                  dboot_panic("failed to allocate aligned kernel memory");
2486 2546          DBG(load_addr);
2487 2547          if (dboot_elfload64(load_addr) != 0)
2488 2548                  dboot_panic("failed to parse kernel ELF image, rebooting");
2489 2549  #endif
2490 2550  
2491 2551          DBG(ktext_phys);
2492 2552  
2493 2553          /*
2494 2554           * Allocate page tables.
2495 2555           */
2496 2556          build_page_tables();
2497 2557  
2498 2558          /*
2499 2559           * return to assembly code to switch to running kernel
2500 2560           */
2501 2561          entry_addr_low = (uint32_t)target_kernel_text;
2502 2562          DBG(entry_addr_low);
2503 2563          bi->bi_use_largepage = largepage_support;
2504 2564          bi->bi_use_pae = pae_support;
2505 2565          bi->bi_use_pge = pge_support;
2506 2566          bi->bi_use_nx = NX_support;
2507 2567  
2508 2568  #if defined(__xpv)
2509 2569  
2510 2570          bi->bi_next_paddr = next_avail_addr - mfn_base;
2511 2571          DBG(bi->bi_next_paddr);
2512 2572          bi->bi_next_vaddr = (native_ptr_t)(uintptr_t)next_avail_addr;
2513 2573          DBG(bi->bi_next_vaddr);
2514 2574  
2515 2575          /*
2516 2576           * unmap unused pages in start area to make them available for DMA
2517 2577           */
2518 2578          while (next_avail_addr < scratch_end) {
2519 2579                  (void) HYPERVISOR_update_va_mapping(next_avail_addr,
2520 2580                      0, UVMF_INVLPG | UVMF_LOCAL);
2521 2581                  next_avail_addr += MMU_PAGESIZE;
2522 2582          }
2523 2583  
2524 2584          bi->bi_xen_start_info = (native_ptr_t)(uintptr_t)xen_info;
2525 2585          DBG((uintptr_t)HYPERVISOR_shared_info);
2526 2586          bi->bi_shared_info = (native_ptr_t)HYPERVISOR_shared_info;
2527 2587          bi->bi_top_page_table = (uintptr_t)top_page_table - mfn_base;
2528 2588  
2529 2589  #else /* __xpv */
2530 2590  
2531 2591          bi->bi_next_paddr = next_avail_addr;
2532 2592          DBG(bi->bi_next_paddr);
2533 2593          bi->bi_next_vaddr = (native_ptr_t)(uintptr_t)next_avail_addr;
2534 2594          DBG(bi->bi_next_vaddr);
2535 2595          bi->bi_mb_version = multiboot_version;
2536 2596  
2537 2597          switch (multiboot_version) {
2538 2598          case 1:
2539 2599                  bi->bi_mb_info = (native_ptr_t)(uintptr_t)mb_info;
2540 2600                  break;
2541 2601          case 2:
2542 2602                  bi->bi_mb_info = (native_ptr_t)(uintptr_t)mb2_info;
2543 2603                  break;
2544 2604          default:
2545 2605                  dboot_panic("Unknown multiboot version: %d\n",
2546 2606                      multiboot_version);
2547 2607                  break;
2548 2608          }
2549 2609          bi->bi_top_page_table = (uintptr_t)top_page_table;
2550 2610  
  
    | 
      ↓ open down ↓ | 
    79 lines elided | 
    
      ↑ open up ↑ | 
  
2551 2611  #endif /* __xpv */
2552 2612  
2553 2613          bi->bi_kseg_size = FOUR_MEG;
2554 2614          DBG(bi->bi_kseg_size);
2555 2615  
2556 2616  #ifndef __xpv
2557 2617          if (map_debug)
2558 2618                  dump_tables();
2559 2619  #endif
2560 2620  
     2621 +#ifndef __xpv
     2622 +        /* Update boot info with FB data */
     2623 +        fb->cursor.origin.x = fb_info.cursor.origin.x;
     2624 +        fb->cursor.origin.y = fb_info.cursor.origin.y;
     2625 +        fb->cursor.pos.x = fb_info.cursor.pos.x;
     2626 +        fb->cursor.pos.y = fb_info.cursor.pos.y;
     2627 +        fb->cursor.visible = fb_info.cursor.visible;
     2628 +#endif
     2629 +
2561 2630          DBG_MSG("\n\n*** DBOOT DONE -- back to asm to jump to kernel\n\n");
2562 2631  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX