summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-03-29 17:17:17 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-03-29 17:17:17 +0200
commit38149699cd27636b58d4b6539f7a6612783eb45c (patch)
tree94558d2e0d6910729b54f17961ed79e53f1ba1fe
parentd3469ab5e83740fa9492bd3c87ebba3e242f06dd (diff)
parent4d79b40a53d855c41137fa44bcafa62f5ae9f55d (diff)
Merge branch 'master' into master-x86_64
-rw-r--r--configfrag-first.ac29
-rw-r--r--configfrag.ac13
-rw-r--r--configure.ac3
-rw-r--r--i386/configfrag.ac19
-rw-r--r--i386/i386/gdt.h59
-rw-r--r--i386/i386/ktss.c10
-rw-r--r--i386/i386/ldt.c12
-rw-r--r--i386/i386/ldt.h9
-rw-r--r--i386/i386/mp_desc.c7
-rw-r--r--i386/i386/pcb.c3
-rw-r--r--i386/i386/seg.h58
-rw-r--r--x86_64/configfrag.ac15
12 files changed, 179 insertions, 58 deletions
diff --git a/configfrag-first.ac b/configfrag-first.ac
new file mode 100644
index 00000000..5dc0db2c
--- /dev/null
+++ b/configfrag-first.ac
@@ -0,0 +1,29 @@
+dnl Configure fragment for general options.
+
+dnl Copyright (C) 2020 Free Software Foundation, Inc.
+
+dnl Permission to use, copy, modify and distribute this software and its
+dnl documentation is hereby granted, provided that both the copyright
+dnl notice and this permission notice appear in all copies of the
+dnl software, derivative works or modified versions, and any portions
+dnl thereof, and that both notices appear in supporting documentation.
+dnl
+dnl THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+dnl "AS IS" CONDITION. THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+dnl LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+dnl USE OF THIS SOFTWARE.
+
+#
+# Common options
+#
+
+ncom=0
+nlpr=0
+
+AC_ARG_ENABLE([pae],
+ AS_HELP_STRING([--enable-pae], [PAE support (ix86-only); on i386-at disabled
+ by default, otherwise enabled by default]))
+
+dnl Local Variables:
+dnl mode: autoconf
+dnl End:
diff --git a/configfrag.ac b/configfrag.ac
index 73c23ffb..91d737ef 100644
--- a/configfrag.ac
+++ b/configfrag.ac
@@ -26,6 +26,19 @@ AC_DEFINE([KERNEL], [1], [KERNEL])
# Formerly in `bogus/'.
#
+# i386/bogus/com.h
+AC_DEFINE_UNQUOTED([NCOM], [$ncom], [NCOM])
+
+# i386/bogus/lpr.h
+AC_DEFINE_UNQUOTED([NLPR], [$nlpr], [NLPR])
+
+[if [ x"$enable_pae" = xyes ]; then]
+ AC_DEFINE([PAE], [1], [PAE support])
+ AM_CONDITIONAL([enable_pae], [true])
+[else]
+ AM_CONDITIONAL([enable_pae], [false])
+[fi]
+
# When set, the bootstrap task symbols are preserved by the kernel debugger.
# Used in `kern/bootstrap.c'.
AC_DEFINE([BOOTSTRAP_SYMBOLS], [0], [BOOTSTRAP_SYMBOLS])
diff --git a/configure.ac b/configure.ac
index 49e16399..806a1da1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -134,6 +134,9 @@ esac]
# PC AT.
# TODO. Currently handled in `i386/configfrag.ac'.
+# General options.
+m4_include([configfrag-first.ac])
+
# Xen.
m4_include([xen/configfrag.ac])
diff --git a/i386/configfrag.ac b/i386/configfrag.ac
index 3c29bdf9..df5311e5 100644
--- a/i386/configfrag.ac
+++ b/i386/configfrag.ac
@@ -44,8 +44,6 @@ esac
# Formerly in `i386/bogus/'.
#
-ncom=0
-nlpr=0
case $host_platform:$host_cpu in
at:i?86)
ncom=4
@@ -62,12 +60,6 @@ case $host_platform:$host_cpu in
*)
:;;
esac]
-
-# i386/bogus/com.h
-AC_DEFINE_UNQUOTED([NCOM], [$ncom], [NCOM])
-
-# i386/bogus/lpr.h
-AC_DEFINE_UNQUOTED([NLPR], [$nlpr], [NLPR])
#
# Options.
@@ -100,9 +92,6 @@ if [ x"$enable_lpr" = xyes ]; then]
[fi]
-AC_ARG_ENABLE([pae],
- AS_HELP_STRING([--enable-pae], [PAE support (ix86-only); on ix86-at disabled
- by default, on ix86-xen enabled by default]))
[case $host_platform:$host_cpu in
xen:i?86)
enable_pae=${enable_pae-yes};;
@@ -112,13 +101,7 @@ AC_ARG_ENABLE([pae],
if [ x"$enable_pae" = xyes ]; then]
AC_MSG_ERROR([can only enable the `PAE' feature on ix86.])
[fi;;
-esac
-if [ x"$enable_pae" = xyes ]; then]
- AC_DEFINE([PAE], [1], [PAE support])
- AM_CONDITIONAL([enable_pae], [true])
-[else]
- AM_CONDITIONAL([enable_pae], [false])
-[fi]
+esac]
AC_ARG_WITH([_START_MAP],
AS_HELP_STRING([--with-_START_MAP=0x1000000], [specify kernel mapping start address]),
diff --git a/i386/i386/gdt.h b/i386/i386/gdt.h
index d865640b..9879ad3e 100644
--- a/i386/i386/gdt.h
+++ b/i386/i386/gdt.h
@@ -40,28 +40,79 @@
*/
#define KERNEL_CS (0x08 | KERNEL_RING) /* kernel code */
#define KERNEL_DS (0x10 | KERNEL_RING) /* kernel data */
+
+
#ifndef MACH_PV_DESCRIPTORS
#define KERNEL_LDT 0x18 /* master LDT */
#endif /* MACH_PV_DESCRIPTORS */
+
+#ifdef __x86_64__
+/* LDT needs two entries */
+#define KERNEL_TSS 0x40 /* master TSS (uniprocessor) */
+#else
#define KERNEL_TSS 0x20 /* master TSS (uniprocessor) */
+#endif
+
+
#define USER_LDT 0x28 /* place for per-thread LDT */
+
+#ifdef __x86_64__
+/* LDT needs two entries */
+#define USER_TSS 0x58 /* place for per-thread TSS
+ that holds IO bitmap */
+#else
#define USER_TSS 0x30 /* place for per-thread TSS
that holds IO bitmap */
+#endif
+
+
#ifndef MACH_PV_DESCRIPTORS
#define LINEAR_DS 0x38 /* linear mapping */
#endif /* MACH_PV_DESCRIPTORS */
-/* 0x40 was USER_FPREGS, now free */
-#define USER_GDT 0x48 /* user-defined GDT entries */
+/* 0x40 was USER_FPREGS, now used by TSS in 64bit mode */
+
+#define USER_GDT 0x48 /* user-defined 32bit GDT entries */
#define USER_GDT_SLOTS 2
-#define GDTSZ (USER_GDT/8 + USER_GDT_SLOTS)
+/* 0x58 used by user TSS in 64bit mode */
+
+#ifdef __x86_64__
+#define GDTSZ sel_idx(0x60)
+#else
+#define GDTSZ sel_idx(0x58)
+#endif
extern struct real_descriptor gdt[GDTSZ];
/* Fill a segment descriptor in the GDT. */
+#define _fill_gdt_descriptor(_gdt, segment, base, limit, access, sizebits) \
+ fill_descriptor(&_gdt[sel_idx(segment)], base, limit, access, sizebits)
+
#define fill_gdt_descriptor(segment, base, limit, access, sizebits) \
- fill_descriptor(&gdt[segment/8], base, limit, access, sizebits)
+ _fill_gdt_descriptor(gdt, segment, base, limit, access, sizebits)
+
+/* 64bit variant */
+#ifdef __x86_64__
+#define _fill_gdt_descriptor64(_gdt, segment, base, limit, access, sizebits) \
+ fill_descriptor64((struct real_descriptor64 *) &_gdt[sel_idx(segment)], base, limit, access, sizebits)
+
+#define fill_gdt_descriptor64(segment, base, limit, access, sizebits) \
+ _fill_gdt_descriptor64(gdt, segment, base, limit, access, sizebits)
+#endif
+
+/* System descriptor variants */
+#ifdef __x86_64__
+#define _fill_gdt_sys_descriptor(_gdt, segment, base, limit, access, sizebits) \
+ _fill_gdt_descriptor64(_gdt, segment, base, limit, access, sizebits)
+#define fill_gdt_sys_descriptor(segment, base, limit, access, sizebits) \
+ fill_gdt_descriptor64(segment, base, limit, access, sizebits)
+#else
+#define _fill_gdt_sys_descriptor(_gdt, segment, base, limit, access, sizebits) \
+ _fill_gdt_descriptor(_gdt, segment, base, limit, access, sizebits)
+#define fill_gdt_sys_descriptor(segment, base, limit, access, sizebits) \
+ fill_gdt_descriptor(segment, base, limit, access, sizebits)
+#endif
extern void gdt_init(void);
diff --git a/i386/i386/ktss.c b/i386/i386/ktss.c
index 62de2a27..917e6305 100644
--- a/i386/i386/ktss.c
+++ b/i386/i386/ktss.c
@@ -51,14 +51,10 @@ ktss_init(void)
if (hyp_stack_switch(KERNEL_DS, (unsigned long)(exception_stack+1024)))
panic("couldn't register exception stack\n");
#else /* MACH_RING1 */
-
-#ifdef __x86_64__
-#warning FIXME
-#endif
/* Initialize the master TSS descriptor. */
- fill_gdt_descriptor(KERNEL_TSS,
- kvtolin(&ktss), sizeof(struct task_tss) - 1,
- ACC_PL_K|ACC_TSS, 0);
+ fill_gdt_sys_descriptor(KERNEL_TSS,
+ kvtolin(&ktss), sizeof(struct task_tss) - 1,
+ ACC_PL_K|ACC_TSS, 0);
/* Initialize the master TSS. */
ktss.tss.ss0 = KERNEL_DS;
diff --git a/i386/i386/ldt.c b/i386/i386/ldt.c
index 99d2f7fe..261df93a 100644
--- a/i386/i386/ldt.c
+++ b/i386/i386/ldt.c
@@ -47,22 +47,18 @@ struct real_descriptor ldt[LDTSZ];
void
ldt_init(void)
{
-#ifdef __x86_64__
-#warning FIXME
-#endif
-
#ifdef MACH_PV_DESCRIPTORS
#ifdef MACH_PV_PAGETABLES
pmap_set_page_readwrite(ldt);
#endif /* MACH_PV_PAGETABLES */
#else /* MACH_PV_DESCRIPTORS */
/* Initialize the master LDT descriptor in the GDT. */
- fill_gdt_descriptor(KERNEL_LDT,
- kvtolin(&ldt), sizeof(ldt)-1,
- ACC_PL_K|ACC_LDT, 0);
+ fill_gdt_sys_descriptor(KERNEL_LDT,
+ kvtolin(&ldt), sizeof(ldt)-1,
+ ACC_PL_K|ACC_LDT, 0);
#endif /* MACH_PV_DESCRIPTORS */
- /* Initialize the LDT descriptors. */
+ /* Initialize the 32bit LDT descriptors. */
fill_ldt_gate(USER_SCALL,
(vm_offset_t)&syscall, KERNEL_CS,
ACC_PL_U|ACC_CALL_GATE, 0);
diff --git a/i386/i386/ldt.h b/i386/i386/ldt.h
index f196c74b..1f0d7014 100644
--- a/i386/i386/ldt.h
+++ b/i386/i386/ldt.h
@@ -43,6 +43,9 @@
* User descriptors for Mach - 32-bit flat address space
*/
#define USER_SCALL 0x07 /* system call gate */
+#ifdef __x86_64__
+/* Call gate needs two entries */
+#endif
#define USER_CS 0x17 /* user code segment */
#define USER_DS 0x1f /* user data segment */
@@ -53,12 +56,12 @@
extern struct real_descriptor ldt[LDTSZ];
-/* Fill a segment descriptor in the LDT. */
+/* Fill a 32bit segment descriptor in the LDT. */
#define fill_ldt_descriptor(selector, base, limit, access, sizebits) \
- fill_descriptor(&ldt[selector/8], base, limit, access, sizebits)
+ fill_descriptor(&ldt[sel_idx(selector)], base, limit, access, sizebits)
#define fill_ldt_gate(selector, offset, dest_selector, access, word_count) \
- fill_gate((struct real_gate*)&ldt[selector/8], \
+ fill_gate((struct real_gate*)&ldt[sel_idx(selector)], \
offset, dest_selector, access, word_count)
void ldt_init(void);
diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
index d62d4958..07cc389a 100644
--- a/i386/i386/mp_desc.c
+++ b/i386/i386/mp_desc.c
@@ -146,14 +146,11 @@ mp_desc_init(int mycpu)
#ifdef MACH_RING1
panic("TODO %s:%d\n",__FILE__,__LINE__);
#else /* MACH_RING1 */
-#ifdef __x86_64__
-#warning FIXME
-#endif
- fill_descriptor(&mpt->gdt[sel_idx(KERNEL_LDT)],
+ _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_LDT,
(unsigned)&mpt->ldt,
LDTSZ * sizeof(struct real_descriptor) - 1,
ACC_P|ACC_PL_K|ACC_LDT, 0);
- fill_descriptor(&mpt->gdt[sel_idx(KERNEL_TSS)],
+ _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_TSS,
(unsigned)&mpt->ktss,
sizeof(struct task_tss) - 1,
ACC_P|ACC_PL_K|ACC_TSS, 0);
diff --git a/i386/i386/pcb.c b/i386/i386/pcb.c
index 743108db..23585323 100644
--- a/i386/i386/pcb.c
+++ b/i386/i386/pcb.c
@@ -169,7 +169,8 @@ void switch_ktss(pcb_t pcb)
#ifdef MACH_PV_DESCRIPTORS
hyp_set_ldt(&ldt, LDTSZ);
#else /* MACH_PV_DESCRIPTORS */
- set_ldt(KERNEL_LDT);
+ if (get_ldt() != KERNEL_LDT)
+ set_ldt(KERNEL_LDT);
#endif /* MACH_PV_DESCRIPTORS */
}
else {
diff --git a/i386/i386/seg.h b/i386/i386/seg.h
index 6f3d5af9..b1a14fe4 100644
--- a/i386/i386/seg.h
+++ b/i386/i386/seg.h
@@ -59,12 +59,32 @@ struct real_descriptor {
base_high:8; /* base 24..31 */
};
+#ifdef __x86_64__
+struct real_descriptor64 {
+ unsigned int limit_low:16, /* limit 0..15 */
+ base_low:16, /* base 0..15 */
+ base_med:8, /* base 16..23 */
+ access:8, /* access byte */
+ limit_high:4, /* limit 16..19 */
+ granularity:4, /* granularity */
+ base_high:8, /* base 24..31 */
+ base_ext:32, /* base 32..63 */
+ reserved1:8,
+ zero:5,
+ reserved2:19;
+};
+#endif
+
struct real_gate {
unsigned int offset_low:16, /* offset 0..15 */
selector:16,
word_count:8,
access:8,
offset_high:16; /* offset 16..31 */
+#ifdef __x86_64__
+ unsigned int offset_ext:32, /* offset 32..63 */
+ reserved:32;
+#endif
};
#endif /* !__ASSEMBLER__ */
@@ -185,6 +205,40 @@ fill_descriptor(struct real_descriptor *_desc, unsigned base, unsigned limit,
#endif /* MACH_PV_DESCRIPTORS */
}
+#ifdef __x86_64__
+MACH_INLINE void
+fill_descriptor64(struct real_descriptor64 *_desc, unsigned long base, unsigned limit,
+ unsigned char access, unsigned char sizebits)
+{
+ /* TODO: when !MACH_PV_DESCRIPTORS, setting desc and just memcpy isn't simpler actually */
+#ifdef MACH_PV_DESCRIPTORS
+ struct real_descriptor64 __desc, *desc = &__desc;
+#else /* MACH_PV_DESCRIPTORS */
+ struct real_descriptor64 *desc = _desc;
+#endif /* MACH_PV_DESCRIPTORS */
+ if (limit > 0xfffff)
+ {
+ limit >>= 12;
+ sizebits |= SZ_G;
+ }
+ desc->limit_low = limit & 0xffff;
+ desc->base_low = base & 0xffff;
+ desc->base_med = (base >> 16) & 0xff;
+ desc->access = access | ACC_P;
+ desc->limit_high = limit >> 16;
+ desc->granularity = sizebits;
+ desc->base_high = base >> 24;
+ desc->base_ext = base >> 32;
+ desc->reserved1 = 0;
+ desc->zero = 0;
+ desc->reserved2 = 0;
+#ifdef MACH_PV_DESCRIPTORS
+ if (hyp_do_update_descriptor(kv_to_ma(_desc), *(uint64_t*)desc))
+ panic("couldn't update descriptor(%lu to %08lx%08lx)\n", (vm_offset_t) kv_to_ma(_desc), *(((unsigned long*)desc)+1), *(unsigned long *)desc);
+#endif /* MACH_PV_DESCRIPTORS */
+}
+#endif
+
/* Fill a gate with particular values. */
MACH_INLINE void
fill_gate(struct real_gate *gate, unsigned offset, unsigned short selector,
@@ -195,6 +249,10 @@ fill_gate(struct real_gate *gate, unsigned offset, unsigned short selector,
gate->word_count = word_count;
gate->access = access | ACC_P;
gate->offset_high = (offset >> 16) & 0xffff;
+#ifdef __x86_64__
+ gate->offset_ext = offset >> 32;
+ gate->reserved = 0;
+#endif
}
#endif /* !__ASSEMBLER__ */
diff --git a/x86_64/configfrag.ac b/x86_64/configfrag.ac
index 480028c8..817eff3d 100644
--- a/x86_64/configfrag.ac
+++ b/x86_64/configfrag.ac
@@ -28,7 +28,9 @@ dnl USE OF THIS SOFTWARE.
AC_DEFINE([CPU_L1_SHIFT], [6], [CPU_L1_SHIFT])
[# Does the architecture provide machine-specific interfaces?
- mach_machine_routines=1;;
+ mach_machine_routines=1
+
+ enable_pae=yes;;
*)]
AM_CONDITIONAL([HOST_x86_64], [false])[;;
esac
@@ -40,8 +42,6 @@ case $host_platform in
AM_CONDITIONAL([PLATFORM_at], [false])[;;
esac]
-ncom=0
-nlpr=0
[case $host_platform:$host_cpu in
at:x86_64)]
ncom=4
@@ -52,15 +52,6 @@ nlpr=0
*)
:;;
esac]
-
-# i386/bogus/com.h
-AC_DEFINE_UNQUOTED([NCOM], [$ncom], [NCOM])
-
-# i386/bogus/lpr.h
-AC_DEFINE_UNQUOTED([NLPR], [$nlpr], [NLPR])
-
-AC_DEFINE([PAE], [1], [PAE support])
-AM_CONDITIONAL([enable_pae], [true])
dnl Local Variables:
dnl mode: autoconf