Goto sanos source index
//
// mach.c
//
// Interface to physical/virtual machine
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <os/krnl.h>
int probe_vmi(); // from vmi.c
int init_vmi(); // from vmi.c
static void hw_sti() {
__asm sti;
}
static void hw_cli() {
__asm cli;
}
static void hw_hlt() {
__asm hlt;
}
static void hw_iretd() {
__asm add esp,4;
__asm iretd;
}
static void hw_sysret() {
__asm add esp,4;
__asm sysexit;
}
static __declspec(naked) int __fastcall hw_in(port_t port) {
__asm {
mov dx,cx
xor eax,eax
in al,dx
ret
}
}
static __declspec(naked) unsigned short __fastcall hw_inw(port_t port) {
__asm {
mov dx,cx
in ax,dx
ret
}
}
static __declspec(naked) unsigned long __fastcall hw_ind(port_t port) {
__asm {
mov dx,cx
in eax,dx
ret
}
}
static void hw_insw(port_t port, void *buf, int count) {
__asm {
mov edx, port
mov edi, buf
mov ecx, count
rep insw
}
}
static void hw_insd(port_t port, void *buf, int count) {
__asm {
mov edx, port
mov edi, buf
mov ecx, count
rep insd
}
}
static __declspec(naked) int __fastcall hw_out(port_t port, int val) {
__asm {
mov al,dl
mov dx,cx
out dx, al
ret
}
}
static __declspec(naked) unsigned short __fastcall hw_outw(port_t port, unsigned short val) {
__asm {
mov ax,dx
mov dx,cx
out dx, ax
ret
}
}
static __declspec(naked) unsigned long __fastcall hw_outd(port_t port, unsigned long val) {
__asm {
mov eax,edx
mov dx,cx
out dx, eax
ret
}
}
static void hw_outsw(port_t port, void *buf, int count) {
__asm {
mov edx, port
mov esi, buf
mov ecx, count
rep outsw
}
}
static void hw_outsd(port_t port, void *buf, int count) {
__asm {
mov edx, port
mov esi, buf
mov ecx, count
rep outsd
}
}
static void hw_cpuid(unsigned long reg, unsigned long values[4]) {
__asm {
mov eax, reg
cpuid
mov esi, values
mov [esi], eax
mov [esi+4], ebx
mov [esi+8], ecx
mov [esi+12], edx
}
}
static unsigned long hw_get_cr0() {
unsigned long val;
__asm {
mov eax, cr0
mov val, eax
}
return val;
}
static void hw_set_cr0(unsigned long val) {
__asm {
mov eax, val
mov cr0, eax
}
}
static unsigned long hw_get_cr2() {
unsigned long val;
__asm {
mov eax, cr2
mov val, eax
}
return val;
}
static __declspec(naked) unsigned __int64 hw_rdtsc() {
__asm {
rdtsc
ret
}
}
static void hw_wrmsr(unsigned long reg, unsigned long valuelow, unsigned long valuehigh) {
__asm {
mov ecx, reg
mov eax, valuelow
mov edx, valuehigh
wrmsr
}
}
static void hw_set_gdt_entry(int entry, unsigned long addr, unsigned long size, int access, int granularity) {
seginit(&syspage->gdt[entry], addr, size, access, granularity);
}
static void hw_set_idt_gate(int intrno, void *handler) {
syspage->idt[intrno].offset_low = (unsigned short) (((unsigned long) handler) & 0xFFFF);
syspage->idt[intrno].selector = SEL_KTEXT | mach.kring;
syspage->idt[intrno].access = D_PRESENT | D_INT | D_DPL0;
syspage->idt[intrno].offset_high = (unsigned short) (((unsigned long) handler) >> 16);
}
static void hw_set_idt_trap(int intrno, void *handler) {
syspage->idt[intrno].offset_low = (unsigned short) (((unsigned long) handler) & 0xFFFF);
syspage->idt[intrno].selector = SEL_KTEXT | mach.kring;
syspage->idt[intrno].access = D_PRESENT | D_TRAP | D_DPL3;
syspage->idt[intrno].offset_high = (unsigned short) (((unsigned long) handler) >> 16);
}
static void hw_switch_kernel_stack() {
}
static void hw_flushtlb() {
__asm { mov eax, cr3 }
__asm { mov cr3, eax }
}
static void hw_invlpage(void *addr) {
if (cpu.family < CPU_FAMILY_486) {
__asm { mov eax, cr3 }
__asm { mov cr3, eax }
} else {
__asm { mov eax, addr }
__asm { invlpg [eax] }
}
}
static void hw_register_page_dir(unsigned long pfn) {
// Do nothing
}
static void hw_register_page_table(unsigned long pfn) {
// Do nothing
}
static void hw_set_page_dir_entry(pte_t *pde, unsigned long value) {
*pde = value;
}
static void hw_set_page_table_entry(pte_t *pte, unsigned long value) {
*pte = value;
}
static void hw_poweroff() {
if (apm_enabled) {
apm_power_off();
} else {
kprintf("kernel: power management not enabled, system stopped...\n");
}
while (1) {
__asm {
cli
hlt
}
}
}
static void hw_reboot() {
kbd_reboot();
}
struct mach mach = {
0, // kernel ring
hw_sti,
hw_cli,
hw_hlt,
hw_iretd,
hw_sysret,
hw_in,
hw_inw,
hw_ind,
hw_insw,
hw_insd,
hw_out,
hw_outw,
hw_outd,
hw_outsw,
hw_outsd,
hw_cpuid,
hw_get_cr0,
hw_set_cr0,
hw_get_cr2,
hw_rdtsc,
hw_wrmsr,
hw_set_gdt_entry,
hw_set_idt_gate,
hw_set_idt_trap,
hw_switch_kernel_stack,
hw_flushtlb,
hw_invlpage,
hw_register_page_dir,
hw_register_page_table,
hw_set_page_dir_entry,
hw_set_page_table_entry,
hw_poweroff,
hw_reboot
};
#ifdef VMACH
void init_mach() {
kprintf("mach: running in machine virtualization mode\n");
if (probe_vmi()) init_vmi();
}
#else
void init_mach() {
}
#endif