139833Speter/*-
239833Speter * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
339833Speter * All rights reserved.
439833Speter *
539833Speter * Redistribution and use in source and binary forms, with or without
639833Speter * modification, are permitted provided that the following conditions
739833Speter * are met:
839833Speter * 1. Redistributions of source code must retain the above copyright
939833Speter *    notice, this list of conditions and the following disclaimer.
1039833Speter * 2. Redistributions in binary form must reproduce the above copyright
1139833Speter *    notice, this list of conditions and the following disclaimer in the
1239833Speter *    documentation and/or other materials provided with the distribution.
1339833Speter *
1439833Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1539833Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1639833Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1739833Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1839833Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1939833Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2039833Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2139833Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2239833Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2339833Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2439833Speter * SUCH DAMAGE.
2539833Speter */
2639833Speter
27119482Sobrien#include <sys/cdefs.h>
28119482Sobrien__FBSDID("$FreeBSD$");
29119482Sobrien
30114379Speter#define __ELF_WORD_SIZE 64
3139833Speter#include <sys/param.h>
3239833Speter#include <sys/exec.h>
3339833Speter#include <sys/linker.h>
3439833Speter#include <string.h>
3539833Speter#include <machine/bootinfo.h>
3639833Speter#include <machine/elf.h>
3739833Speter#include <stand.h>
3839833Speter
3939833Speter#include "bootstrap.h"
4039833Speter#include "libi386.h"
4139833Speter#include "btxv86.h"
4239833Speter
43114379Speterstatic int	elf64_exec(struct preloaded_file *amp);
44134459Siedowsestatic int	elf64_obj_exec(struct preloaded_file *amp);
4539833Speter
46114379Speterstruct file_format amd64_elf = { elf64_loadfile, elf64_exec };
47134459Siedowsestruct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
4839833Speter
49114379Speter#define PG_V	0x001
50114379Speter#define PG_RW	0x002
51114379Speter#define PG_U	0x004
52114379Speter#define PG_PS	0x080
53114379Speter
54114379Spetertypedef u_int64_t p4_entry_t;
55114379Spetertypedef u_int64_t p3_entry_t;
56114379Spetertypedef u_int64_t p2_entry_t;
57114379Speterextern p4_entry_t PT4[];
58114379Speterextern p3_entry_t PT3[];
59114379Speterextern p2_entry_t PT2[];
60114379Speter
61114379Speteru_int32_t entry_hi;
62114379Speteru_int32_t entry_lo;
63114379Speter
64162814Sruextern void amd64_tramp();
65114379Speter
6639833Speter/*
67163708Sru * There is an ELF kernel and one or more ELF modules loaded.
6839833Speter * We wish to start executing the kernel image, so make such
6939833Speter * preparations as are required, and do so.
7039833Speter */
7139833Speterstatic int
72114379Speterelf64_exec(struct preloaded_file *fp)
7339833Speter{
7459854Sbp    struct file_metadata	*md;
7539833Speter    Elf_Ehdr 			*ehdr;
76114379Speter    vm_offset_t			modulep, kernend;
77114379Speter    int				err;
78114379Speter    int				i;
7939833Speter
8059854Sbp    if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
81199806Strasz	return(EFTYPE);
8239833Speter    ehdr = (Elf_Ehdr *)&(md->md_data);
8339833Speter
84114379Speter    err = bi_load64(fp->f_args, &modulep, &kernend);
85114379Speter    if (err != 0)
8639902Smsmith	return(err);
8739902Smsmith
88114379Speter    bzero(PT4, PAGE_SIZE);
89114379Speter    bzero(PT3, PAGE_SIZE);
90114379Speter    bzero(PT2, PAGE_SIZE);
9139833Speter
92114920Speter    /*
93114920Speter     * This is kinda brutal, but every single 1GB VM memory segment points to
94114920Speter     * the same first 1GB of physical memory.  But it is more than adequate.
95114920Speter     */
96114920Speter    for (i = 0; i < 512; i++) {
97114920Speter	/* Each slot of the level 4 pages points to the same level 3 page */
98114920Speter	PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]);
99114920Speter	PT4[i] |= PG_V | PG_RW | PG_U;
10039833Speter
101114920Speter	/* Each slot of the level 3 pages points to the same level 2 page */
102114920Speter	PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]);
103114920Speter	PT3[i] |= PG_V | PG_RW | PG_U;
104114379Speter
105114920Speter	/* The level 2 page slots are mapped with 2MB pages for 1GB. */
106114379Speter	PT2[i] = i * (2 * 1024 * 1024);
107114379Speter	PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
108114379Speter    }
109114379Speter
110114379Speter    entry_lo = ehdr->e_entry & 0xffffffff;
111114379Speter    entry_hi = (ehdr->e_entry >> 32) & 0xffffffff;
11239833Speter#ifdef DEBUG
113114379Speter    printf("Start @ %#llx ...\n", ehdr->e_entry);
11439833Speter#endif
11539833Speter
11661659Sps    dev_cleanup();
117114379Speter    __exec((void *)VTOP(amd64_tramp), modulep, kernend);
11839833Speter
11939833Speter    panic("exec returned");
12039833Speter}
121134459Siedowse
122134459Siedowsestatic int
123134459Siedowseelf64_obj_exec(struct preloaded_file *fp)
124134459Siedowse{
125134459Siedowse	return (EFTYPE);
126134459Siedowse}
127