summaryrefslogtreecommitdiff
path: root/i386/i386/gdt.c
blob: fb18360e7e7bbe2a2ea622d058b03d39e9ae2b7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* 
 * Mach Operating System
 * Copyright (c) 1991,1990 Carnegie Mellon University
 * Copyright (c) 1991 IBM Corporation 
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation,
 * and that the name IBM not be used in advertising or publicity 
 * pertaining to distribution of the software without specific, written
 * prior permission.
 * 
 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 * Global descriptor table.
 */
#include <mach/machine/vm_types.h>
#include <mach/xen.h>

#include <kern/assert.h>
#include <intel/pmap.h>

#include "vm_param.h"
#include "seg.h"
#include "gdt.h"

#ifdef	MACH_PV_DESCRIPTORS
/* It is actually defined in xen_boothdr.S */
extern
#endif	/* MACH_PV_DESCRIPTORS */
struct real_descriptor gdt[GDTSZ];

void
gdt_init(void)
{
	/* Initialize the kernel code and data segment descriptors.  */
#ifdef __x86_64__
	assert(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS == 0);
	fill_gdt_descriptor(KERNEL_CS, 0, 0, ACC_PL_K|ACC_CODE_R, SZ_64);
	fill_gdt_descriptor(KERNEL_DS, 0, 0, ACC_PL_K|ACC_DATA_W, SZ_64);
#ifndef	MACH_PV_DESCRIPTORS
	fill_gdt_descriptor(LINEAR_DS, 0, 0, ACC_PL_K|ACC_DATA_W, SZ_64);
#endif	/* MACH_PV_DESCRIPTORS */
#else
	fill_gdt_descriptor(KERNEL_CS,
			    LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
			    LINEAR_MAX_KERNEL_ADDRESS - (LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) - 1,
			    ACC_PL_K|ACC_CODE_R, SZ_32);
	fill_gdt_descriptor(KERNEL_DS,
			    LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
			    LINEAR_MAX_KERNEL_ADDRESS - (LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) - 1,
			    ACC_PL_K|ACC_DATA_W, SZ_32);
#ifndef	MACH_PV_DESCRIPTORS
	fill_gdt_descriptor(LINEAR_DS,
			    0,
			    0xffffffff,
			    ACC_PL_K|ACC_DATA_W, SZ_32);
#endif	/* MACH_PV_DESCRIPTORS */
#endif

#ifdef	MACH_PV_DESCRIPTORS
	unsigned long frame = kv_to_mfn(gdt);
	pmap_set_page_readonly(gdt);
	if (hyp_set_gdt(kv_to_la(&frame), GDTSZ))
		panic("couldn't set gdt\n");
#endif
#ifdef	MACH_PV_PAGETABLES
	if (hyp_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments))
		panic("couldn't set 4gb segments vm assist");
#if 0
	if (hyp_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments_notify))
		panic("couldn't set 4gb segments vm assist notify");
#endif
#endif	/* MACH_PV_PAGETABLES */

#ifndef	MACH_PV_DESCRIPTORS
	/* Load the new GDT.  */
	{
		struct pseudo_descriptor pdesc;

		pdesc.limit = sizeof(gdt)-1;
		pdesc.linear_base = kvtolin(&gdt);
		lgdt(&pdesc);
	}
#endif	/* MACH_PV_DESCRIPTORS */

	/* Reload all the segment registers from the new GDT.
	   We must load ds and es with 0 before loading them with KERNEL_DS
	   because some processors will "optimize out" the loads
	   if the previous selector values happen to be the same.  */
#ifndef __x86_64__
	asm volatile("ljmp	%0,$1f\n"
		     "1:\n"
		     "movw	%w2,%%ds\n"
		     "movw	%w2,%%es\n"
		     "movw	%w2,%%fs\n"
		     "movw	%w2,%%gs\n"
		     
		     "movw	%w1,%%ds\n"
		     "movw	%w1,%%es\n"
		     "movw	%w1,%%ss\n"
		     : : "i" (KERNEL_CS), "r" (KERNEL_DS), "r" (0));
#endif
#ifdef	MACH_PV_PAGETABLES
#if VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
	/* things now get shifted */
#ifdef	MACH_PSEUDO_PHYS
	pfn_list = (void*) pfn_list + VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS;
#endif	/* MACH_PSEUDO_PHYS */
	la_shift += LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS;
#endif
#endif	/* MACH_PV_PAGETABLES */
}