Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ACS
Public
HermitCore
libhermit-rs
Commits
41eff498
Unverified
Commit
41eff498
authored
Dec 19, 2020
by
Stefan Lankes
Browse files
introduce feature flag to enable/disable FSGSBASE support
parent
168e7a15
Changes
5
Hide whitespace changes
Inline
Side-by-side
Cargo.toml
View file @
41eff498
...
...
@@ -38,11 +38,12 @@ name = "measure_startup_time"
harness
=
false
[features]
default
=
[
"pci"
,
"acpi"
]
default
=
[
"pci"
,
"acpi"
,
"fsgsbase"
]
vga
=
[]
newlib
=
[]
pci
=
[]
acpi
=
[]
fsgsbase
=
[]
[dev-dependencies]
x86
=
{
version
=
"0.34.*"
,
default-features
=
false
}
...
...
src/arch/x86_64/kernel/mod.rs
View file @
41eff498
...
...
@@ -50,8 +50,10 @@ pub mod virtio_net;
#[cfg(not(test))]
global_asm!
(
include_str!
(
"start.s"
));
#[cfg(not(test))]
#[cfg(
all(
not(test)
,
not(fsgsbase))
)]
global_asm!
(
include_str!
(
"switch.s"
));
#[cfg(all(not(test),
fsgsbase))]
global_asm!
(
include_str!
(
"switch_fsgsbase.s"
));
const
SERIAL_PORT_BAUDRATE
:
u32
=
115_200
;
...
...
src/arch/x86_64/kernel/processor.rs
View file @
41eff498
...
...
@@ -19,7 +19,7 @@ use core::arch::x86_64::__rdtscp as rdtscp;
use
core
::
arch
::
x86_64
::
_rdtsc
as
rdtsc
;
use
core
::
convert
::
TryInto
;
use
core
::
sync
::
atomic
::
spin_loop_hint
;
use
core
::{
fmt
,
ptr
,
u32
};
use
core
::{
fmt
,
u32
};
const
IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP
:
u64
=
1
<<
16
;
const
IA32_MISC_ENABLE_SPEEDSTEP_LOCK
:
u64
=
1
<<
20
;
...
...
@@ -50,13 +50,6 @@ static mut SUPPORTS_FSGS: bool = false;
static
mut
RUN_ON_HYPERVISOR
:
bool
=
false
;
static
mut
TIMESTAMP_FUNCTION
:
unsafe
fn
()
->
u64
=
get_timestamp_rdtsc
;
extern
"C"
{
static
Lpatch0
:
u64
;
static
Lpatch1
:
u64
;
static
Lpatch2
:
u64
;
static
Lpatch3
:
u64
;
}
#[repr(C,
align(
16
))]
pub
struct
XSaveLegacyRegion
{
pub
fpu_control_word
:
u16
,
...
...
@@ -804,27 +797,13 @@ pub fn configure() {
if
supports_fsgs
()
{
cr4
.insert
(
Cr4
::
CR4_ENABLE_FSGSBASE
);
// enable the usage of fsgsbase during a context switch
// => replace short jump with nops
// => see switch.s
unsafe
{
#[cfg(not(feature
=
"newlib"
))]
let
base
:
u64
=
environment
::
get_base_address
()
.as_u64
();
// newlib based application doesn't support relocatable binaries
// => we don't have to recalulate the address
#[cfg(feature
=
"newlib"
)]
let
base
:
u64
=
0
;
let
addr
=
&
Lpatch0
as
*
const
_
as
u64
;
ptr
::
write_bytes
((
addr
+
base
)
as
*
mut
u8
,
0x90
,
2
);
let
addr
=
&
Lpatch1
as
*
const
_
as
u64
;
ptr
::
write_bytes
((
addr
+
base
)
as
*
mut
u8
,
0x90
,
2
);
let
addr
=
&
Lpatch2
as
*
const
_
as
u64
;
ptr
::
write_bytes
((
addr
+
base
)
as
*
mut
u8
,
0x90
,
2
);
let
addr
=
&
Lpatch3
as
*
const
_
as
u64
;
ptr
::
write_bytes
((
addr
+
base
)
as
*
mut
u8
,
0x90
,
2
);
}
#[cfg(feature
=
"fsgsbase"
)]
info!
(
"Enable FSGSBASE support"
);
}
#[cfg(feature
=
"fsgsbase"
)]
if
!
supports_fsgs
()
{
error!
(
"FSGSBASE support is enabled, but the processor doesn't support it!"
);
loop
{}
}
debug!
(
"Set CR4 to 0x{:x}"
,
cr4
);
...
...
@@ -1025,63 +1004,90 @@ pub fn get_frequency() -> u16 {
}
#[inline]
#[cfg(feature
=
"fsgsbase"
)]
pub
fn
readfs
()
->
usize
{
let
val
:
u64
;
unsafe
{
if
supports_fsgs
()
{
llvm_asm!
(
"rdfsbase $0"
:
"=r"
(
val
)
:::
"volatile"
);
}
else
{
let
rdx
:
u64
;
let
rax
:
u64
;
llvm_asm!
(
"rdfsbase $0"
:
"=r"
(
val
)
:::
"volatile"
);
}
llvm_asm!
(
"rdmsr"
:
"=%rdx"
(
rdx
),
"=%rax"
(
rax
)
:
"%rcx"
(
0xc0000100u64
)
::
"volatile"
);
val
as
usize
}
val
=
(
rdx
<<
32
)
|
rax
;
}
#[inline]
#[cfg(not(feature
=
"fsgsbase"
))]
pub
fn
readfs
()
->
usize
{
let
rdx
:
u64
;
let
rax
:
u64
;
unsafe
{
llvm_asm!
(
"rdmsr"
:
"=%rdx"
(
rdx
),
"=%rax"
(
rax
)
:
"%rcx"
(
0xc0000100u64
)
::
"volatile"
);
}
val
as
usize
((
rdx
<<
32
)
|
rax
)
as
usize
}
#[inline]
#[cfg(feature
=
"fsgsbase"
)]
pub
fn
readgs
()
->
usize
{
let
val
:
u64
;
unsafe
{
if
supports_fsgs
()
{
llvm_asm!
(
"rdgsbase $0"
:
"=r"
(
val
)
:::
"volatile"
);
}
else
{
let
rdx
:
u64
;
let
rax
:
u64
;
llvm_asm!
(
"rdgsbase $0"
:
"=r"
(
val
)
:::
"volatile"
);
}
llvm_asm!
(
"rdmsr"
:
"=%rdx"
(
rdx
),
"=%rax"
(
rax
)
:
"%rcx"
(
0xc0000101u64
)
::
"volatile"
);
val
as
usize
}
val
=
(
rdx
<<
32
)
|
rax
;
}
#[inline]
#[cfg(not(feature
=
"fsgsbase"
))]
pub
fn
readgs
()
->
usize
{
let
rdx
:
u64
;
let
rax
:
u64
;
unsafe
{
llvm_asm!
(
"rdmsr"
:
"=%rdx"
(
rdx
),
"=%rax"
(
rax
)
:
"%rcx"
(
0xc0000101u64
)
::
"volatile"
);
}
val
as
usize
((
rdx
<<
32
)
|
rax
)
as
usize
}
#[inline]
#[cfg(feature
=
"fsgsbase"
)]
pub
fn
writefs
(
fs
:
usize
)
{
unsafe
{
if
supports_fsgs
()
{
llvm_asm!
(
"wrfsbase $0"
::
"r"
(
fs
as
u64
)
::
"volatile"
);
}
else
{
let
edx
=
fs
>>
32
;
let
eax
=
fs
as
u64
&
(
u32
::
MAX
-
1
)
as
u64
;
llvm_asm!
(
"wrfsbase $0"
::
"r"
(
fs
)
::
"volatile"
);
}
}
llvm_asm!
(
"wrmsr"
::
"%rcx"
(
0xc0000100u64
),
"%rdx"
(
edx
),
"%rax"
(
eax
)
::
"volatile"
);
}
#[inline]
#[cfg(not(feature
=
"fsgsbase"
))]
pub
fn
writefs
(
fs
:
usize
)
{
let
rdx
=
fs
>>
32
;
let
rax
=
fs
&
(
u32
::
MAX
-
1
)
as
usize
;
unsafe
{
llvm_asm!
(
"wrmsr"
::
"%rcx"
(
0xc0000100u64
),
"%rdx"
(
rdx
),
"%rax"
(
rax
)
::
"volatile"
);
}
}
#[inline]
#[cfg(feature
=
"fsgsbase"
)]
pub
fn
writegs
(
gs
:
usize
)
{
unsafe
{
llvm_asm!
(
"wrgsbase $0"
::
"r"
(
gs
)
::
"volatile"
);
}
}
#[inline]
#[cfg(not(feature
=
"fsgsbase"
))]
pub
fn
writegs
(
gs
:
usize
)
{
let
rdx
=
gs
>>
32
;
let
rax
=
gs
&
(
u32
::
MAX
-
1
)
as
usize
;
unsafe
{
llvm_asm!
(
"wr
gsbase $0"
::
"r"
(
gs
as
u64
)
::
"volatile"
);
llvm_asm!
(
"wr
msr"
::
"%rcx"
(
0xc0000101u64
),
"%rdx"
(
rdx
),
"%rax"
(
rax
)
::
"volatile"
);
}
}
...
...
src/arch/x86_64/kernel/switch.s
View file @
41eff498
...
...
@@ -8,10 +8,6 @@
.
section
.
text
.
global
switch_to_task
.
global
switch_to_fpu_owner
.
global
Lpatch0
.
global
Lpatch1
.
global
Lpatch2
.
global
Lpatch3
.
extern
set_current_kernel_stack
.
align
16
...
...
@@ -36,18 +32,11 @@ switch_to_task:
push
%
r14
push
%
r15
//
push
fs
registers
Lpatch0
:
jmp
Lrdgs0
//
we
patch
later
this
jump
to
enable
rdfsbase
/
rdgsbase
rdfsbaseq
%
rax
push
%
rax
jmp
Lgo0
Lrdgs0
:
mov
$
0xc0000100
,
%
ecx
rdmsr
sub
$
8
,
%
rsp
mov
%
edx
,
4
(%
rsp
)
mov
%
eax
,
(%
rsp
)
Lgo0
:
//
store
the
old
stack
pointer
in
the
dereferenced
first
parameter
\
n
\
t
\
//
and
load
the
new
stack
pointer
in
the
second
parameter
.
\
n
\
t
\
mov
%
rsp
,
(%
rdi
)
...
...
@@ -59,18 +48,11 @@ Lgo0:
//
set
stack
pointer
in
TSS
call
set_current_kernel_stack
//
restore
context
Lpatch1
:
jmp
Lwrfsgs1
//
we
patch
later
this
jump
to
enable
wrfsbase
/
wrgsbase
pop
%
rax
wrfsbaseq
%
rax
jmp
Lgo1
Lwrfsgs1
:
mov
$
0xc0000100
,
%
ecx
mov
4
(%
rsp
),
%
edx
mov
(%
rsp
),
%
eax
add
$
8
,
%
rsp
wrmsr
Lgo1
:
pop
%
r15
pop
%
r14
pop
%
r13
...
...
@@ -115,18 +97,11 @@ switch_to_fpu_owner:
push
%
r14
push
%
r15
//
push
fs
registers
Lpatch2
:
jmp
Lrdgs2
//
we
patch
later
this
jump
to
enable
rdfsbase
/
rdgsbase
rdfsbaseq
%
rax
push
%
rax
jmp
Lgo2
Lrdgs2
:
mov
$
0xc0000100
,
%
ecx
rdmsr
sub
$
8
,
%
rsp
mov
%
edx
,
4
(%
rsp
)
mov
%
eax
,
(%
rsp
)
Lgo2
:
//
store
the
old
stack
pointer
in
the
dereferenced
first
parameter
\
n
\
t
\
//
and
load
the
new
stack
pointer
in
the
second
parameter
.
\
n
\
t
\
mov
%
rsp
,
(%
rdi
)
...
...
@@ -134,18 +109,11 @@ Lgo2:
//
set
stack
pointer
in
TSS
call
set_current_kernel_stack
//
restore
context
Lpatch3
:
jmp
Lwrfsgs3
//
we
patch
later
this
jump
to
enable
wrfsbase
/
wrgsbase
pop
%
rax
wrfsbaseq
%
rax
jmp
Lgo3
Lwrfsgs3
:
mov
$
0xc0000100
,
%
ecx
mov
4
(%
rsp
),
%
edx
mov
(%
rsp
),
%
eax
add
$
8
,
%
rsp
wrmsr
Lgo3
:
pop
%
r15
pop
%
r14
pop
%
r13
...
...
src/arch/x86_64/kernel/switch_fsgsbase.s
0 → 100755
View file @
41eff498
//
Copyright
(
c
)
2020
Stefan
Lankes
,
RWTH
Aachen
University
//
//
Licensed
under
the
Apache
License
,
Version
2
.0
,
<
LICENSE
-
APACHE
or
//
http
://
apache.org
/
licenses
/
LICENSE
-2.0>
or
the
MIT
license
<
LICENSE
-
MIT
or
//
http
://
opensource.org
/
licenses
/
MIT
>,
at
your
option
.
This
file
may
not
be
//
copied
,
modified
,
or
distributed
except
according
to
those
terms
.
.
section
.
text
.
global
switch_to_task
.
global
switch_to_fpu_owner
.
extern
set_current_kernel_stack
.
align
16
switch_to_task
:
//
rdi
=
old_stack
=>
the
address
to
store
the
old
rsp
//
rsi
=
new_stack
=>
stack
pointer
of
the
new
task
pushfq
push
%
rax
push
%
rcx
push
%
rdx
push
%
rbx
push
%
rbp
push
%
rsi
push
%
rdi
push
%
r8
push
%
r9
push
%
r10
push
%
r11
push
%
r12
push
%
r13
push
%
r14
push
%
r15
//
push
fs
registers
rdfsbaseq
%
rax
push
%
rax
//
store
the
old
stack
pointer
in
the
dereferenced
first
parameter
\
n
\
t
\
//
and
load
the
new
stack
pointer
in
the
second
parameter
.
\
n
\
t
\
mov
%
rsp
,
(%
rdi
)
mov
%
rsi
,
%
rsp
//
Set
task
switched
flag
mov
%
cr0
,
%
rax
or
$
8
,
%
rax
mov
%
rax
,
%
cr0
//
set
stack
pointer
in
TSS
call
set_current_kernel_stack
//
restore
context
pop
%
rax
wrfsbaseq
%
rax
pop
%
r15
pop
%
r14
pop
%
r13
pop
%
r12
pop
%
r11
pop
%
r10
pop
%
r9
pop
%
r8
pop
%
rdi
pop
%
rsi
pop
%
rbp
pop
%
rbx
pop
%
rdx
pop
%
rcx
pop
%
rax
popfq
ret
///
The
function
triggers
a
context
switch
to
an
idle
task
or
///
a
task
,
which
is
alread
owner
of
the
FPU
.
///
Consequently
the
kernel
don
't set the task switched flag.
.
align
16
switch_to_fpu_owner
:
//
rdi
=
old_stack
=>
the
address
to
store
the
old
rsp
//
rsi
=
new_stack
=>
stack
pointer
of
the
new
task
//
store
context
pushfq
push
%
rax
push
%
rcx
push
%
rdx
push
%
rbx
push
%
rbp
push
%
rsi
push
%
rdi
push
%
r8
push
%
r9
push
%
r10
push
%
r11
push
%
r12
push
%
r13
push
%
r14
push
%
r15
//
push
fs
registers
rdfsbaseq
%
rax
push
%
rax
//
store
the
old
stack
pointer
in
the
dereferenced
first
parameter
\
n
\
t
\
//
and
load
the
new
stack
pointer
in
the
second
parameter
.
\
n
\
t
\
mov
%
rsp
,
(%
rdi
)
mov
%
rsi
,
%
rsp
//
set
stack
pointer
in
TSS
call
set_current_kernel_stack
//
restore
context
pop
%
rax
wrfsbaseq
%
rax
pop
%
r15
pop
%
r14
pop
%
r13
pop
%
r12
pop
%
r11
pop
%
r10
pop
%
r9
pop
%
r8
pop
%
rdi
pop
%
rsi
pop
%
rbp
pop
%
rbx
pop
%
rdx
pop
%
rcx
pop
%
rax
popfq
ret
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment