Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some fixes for the #HV handler #466

Merged
merged 3 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions kernel/src/cpu/idt/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ hv_not_vmpl_switch:
// point, there are two possibilities. If RIP is before the IRET
// instruction itself, then the RSP at the time of #HV exception
// points to the register context that was established for the previous
// exceptoin. In that case, the current RSP can be changed to point
// exception. In that case, the current RSP can be changed to point
// to that exception context, and the #HV can be handled using that
// register context, and when #HV processing completes, the subsequent
// end-of-interrupt flow will restore the context at the time of the
Expand Down Expand Up @@ -171,7 +171,7 @@ restart_hv:
// register state at the time of the exception that was returning at
// the time the #HV arrived.
// At this point, RCX holds the stack pointer at the time of the
// IRET taht was aborted. The first QWORD below that pointer is
// IRET that was aborted. The first QWORD below that pointer is
// reserved for the dummy error code, then the three QWORDS below that
// will hold the RAX, RBX, and RCX values, which are presently stored
// in the top three QWORDs of the current stack.
Expand All @@ -185,7 +185,7 @@ restart_hv:

continue_hv:
// At this point, only the dummy error code and first three registers
// have been pushed onto the stack. Push the remainder o construct a
// have been pushed onto the stack. Push the remainder to construct a
// full exception context.
pushq %rdx
pushq %rsi
Expand Down Expand Up @@ -213,19 +213,14 @@ handle_as_hv:
call process_hv_events
// fall through to default_return

.globl return_new_task
return_new_task:
call setup_new_task
jmp default_return

.globl default_return
default_return:
// Ensure that interrupts are disabled before attempting any return.
cli
testb $3, 17*8(%rsp) // Check CS in exception frame
jnz return_user
return_all_paths:
// If interrupts were prerviously available, then check whether any #HV
// If interrupts were previously available, then check whether any #HV
// events are pending. If so, proceed as if the original trap was
// #HV.
testl $0x200, 18*8(%rsp) // check EFLAGS.IF in exception frame
Expand Down Expand Up @@ -273,6 +268,11 @@ return_user:
// Put user-mode specific return code here
jmp return_all_paths

.globl return_new_task
return_new_task:
call setup_new_task
jmp default_return

// #DE Divide-by-Zero-Error Exception (Vector 0)
default_entry_no_ist name=de handler=panic error_code=0 vector=0

Expand Down
19 changes: 9 additions & 10 deletions kernel/src/cpu/percpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ pub struct PerCpu {
ghcb: OnceCell<GhcbPage>,

/// `#HV` doorbell page for this CPU.
hv_doorbell: OnceCell<&'static HVDoorbell>,
hv_doorbell: Cell<Option<&'static HVDoorbell>>,

init_stack: Cell<Option<VirtAddr>>,
ist: IstStacks,
Expand Down Expand Up @@ -341,7 +341,7 @@ impl PerCpu {

shared: PerCpuShared::new(apic_id),
ghcb: OnceCell::new(),
hv_doorbell: OnceCell::new(),
hv_doorbell: Cell::new(None),
init_stack: Cell::new(None),
ist: IstStacks::new(),
current_stack: Cell::new(MemoryRegion::new(VirtAddr::null(), 0)),
Expand Down Expand Up @@ -408,17 +408,14 @@ impl PerCpu {
}

pub fn hv_doorbell(&self) -> Option<&'static HVDoorbell> {
self.hv_doorbell.get().copied()
self.hv_doorbell.get()
}

/// Gets a pointer to the location of the HV doorbell pointer in the
/// PerCpu structure. Pointers and references have the same layout, so
/// the return type is equivalent to `*const *const HVDoorbell`.
pub fn hv_doorbell_addr(&self) -> *const &'static HVDoorbell {
self.hv_doorbell
.get()
.map(ptr::from_ref)
.unwrap_or(ptr::null())
self.hv_doorbell.as_ptr().cast()
}

pub fn get_top_of_stack(&self) -> VirtAddr {
Expand Down Expand Up @@ -488,9 +485,11 @@ impl PerCpu {

fn setup_hv_doorbell(&self) -> Result<(), SvsmError> {
let doorbell = allocate_hv_doorbell_page(current_ghcb())?;
self.hv_doorbell
.set(doorbell)
.expect("Attempted to reinitialize the HV doorbell page");
assert!(
self.hv_doorbell.get().is_none(),
"Attempted to reinitialize the HV doorbell page"
);
self.hv_doorbell.set(Some(doorbell));
Ok(())
}

Expand Down
Loading