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