switch (Width)
{
case 8:
- *Value = inportb(Address);
+ *Value = cpu_read_port_byte(Address);
break;
case 16:
- *Value = inportw(Address);
+ *Value = cpu_read_port_word(Address);
break;
case 32:
- *Value = inportl(Address);
+ *Value = cpu_read_port_dword(Address);
break;
default:
return AE_SUPPORT;
switch (Width)
{
case 8:
- outportb(Address, Value);
+ cpu_write_port_byte(Address, Value);
break;
case 16:
- outportw(Address, Value);
+ cpu_write_port_word(Address, Value);
break;
case 32:
- outportl(Address, Value);
+ cpu_write_port_dword(Address, Value);
break;
default:
return AE_SUPPORT;
case POWER_STATE_OFF:
AcpiEnterSleepStatePrep(ACPI_STATE_S5);
- disable_ints();
+ cpu_disable_interrupts();
AcpiEnterSleepState(ACPI_STATE_S5);
break;
while (timeout--)
{
- byte_t msr = inportb(FLOPPY_MSR);
+ byte_t msr = cpu_read_port_byte(FLOPPY_MSR);
if (msr & 0x80) break;
syscall_sleep(1);
}
- if (timeout != 0) outportb(FLOPPY_FIFO, byte);
+ if (timeout != 0) cpu_write_port_byte(FLOPPY_FIFO, byte);
else return FALSE;
return TRUE;
while (timeout--)
{
- byte_t msr = inportb(FLOPPY_MSR);
+ byte_t msr = cpu_read_port_byte(FLOPPY_MSR);
if (msr & 0x80) break;
syscall_sleep(1);
}
- if (timeout != 0) *byte = inportb(FLOPPY_FIFO);
+ if (timeout != 0) *byte = cpu_read_port_byte(FLOPPY_FIFO);
else return FALSE;
return TRUE;
static void floppy_select(byte_t drive)
{
- byte_t dor = inportb(FLOPPY_DOR);
+ byte_t dor = cpu_read_port_byte(FLOPPY_DOR);
dor &= 0xFC;
dor |= drive & 1;
- outportb(FLOPPY_DOR, dor);
+ cpu_write_port_byte(FLOPPY_DOR, dor);
}
static void floppy_reset()
{
dword_t i;
- outportb(FLOPPY_DOR, 0x00);
- outportb(FLOPPY_DOR, 0x0C);
+ cpu_write_port_byte(FLOPPY_DOR, 0x00);
+ cpu_write_port_byte(FLOPPY_DOR, 0x0C);
floppy_wait_irq(NO_TIMEOUT);
for (i = 0; i < 4; i++) floppy_sense_interrupt();
floppy_fifo_write(FLOPPY_SRT << 4 | FLOPPY_HUT);
floppy_fifo_write(FLOPPY_HLT << 1);
- outportb(FLOPPY_CCR, 0x00);
+ cpu_write_port_byte(FLOPPY_CCR, 0x00);
floppy_select(0);
}
}
else if (floppy_motor_status[i] == FLOPPY_MOTOR_STOPPING)
{
- byte_t dor = inportb(FLOPPY_DOR);
+ byte_t dor = cpu_read_port_byte(FLOPPY_DOR);
dor &= ~(1 << (4 + i));
- outportb(FLOPPY_DOR, dor);
+ cpu_write_port_byte(FLOPPY_DOR, dor);
floppy_motor_status[i] = FLOPPY_MOTOR_STOPPED;
}
if (floppy_motor_status[drive & 1] == FLOPPY_MOTOR_STOPPED)
{
- byte_t dor = inportb(FLOPPY_DOR);
+ byte_t dor = cpu_read_port_byte(FLOPPY_DOR);
dor |= 1 << (4 + (drive & 1));
- outportb(FLOPPY_DOR, dor);
+ cpu_write_port_byte(FLOPPY_DOR, dor);
syscall_sleep(300);
}
{
init_mutex(&irq_mutex, 0);
- outportb(CMOS_CMD_PORT, CMOS_FLOPPY_REG);
- byte_t floppy_data = inportb(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_FLOPPY_REG);
+ byte_t floppy_data = cpu_read_port_byte(CMOS_DATA_PORT);
if (!floppy_data) return ERR_NOTFOUND;
dword_t ret = register_irq_handler(FLOPPY_IRQ, floppy_irq_handler, TRUE);
{
qword_t end_time = syscall_get_milliseconds() + (qword_t)PS2_TIMEOUT;
- while (!(inportb(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL))
+ while (!(cpu_read_port_byte(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL))
{
if (syscall_get_milliseconds() >= end_time) return FALSE;
}
- *byte = inportb(PS2_DATA_PORT);
+ *byte = cpu_read_port_byte(PS2_DATA_PORT);
return TRUE;
}
{
qword_t end_time = syscall_get_milliseconds() + (qword_t)PS2_TIMEOUT;
- while (inportb(PS2_STATUS_PORT) & PS2_INPUT_BUFFER_FULL)
+ while (cpu_read_port_byte(PS2_STATUS_PORT) & PS2_INPUT_BUFFER_FULL)
{
if (syscall_get_milliseconds() >= end_time) return FALSE;
}
- outportb(PS2_DATA_PORT, byte);
+ cpu_write_port_byte(PS2_DATA_PORT, byte);
return TRUE;
}
while (retries--)
{
- inportb(PS2_DATA_PORT);
+ cpu_read_port_byte(PS2_DATA_PORT);
- if (port) outportb(PS2_CONTROL_PORT, PS2_CMD_SEND_TO_SECONDARY);
+ if (port) cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_SEND_TO_SECONDARY);
if (!poll_and_write(command)) return PS2_DEVICE_RESPONSE_FAILURE;
va_start(args, num_params);
for (i = 0; i < num_params; i++)
{
- if (port) outportb(PS2_CONTROL_PORT, PS2_CMD_SEND_TO_SECONDARY);
+ if (port) cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_SEND_TO_SECONDARY);
if (!poll_and_write(va_arg(args, uintptr_t)))
{
va_end(args);
byte_t port = int_num == PS2_FIRST_IRQ ? 0 : 1;
release_mutex(&irq_mutex[port]);
- if (!(inportb(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL)) return;
- byte_t buffer = inportb(PS2_DATA_PORT);
+ if (!(cpu_read_port_byte(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL)) return;
+ byte_t buffer = cpu_read_port_byte(PS2_DATA_PORT);
if (buffer == 0xAA && ps2_devices[port] == NULL)
{
byte_t working_ports = 3;
byte_t buffer;
- outportb(PS2_CONTROL_PORT, PS2_CMD_DISABLE_FIRST_PORT);
- outportb(PS2_CONTROL_PORT, PS2_CMD_DISABLE_SECOND_PORT);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_DISABLE_FIRST_PORT);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_DISABLE_SECOND_PORT);
- while (inportb(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL) inportb(PS2_DATA_PORT);
+ while (cpu_read_port_byte(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL) cpu_read_port_byte(PS2_DATA_PORT);
- outportb(PS2_CONTROL_PORT, PS2_CMD_TEST_CONTROLLER);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_TEST_CONTROLLER);
if (!poll_and_read(&buffer)) return ERR_HARDWARE;
if (buffer != 0x55) return ERR_HARDWARE;
- outportb(PS2_CONTROL_PORT, PS2_CMD_READ_CONFIG);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_READ_CONFIG);
byte_t config;
if (!poll_and_read(&config)) return ERR_HARDWARE;
- outportb(PS2_CONTROL_PORT, PS2_CMD_WRITE_CONFIG);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_WRITE_CONFIG);
if (!poll_and_write(1 << 2)) return ERR_HARDWARE;
- outportb(PS2_CONTROL_PORT, PS2_CMD_TEST_FIRST_PORT);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_TEST_FIRST_PORT);
if (!poll_and_read(&buffer)) working_ports &= ~(1 << 0);
if (buffer) working_ports &= ~(1 << 0);
- outportb(PS2_CONTROL_PORT, PS2_CMD_TEST_SECOND_PORT);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_TEST_SECOND_PORT);
if (!poll_and_read(&buffer)) working_ports &= ~(1 << 1);
if (buffer) working_ports &= ~(1 << 1);
if (!working_ports) return ERR_NOTFOUND;
}
config |= working_ports;
- outportb(PS2_CONTROL_PORT, PS2_CMD_WRITE_CONFIG);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_WRITE_CONFIG);
if (!poll_and_write(config)) return ERR_HARDWARE;
- if (working_ports & (1 << 0)) outportb(PS2_CONTROL_PORT, PS2_CMD_ENABLE_FIRST_PORT);
- if (working_ports & (1 << 1)) outportb(PS2_CONTROL_PORT, PS2_CMD_ENABLE_SECOND_PORT);
+ if (working_ports & (1 << 0)) cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_ENABLE_FIRST_PORT);
+ if (working_ports & (1 << 1)) cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_ENABLE_SECOND_PORT);
if (working_ports & (1 << 0)) poll_and_write(PS2_DEVICE_CMD_RESET);
if (working_ports & (1 << 1))
{
- outportb(PS2_CONTROL_PORT, PS2_CMD_SEND_TO_SECONDARY);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_SEND_TO_SECONDARY);
poll_and_write(PS2_DEVICE_CMD_RESET);
}
{
int i;
- outportb(PS2_CONTROL_PORT, PS2_CMD_DISABLE_FIRST_PORT);
- outportb(PS2_CONTROL_PORT, PS2_CMD_DISABLE_SECOND_PORT);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_DISABLE_FIRST_PORT);
+ cpu_write_port_byte(PS2_CONTROL_PORT, PS2_CMD_DISABLE_SECOND_PORT);
unregister_irq_handler(PS2_FIRST_IRQ, &ps2_irq_handler);
unregister_irq_handler(PS2_SECOND_IRQ, &ps2_irq_handler);
word_t divisor = SERIAL_BAUD_FREQ / baud;
if (divisor == 0) divisor = 1;
- outportb(device->port + SERIAL_LCR, inportb(device->port + SERIAL_LCR) | SERIAL_DLAB_BIT);
- outportb(device->port + SERIAL_DLR, divisor & 0xFF);
- outportb(device->port + SERIAL_DHR, divisor >> 8);
- outportb(device->port + SERIAL_LCR, inportb(device->port + SERIAL_LCR) & ~SERIAL_DLAB_BIT);
+ cpu_write_port_byte(device->port + SERIAL_LCR, cpu_read_port_byte(device->port + SERIAL_LCR) | SERIAL_DLAB_BIT);
+ cpu_write_port_byte(device->port + SERIAL_DLR, divisor & 0xFF);
+ cpu_write_port_byte(device->port + SERIAL_DHR, divisor >> 8);
+ cpu_write_port_byte(device->port + SERIAL_LCR, cpu_read_port_byte(device->port + SERIAL_LCR) & ~SERIAL_DLAB_BIT);
}
static void serial_irq_handler(registers_t *regs, byte_t irq_num)
serial_port_t *device = CONTAINER_OF(get_char_device(name), serial_port_t, header);
if (!device) continue;
- byte_t status = inportb(device->port + SERIAL_IIR);
+ byte_t status = cpu_read_port_byte(device->port + SERIAL_IIR);
if ((status & 0x07) == 2) release_semaphore(&device->write_mutex, 1);
else if ((status & 0x07) == 4) release_semaphore(&device->read_mutex, 1);
init_semaphore(&device->write_mutex, 0, 1);
set_baud_rate(device, SERIAL_BAUD_FREQ);
- outportb(device->port + SERIAL_IER, 0x03);
- outportb(device->port + SERIAL_FCR,
+ cpu_write_port_byte(device->port + SERIAL_IER, 0x03);
+ cpu_write_port_byte(device->port + SERIAL_FCR,
SERIAL_FIFO_ENABLED_BIT
| SERIAL_RECV_FIFO_FLUSH_BIT
| SERIAL_SEND_FIFO_FLUSH_BIT);
- outportb(device->port + SERIAL_LCR, 0x03);
- outportb(device->port + SERIAL_MCR, 0x00);
+ cpu_write_port_byte(device->port + SERIAL_LCR, 0x03);
+ cpu_write_port_byte(device->port + SERIAL_MCR, 0x00);
ret = register_char_device(&device->header);
if (ret != ERR_SUCCESS) goto cleanup;
break;
}
- if (!(inportb(serial->port + SERIAL_LSR) & SERIAL_RECV_RDY_BIT))
+ if (!(cpu_read_port_byte(serial->port + SERIAL_LSR) & SERIAL_RECV_RDY_BIT))
{
if (wait_semaphore(&serial->read_mutex, 1, (dword_t)-1) == ERR_CANCELED)
{
}
}
- ((byte_t*)buffer)[i] = inportb(serial->port + SERIAL_DATA);
+ ((byte_t*)buffer)[i] = cpu_read_port_byte(serial->port + SERIAL_DATA);
}
return ret;
break;
}
- if (!(inportb(serial->port + SERIAL_LSR) & SERIAL_SEND_RDY_BIT))
+ if (!(cpu_read_port_byte(serial->port + SERIAL_LSR) & SERIAL_SEND_RDY_BIT))
{
if (wait_semaphore(&serial->write_mutex, 1, (dword_t)-1) == ERR_CANCELED)
{
}
}
- outportb(serial->port + SERIAL_DATA, ((const byte_t*)buffer)[i]);
+ cpu_write_port_byte(serial->port + SERIAL_DATA, ((const byte_t*)buffer)[i]);
}
return ret;
case IOCTL_CHAR_DEV_CHECK_INPUT:
if (out_length >= sizeof(size_t))
{
- *((size_t*)out_buffer) = (inportb(serial->port + SERIAL_LSR) & SERIAL_RECV_RDY_BIT) ? 1 : 0;
+ *((size_t*)out_buffer) = (cpu_read_port_byte(serial->port + SERIAL_LSR) & SERIAL_RECV_RDY_BIT) ? 1 : 0;
return ERR_SUCCESS;
}
else
case IOCTL_CHAR_DEV_CHECK_OUTPUT:
if (out_length >= sizeof(size_t))
{
- *((size_t*)out_buffer) = (inportb(serial->port + SERIAL_LSR) & SERIAL_SEND_RDY_BIT) ? 1 : 0;
+ *((size_t*)out_buffer) = (cpu_read_port_byte(serial->port + SERIAL_LSR) & SERIAL_SEND_RDY_BIT) ? 1 : 0;
return ERR_SUCCESS;
}
else
{
dword_t divisor = TIMER_BASE_FREQUENCY / frequency;
- outportb(TIMER_CMD_PORT, TIMER_SQUARE_WAVE(2));
- outportb(TIMER_CHANNEL_PORT(2), (byte_t) (divisor & 0xFF));
- outportb(TIMER_CHANNEL_PORT(2), (byte_t) (divisor >> 8));
- outportb(0x61, inportb(0x61) | 3);
+ cpu_write_port_byte(TIMER_CMD_PORT, TIMER_SQUARE_WAVE(2));
+ cpu_write_port_byte(TIMER_CHANNEL_PORT(2), (byte_t) (divisor & 0xFF));
+ cpu_write_port_byte(TIMER_CHANNEL_PORT(2), (byte_t) (divisor >> 8));
+ cpu_write_port_byte(0x61, cpu_read_port_byte(0x61) | 3);
}
static void speaker_off()
{
- outportb(0x61, inportb(0x61) & 0xFC);
+ cpu_write_port_byte(0x61, cpu_read_port_byte(0x61) & 0xFC);
}
static dword_t speaker_init(void)
#include <stdlib.h>
#include <string.h>
#include <sdk/defs.h>
+#include <cpu.h>
/* Monolithium-specific Helper Macros */
#define SEGMENT_RPL(x) ((x) & 0x03)
#define DOUBLE_CORNER_RIGHT_DOWN 0xC9
#define DOUBLE_CORNER_RIGHT_MID 0xCC
-#define IO_PORT_FUNCTIONS(s, t) \
- static inline t inport##s(word_t port) \
- { \
- t value; \
- asm volatile ("in" #s " %1, %0\n" : "=a"(value) : "Nd"(port)); \
- return value; \
- } \
- \
- static inline void outport##s(word_t port, t value) \
- { \
- asm volatile ("out" #s " %0, %1\n" :: "a"(value), "Nd"(port)); \
- } \
- \
- static inline void inportbuf##s(word_t port, t *buffer, size_t size) \
- { \
- asm volatile("cld\n" \
- "rep; ins" #s "\n" \
- :"+D"(buffer), "+c"(size) \
- : "d"(port) \
- : "cc"); \
- } \
- \
- static inline void outportbuf##s(word_t port, const t *buffer, size_t size) \
- { \
- asm volatile("cld\n" \
- "rep; outs\n" \
- : "+S"(buffer), "+c"(size) \
- : "d"(port) \
- : "cc"); \
- }
-
-IO_PORT_FUNCTIONS(b, byte_t)
-IO_PORT_FUNCTIONS(w, word_t)
-IO_PORT_FUNCTIONS(l, dword_t)
-
-static inline bool_t check_ints()
-{
- dword_t eflags;
- asm volatile ("pushfl\n"
- "popl %0"
- : "=g"(eflags));
- return (eflags & 0x200) != 0 ? TRUE : FALSE;
-}
-
-static inline bool_t enable_ints()
-{
- bool_t old = check_ints();
- asm volatile ("sti");
- return old;
-}
-
-static inline bool_t disable_ints()
-{
- bool_t old = check_ints();
- asm volatile ("cli");
- return old;
-}
-
-static inline void halt()
-{
- asm volatile ("hlt");
-}
-
static inline void enable_nmi()
{
- outportb(0x70, inportb(0x70) & 0x7F);
+ cpu_write_port_byte(0x70, cpu_read_port_byte(0x70) & 0x7F);
}
static inline void disable_nmi()
{
- outportb(0x70, inportb(0x70) | 0x80);
+ cpu_write_port_byte(0x70, cpu_read_port_byte(0x70) | 0x80);
}
#endif
#ifndef _CPU_H_
#define _CPU_H_
-#include <common.h>
+#include <sdk/defs.h>
#include <sdk/cpu.h>
-#define CPU_FEATURE_FPU (1 << 0)
-#define CPU_FEATURE_VME (1 << 1)
-#define CPU_FEATURE_DE (1 << 2)
-#define CPU_FEATURE_PSE (1 << 3)
-#define CPU_FEATURE_TSC (1 << 4)
-#define CPU_FEATURE_MSR (1 << 5)
-#define CPU_FEATURE_PAE (1 << 6)
-#define CPU_FEATURE_MCE (1 << 7)
-#define CPU_FEATURE_CX8 (1 << 8)
-#define CPU_FEATURE_APIC (1 << 9)
-#define CPU_FEATURE_SEP (1 << 11)
-#define CPU_FEATURE_MTRR (1 << 12)
-#define CPU_FEATURE_PGE (1 << 13)
-#define CPU_FEATURE_MCA (1 << 14)
-#define CPU_FEATURE_CMOV (1 << 15)
-#define CPU_FEATURE_PAT (1 << 16)
-#define CPU_FEATURE_PSE36 (1 << 17)
-#define CPU_FEATURE_PSN (1 << 18)
-#define CPU_FEATURE_CLFL (1 << 19)
-#define CPU_FEATURE_DTES (1 << 21)
-#define CPU_FEATURE_ACPI (1 << 22)
-#define CPU_FEATURE_MMX (1 << 23)
-#define CPU_FEATURE_FXSR (1 << 24)
-#define CPU_FEATURE_SSE (1 << 25)
-#define CPU_FEATURE_SSE2 (1 << 26)
-#define CPU_FEATURE_SS (1 << 27)
-#define CPU_FEATURE_HTT (1 << 28)
-#define CPU_FEATURE_TM1 (1 << 29)
-#define CPU_FEATURE_IA64 (1 << 30)
-#define CPU_FEATURE_PBE (1 << 31)
-
-extern void cpu_init(void);
-extern void cpu_measure_speed(void);
-extern void fpu_save(byte_t *data);
-extern void fpu_restore(byte_t *data);
-extern void stall(dword_t microseconds);
-
-extern char cpu_vendor[13];
-extern dword_t cpu_features[2];
+#define CPU_CONTROL_FLAG_PE (1 << 0)
+#define CPU_CONTROL_FLAG_MP (1 << 1)
+#define CPU_CONTROL_FLAG_EM (1 << 2)
+#define CPU_CONTROL_FLAG_TS (1 << 3)
+#define CPU_CONTROL_FLAG_ET (1 << 4)
+#define CPU_CONTROL_FLAG_NE (1 << 5)
+#define CPU_CONTROL_FLAG_WP (1 << 16)
+#define CPU_CONTROL_FLAG_AM (1 << 18)
+#define CPU_CONTROL_FLAG_NW (1 << 29)
+#define CPU_CONTROL_FLAG_CD (1 << 30)
+#define CPU_CONTROL_FLAG_PG (1 << 31)
+
+#define CPU_FEATURE_FLAG_VME (1 << 0)
+#define CPU_FEATURE_FLAG_PVI (1 << 1)
+#define CPU_FEATURE_FLAG_TSD (1 << 2)
+#define CPU_FEATURE_FLAG_DE (1 << 3)
+#define CPU_FEATURE_FLAG_PSE (1 << 4)
+#define CPU_FEATURE_FLAG_PAE (1 << 5)
+#define CPU_FEATURE_FLAG_MCE (1 << 6)
+#define CPU_FEATURE_FLAG_PGE (1 << 7)
+#define CPU_FEATURE_FLAG_PCE (1 << 8)
+#define CPU_FEATURE_FLAG_OSXFSR (1 << 9)
+#define CPU_FEATURE_FLAG_OSXMMEXCPT (1 << 10)
+#define CPU_FEATURE_FLAG_UMIP (1 << 11)
+#define CPU_FEATURE_FLAG_LA57 (1 << 12)
+#define CPU_FEATURE_FLAG_VMXE (1 << 13)
+#define CPU_FEATURE_FLAG_SMXE (1 << 14)
+#define CPU_FEATURE_FLAG_FSGSBASE (1 << 16)
+#define CPU_FEATURE_FLAG_PCIDE (1 << 17)
+#define CPU_FEATURE_FLAG_OSXSAVE (1 << 18)
+#define CPU_FEATURE_FLAG_SMEP (1 << 20)
+#define CPU_FEATURE_FLAG_SMAP (1 << 21)
+#define CPU_FEATURE_FLAG_PKE (1 << 22)
+
+enum
+{
+ FPU_NOT_PRESENT = 0,
+ FPU_LEGACY,
+ FPU_XFSR,
+};
+
+typedef word_t port_t;
+
+#define IO_PORT_FUNCTIONS(type) \
+ static inline type##_t cpu_read_port_##type(port_t port) \
+ { \
+ type##_t value; \
+ __asm__ volatile ("in %1, %0\n" : "=a"(value) : "Nd"(port)); \
+ return value; \
+ } \
+ \
+ static inline void cpu_write_port_##type(port_t port, type##_t value) \
+ { \
+ __asm__ volatile ("out %0, %1\n" :: "a"(value), "Nd"(port)); \
+ } \
+ \
+ static inline void cpu_read_port_buffer_##type(port_t port, type##_t *buffer, size_t size) \
+ { \
+ __asm__ volatile("cld\n" \
+ "rep; ins\n" \
+ :"+D"(buffer), "+c"(size) \
+ : "d"(port) \
+ : "cc"); \
+ } \
+ \
+ static inline void cpu_write_port_buffer_##type(port_t port, const type##_t *buffer, size_t size) \
+ { \
+ __asm__ volatile("cld\n" \
+ "rep; outs\n" \
+ : "+S"(buffer), "+c"(size) \
+ : "d"(port) \
+ : "cc"); \
+ }
+
+IO_PORT_FUNCTIONS(byte)
+IO_PORT_FUNCTIONS(word)
+IO_PORT_FUNCTIONS(dword)
+
+static inline uintptr_t cpu_read_master_control_register(void)
+{
+ uintptr_t value;
+ __asm__ volatile ("movl %%cr0, %0"
+ : "=r"((dword_t)value) /* output */
+ : /* input */
+ : /* clobber */);
+ return value;
+}
+
+static inline void cpu_write_master_control_register(uintptr_t value)
+{
+ __asm__ volatile ("movl %0, %%cr0"
+ : /* output */
+ : "r"((dword_t)value) /* input */
+ : /* clobber */);
+}
+
+static inline uintptr_t cpu_read_faulting_address(void)
+{
+ uintptr_t value;
+ __asm__ volatile ("movl %%cr2, %0"
+ : "=r"((dword_t)value) /* output */
+ : /* input */
+ : /* clobber */);
+ return value;
+}
+
+static inline uintptr_t cpu_read_page_table_register(void)
+{
+ uintptr_t value;
+ __asm__ volatile ("movl %%cr3, %0"
+ : "=r"((dword_t)value) /* output */
+ : /* input */
+ : /* clobber */);
+ return value;
+}
+
+static inline void cpu_write_page_table_register(uintptr_t value)
+{
+ __asm__ volatile ("movl %0, %%cr3"
+ : /* output */
+ : "r"((dword_t)value) /* input */
+ : /* clobber */);
+}
+
+static inline uintptr_t cpu_read_feature_register(void)
+{
+ uintptr_t value;
+ __asm__ volatile ("movl %%cr4, %0"
+ : "=r"((dword_t)value) /* output */
+ : /* input */
+ : /* clobber */);
+ return value;
+}
+
+static inline void cpu_write_feature_register(uintptr_t value)
+{
+ __asm__ volatile ("movl %0, %%cr4"
+ : /* output */
+ : "r"((dword_t)value) /* input */
+ : /* clobber */);
+}
+
+static inline bool_t cpu_enable_interrupts(void)
+{
+ dword_t flags;
+ __asm__ volatile ("pushf\n"
+ "sti\n"
+ "pop %0"
+ : "=g"(flags) /* output */
+ : /* input */
+ : /* clobber */);
+ return !!(flags & CPU_STATUS_FLAG_IF);
+}
+
+static inline bool_t cpu_disable_interrupts(void)
+{
+ dword_t flags;
+ __asm__ volatile ("pushf\n"
+ "cli\n"
+ "pop %0"
+ : "=g"(flags) /* output */
+ : /* input */
+ : /* clobber */);
+ return !!(flags & CPU_STATUS_FLAG_IF);
+}
+
+static inline void cpu_set_interrupt_table(void *base, word_t size)
+{
+ struct
+ {
+ word_t length;
+ void *base;
+ } __attribute__((__packed__)) idtr = { size - 1, base };
+
+ __asm__ volatile ("lidt %0"
+ : /* output */
+ : "m"(idtr) /* input */
+ : /* clobber */);
+}
+
+static inline void cpu_invalidate_tlb(void *address)
+{
+ __asm__ volatile ("invlpg (%0)"
+ : /* output */
+ : "r"(address) /* input */
+ : "memory" /* clobber */);
+}
+
+static inline void cpu_halt(void)
+{
+ __asm__ volatile ("hlt");
+}
+
+extern int cpu_fpu_present;
+extern byte_t cpu_max_physical_bits;
+
+static inline void cpu_save_fpu_state(void *state)
+{
+ switch (cpu_fpu_present)
+ {
+ case FPU_LEGACY:
+ asm volatile ("fsave %0"
+ : "=m"(*(byte_t*)state) /* output */
+ : /* input */
+ : /* clobber */);
+ break;
+
+ case FPU_XFSR:
+ asm volatile ("fxsave %0"
+ : "=m"(*(byte_t*)state) /* output */
+ : /* input */
+ : /* clobber */);
+ break;
+ }
+}
+
+static inline void cpu_restore_fpu_state(void *state)
+{
+ switch (cpu_fpu_present)
+ {
+ case FPU_LEGACY:
+ asm volatile ("frstor %0"
+ : /* output */
+ : "m"(*(byte_t*)state) /* input */
+ : /* clobber */);
+ break;
+
+ case FPU_XFSR:
+ asm volatile ("fxrstor %0"
+ : /* output */
+ : "m"(*(byte_t*)state) /* input */
+ : /* clobber */);
+ break;
+ }
+}
+
+void cpu_init(void);
#endif
#include <common.h>
#include <thread.h>
#include <interrupt.h>
-
-#define EFLAGS_VM (1<<17)
-#define EFLAGS_IF (1<<9)
-#define EFLAGS_DF (1<<10)
-#define PREFIX_LOCK (1<<0)
-#define PREFIX_OPSIZE (1<<1)
-#define PREFIX_ADDRSIZE (1<<2)
-#define PREFIX_REP (1<<3)
-#define PREFIX_REPNZ (1<<4)
-#define PREFIX_ES (1<<5)
-#define PREFIX_SS (1<<6)
-#define PREFIX_FS (1<<7)
-#define PREFIX_GS (1<<8)
-
-#define VM86_MEM_START 0x10000
-#define VM86_MEM_END 0x90000
-#define VM86_MEM_PARAGRAPHS ((VM86_MEM_END - VM86_MEM_START) >> 4)
-
-#define VM86_TRAMPOLINE_CS 0x0000
-#define VM86_TRAMPOLINE_IP 0xE000
-#define VM86_TRAMPOLINE_SS 0x0000
-#define VM86_TRAMPOLINE_SP 0xDFFA
+#include <cpu.h>
typedef struct
{
dword_t eip, cs, eflags, esp, ss, es, ds, fs, gs;
} vm86_registers_t;
+void vm86_handler(registers_ext_vm86_t *regs);
word_t vm86_alloc(word_t size);
void vm86_free(word_t paragraph);
-void vm86_handler(registers_ext_vm86_t *regs);
dword_t vm86_interrupt(byte_t number, vm86_registers_t *regs);
#endif
{
bool_t pm = FALSE;
- outportb(CMOS_CMD_PORT, CMOS_RTC_SECONDS_REG);
- byte_t seconds = inportb(CMOS_DATA_PORT);
- outportb(CMOS_CMD_PORT, CMOS_RTC_MINUTES_REG);
- byte_t minutes = inportb(CMOS_DATA_PORT);
- outportb(CMOS_CMD_PORT, CMOS_RTC_HOURS_REG);
- byte_t hours = inportb(CMOS_DATA_PORT);
- outportb(CMOS_CMD_PORT, CMOS_RTC_DAY_REG);
- byte_t day = inportb(CMOS_DATA_PORT);
- outportb(CMOS_CMD_PORT, CMOS_RTC_MONTH_REG);
- byte_t month = inportb(CMOS_DATA_PORT);
- outportb(CMOS_CMD_PORT, CMOS_RTC_YEAR_REG);
- byte_t year = inportb(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_SECONDS_REG);
+ byte_t seconds = cpu_read_port_byte(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_MINUTES_REG);
+ byte_t minutes = cpu_read_port_byte(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_HOURS_REG);
+ byte_t hours = cpu_read_port_byte(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_DAY_REG);
+ byte_t day = cpu_read_port_byte(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_MONTH_REG);
+ byte_t month = cpu_read_port_byte(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_YEAR_REG);
+ byte_t year = cpu_read_port_byte(CMOS_DATA_PORT);
if (hours & CLOCK_PM_BIT) pm = TRUE;
hours &= ~CLOCK_PM_BIT;
clock_current_time.month = month;
clock_current_time.year = year;
- outportb(CMOS_CMD_PORT, CMOS_RTC_STC_REG);
- inportb(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_STC_REG);
+ cpu_read_port_byte(CMOS_DATA_PORT);
}
bool_t clock_check_time(clock_time_t *time)
clock_current_time.year = safe_time.year;
disable_nmi();
- outportb(CMOS_CMD_PORT, CMOS_RTC_SECONDS_REG);
- outportb(CMOS_DATA_PORT, seconds);
- outportb(CMOS_CMD_PORT, CMOS_RTC_MINUTES_REG);
- outportb(CMOS_DATA_PORT, minutes);
- outportb(CMOS_CMD_PORT, CMOS_RTC_HOURS_REG);
- outportb(CMOS_DATA_PORT, hours);
- outportb(CMOS_CMD_PORT, CMOS_RTC_DAY_REG);
- outportb(CMOS_DATA_PORT, day);
- outportb(CMOS_CMD_PORT, CMOS_RTC_MONTH_REG);
- outportb(CMOS_DATA_PORT, month);
- outportb(CMOS_CMD_PORT, CMOS_RTC_YEAR_REG);
- outportb(CMOS_DATA_PORT, year);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_SECONDS_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, seconds);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_MINUTES_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, minutes);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_HOURS_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, hours);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_DAY_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, day);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_MONTH_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, month);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_YEAR_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, year);
enable_nmi();
leave_critical(&critical);
critical_t critical;
enter_critical(&critical);
- outportb(CMOS_CMD_PORT, CMOS_RTC_STB_REG);
- clock_settings = inportb(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_STB_REG);
+ clock_settings = cpu_read_port_byte(CMOS_DATA_PORT);
if ((clock_settings & (CLOCK_ALARM_INT | CLOCK_PERIODIC_INT | CLOCK_UPDATE_INT)) != CLOCK_UPDATE_INT)
{
clock_settings |= CLOCK_UPDATE_INT;
disable_nmi();
- outportb(CMOS_CMD_PORT, CMOS_RTC_STB_REG);
- outportb(CMOS_DATA_PORT, clock_settings);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_STB_REG);
+ cpu_write_port_byte(CMOS_DATA_PORT, clock_settings);
enable_nmi();
}
register_irq_handler(CLOCK_IRQ, &clock_irq, FALSE);
- outportb(CMOS_CMD_PORT, CMOS_RTC_STC_REG);
- inportb(CMOS_DATA_PORT);
+ cpu_write_port_byte(CMOS_CMD_PORT, CMOS_RTC_STC_REG);
+ cpu_read_port_byte(CMOS_DATA_PORT);
leave_critical(&critical);
}
+++ /dev/null
-;
-; cpu.asm
-;
-; Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
-;
-; This program is free software: you can redistribute it and/or modify
-; it under the terms of the GNU Affero General Public License as
-; published by the Free Software Foundation, either version 3 of the
-; License, or (at your option) any later version.
-;
-; This program is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-; GNU Affero General Public License for more details.
-;
-; You should have received a copy of the GNU Affero General Public License
-; along with this program. If not, see <http://www.gnu.org/licenses/>.
-;
-
-CPU_FEATURE_FPU EQU 1 << 0
-CPU_FEATURE_VME EQU 1 << 1
-CPU_FEATURE_DE EQU 1 << 2
-CPU_FEATURE_PSE EQU 1 << 3
-CPU_FEATURE_TSC EQU 1 << 4
-CPU_FEATURE_MSR EQU 1 << 5
-CPU_FEATURE_PAE EQU 1 << 6
-CPU_FEATURE_MCE EQU 1 << 7
-CPU_FEATURE_CX8 EQU 1 << 8
-CPU_FEATURE_APIC EQU 1 << 9
-CPU_FEATURE_SEP EQU 1 << 11
-CPU_FEATURE_MTRR EQU 1 << 12
-CPU_FEATURE_PGE EQU 1 << 13
-CPU_FEATURE_MCA EQU 1 << 14
-CPU_FEATURE_CMOV EQU 1 << 15
-CPU_FEATURE_PAT EQU 1 << 16
-CPU_FEATURE_PSE36 EQU 1 << 17
-CPU_FEATURE_PSN EQU 1 << 18
-CPU_FEATURE_CLFL EQU 1 << 19
-CPU_FEATURE_DTES EQU 1 << 21
-CPU_FEATURE_ACPI EQU 1 << 22
-CPU_FEATURE_MMX EQU 1 << 23
-CPU_FEATURE_FXSR EQU 1 << 24
-CPU_FEATURE_SSE EQU 1 << 25
-CPU_FEATURE_SSE2 EQU 1 << 26
-CPU_FEATURE_SS EQU 1 << 27
-CPU_FEATURE_HTT EQU 1 << 28
-CPU_FEATURE_TM1 EQU 1 << 29
-CPU_FEATURE_IA64 EQU 1 << 30
-CPU_FEATURE_PBE EQU 1 << 31
-
-bits 32
-
-global cpu_init
-global fpu_save
-global fpu_restore
-global cpu_vendor
-global cpu_features
-
-cpu_vendor: times 16 DB 0
-cpu_features: times 2 DD 0
-
-;********************************************************************************
-; void cpu_init(void)
-;********************************************************************************
-cpu_init: push ebp
- mov ebp, esp
- sub esp, 4
-.fpu_check: mov eax, cr0
- and eax, 0xFFFFFFF3
- or eax, 0x20
- mov cr0, eax
- fninit
- mov word [ebp - 4], 0xCCCC
- fnstsw word [ebp - 4]
- cmp word [ebp - 4], 0
- jnz .cpuid_check
- or byte [cpu_features], 1
-.cpuid_check: pushfd
- pop eax
- xor eax, 0x200000
- push eax
- popfd
- pushfd
- pop edx
- cmp eax, edx
- jnz .no_cpuid
- xor eax, eax
- push ebx
- cpuid
- mov dword [cpu_vendor], ebx
- mov dword [cpu_vendor + 4], edx
- mov dword [cpu_vendor + 8], ecx
- mov eax, 1
- cpuid
- mov dword [cpu_features], edx
- mov dword [cpu_features + 4], ecx
- pop ebx
-.no_cpuid: leave
- ret
-
-;********************************************************************************
-; void fpu_save(byte_t *buffer)
-;********************************************************************************
-fpu_save: push ebp
- mov ebp, esp
- sub esp, 512 + 16
- push esi
- push edi
- lea esi, [ebp - 512]
- and esi, 0xFFFFFFF0
- mov edi, [ebp + 8]
- test dword [cpu_features], CPU_FEATURE_FXSR
- jz .no_fxr
- fxsave [esi]
- mov ecx, 128
- jmp .copy
-.no_fxr: fsave [esi]
- mov ecx, 27
-.copy: cld
- rep movsd
- pop edi
- pop esi
- xor eax, eax
- leave
- ret
-
-;********************************************************************************
-; void fpu_restore(byte_t *buffer)
-;********************************************************************************
-fpu_restore: push ebp
- mov ebp, esp
- sub esp, 512 + 16
- push esi
- push edi
- mov esi, [ebp + 8]
- lea edi, [ebp - 512]
- and edi, 0xFFFFFFF0
- mov eax, edi
- cld
- test dword [cpu_features], CPU_FEATURE_FXSR
- jz .no_fxr
- mov ecx, 128
- rep movsd
- fxrstor [eax]
- jmp .done
-.no_fxr: mov ecx, 27
- rep movsd
- frstor [eax]
-.done: pop edi
- pop esi
- xor eax, eax
- leave
- ret
--- /dev/null
+/*
+ * cpu.c
+ *
+ * Copyright (C) 2018 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <cpu.h>
+#include <cpuid.h>
+
+#define CPUID_GET_FEATURE_FLAGS 0x00000001
+#define CPUID_GET_MISC_INFORMATION 0x80000008
+
+#define CPUID_FEATURE_FLAG_ECX_SSE3 (1 << 0)
+#define CPUID_FEATURE_FLAG_ECX_PCLMUL (1 << 1)
+#define CPUID_FEATURE_FLAG_ECX_DTES64 (1 << 2)
+#define CPUID_FEATURE_FLAG_ECX_MON (1 << 3)
+#define CPUID_FEATURE_FLAG_ECX_DSCPL (1 << 4)
+#define CPUID_FEATURE_FLAG_ECX_VMX (1 << 5)
+#define CPUID_FEATURE_FLAG_ECX_SMX (1 << 6)
+#define CPUID_FEATURE_FLAG_ECX_EST (1 << 7)
+#define CPUID_FEATURE_FLAG_ECX_TM2 (1 << 8)
+#define CPUID_FEATURE_FLAG_ECX_SSSE3 (1 << 9)
+#define CPUID_FEATURE_FLAG_ECX_CID (1 << 10)
+#define CPUID_FEATURE_FLAG_ECX_SDBG (1 << 11)
+#define CPUID_FEATURE_FLAG_ECX_FMA (1 << 12)
+#define CPUID_FEATURE_FLAG_ECX_CX16 (1 << 13)
+#define CPUID_FEATURE_FLAG_ECX_ETPRD (1 << 14)
+#define CPUID_FEATURE_FLAG_ECX_PDCM (1 << 15)
+#define CPUID_FEATURE_FLAG_ECX_PCID (1 << 17)
+#define CPUID_FEATURE_FLAG_ECX_DCA (1 << 18)
+#define CPUID_FEATURE_FLAG_ECX_SSE41 (1 << 19)
+#define CPUID_FEATURE_FLAG_ECX_SSE42 (1 << 20)
+#define CPUID_FEATURE_FLAG_ECX_X2APIC (1 << 21)
+#define CPUID_FEATURE_FLAG_ECX_MOVBE (1 << 22)
+#define CPUID_FEATURE_FLAG_ECX_POPCNT (1 << 23)
+#define CPUID_FEATURE_FLAG_ECX_TSCD (1 << 24)
+#define CPUID_FEATURE_FLAG_ECX_AES (1 << 25)
+#define CPUID_FEATURE_FLAG_ECX_XSAVE (1 << 26)
+#define CPUID_FEATURE_FLAG_ECX_OSXSAVE (1 << 27)
+#define CPUID_FEATURE_FLAG_ECX_AVX (1 << 28)
+#define CPUID_FEATURE_FLAG_ECX_F16C (1 << 29)
+#define CPUID_FEATURE_FLAG_ECX_RDRAND (1 << 30)
+#define CPUID_FEATURE_FLAG_ECX_HV (1 << 31)
+
+#define CPUID_FEATURE_FLAG_EDX_FPU (1 << 0)
+#define CPUID_FEATURE_FLAG_EDX_VME (1 << 1)
+#define CPUID_FEATURE_FLAG_EDX_DE (1 << 2)
+#define CPUID_FEATURE_FLAG_EDX_PSE (1 << 3)
+#define CPUID_FEATURE_FLAG_EDX_TSC (1 << 4)
+#define CPUID_FEATURE_FLAG_EDX_MSR (1 << 5)
+#define CPUID_FEATURE_FLAG_EDX_PAE (1 << 6)
+#define CPUID_FEATURE_FLAG_EDX_MCE (1 << 7)
+#define CPUID_FEATURE_FLAG_EDX_CX8 (1 << 8)
+#define CPUID_FEATURE_FLAG_EDX_APIC (1 << 9)
+#define CPUID_FEATURE_FLAG_EDX_SEP (1 << 11)
+#define CPUID_FEATURE_FLAG_EDX_MTRR (1 << 12)
+#define CPUID_FEATURE_FLAG_EDX_PGE (1 << 13)
+#define CPUID_FEATURE_FLAG_EDX_MCA (1 << 14)
+#define CPUID_FEATURE_FLAG_EDX_CMOV (1 << 15)
+#define CPUID_FEATURE_FLAG_EDX_PAT (1 << 16)
+#define CPUID_FEATURE_FLAG_EDX_PSE36 (1 << 17)
+#define CPUID_FEATURE_FLAG_EDX_PSN (1 << 18)
+#define CPUID_FEATURE_FLAG_EDX_CLFL (1 << 19)
+#define CPUID_FEATURE_FLAG_EDX_DTES (1 << 21)
+#define CPUID_FEATURE_FLAG_EDX_ACPI (1 << 22)
+#define CPUID_FEATURE_FLAG_EDX_MMX (1 << 23)
+#define CPUID_FEATURE_FLAG_EDX_FXSR (1 << 24)
+#define CPUID_FEATURE_FLAG_EDX_SSE (1 << 25)
+#define CPUID_FEATURE_FLAG_EDX_SSE2 (1 << 26)
+#define CPUID_FEATURE_FLAG_EDX_SS (1 << 27)
+#define CPUID_FEATURE_FLAG_EDX_HTT (1 << 28)
+#define CPUID_FEATURE_FLAG_EDX_TM1 (1 << 29)
+#define CPUID_FEATURE_FLAG_EDX_IA64 (1 << 30)
+#define CPUID_FEATURE_FLAG_EDX_PBE (1 << 31)
+
+int cpu_fpu_present = FPU_NOT_PRESENT;
+byte_t cpu_max_physical_bits = 32;
+
+static void fpu_init(void)
+{
+ cpu_write_master_control_register(cpu_read_master_control_register() & ~(CPU_CONTROL_FLAG_EM | CPU_CONTROL_FLAG_TS));
+ __asm__ volatile ("fninit");
+}
+
+static void fpu_probe(void)
+{
+ word_t fpu_status = 0xCCCC;
+ __asm__ volatile ("fnstsw %0"
+ : "=m" (fpu_status) /* output */
+ : /* input */
+ : /* clobber */);
+
+ if (fpu_status == 0)
+ {
+ cpu_fpu_present = FPU_LEGACY;
+ }
+ else
+ {
+ cpu_fpu_present = FPU_NOT_PRESENT;
+ cpu_write_master_control_register(cpu_read_master_control_register() | CPU_CONTROL_FLAG_EM);
+ }
+}
+
+void cpu_init(void)
+{
+ unsigned int features[5], address_size_info, cpu_count_info, dummy;
+
+ if (!__get_cpuid(CPUID_GET_FEATURE_FLAGS, &features[0], &features[1], &features[2], &features[3]))
+ {
+ fpu_init();
+ fpu_probe();
+ return;
+ }
+
+ if (features[3] & CPUID_FEATURE_FLAG_EDX_FPU)
+ {
+ fpu_init();
+
+ if (features[3] & CPUID_FEATURE_FLAG_EDX_FXSR)
+ {
+ cpu_write_feature_register(cpu_read_feature_register() | CPU_FEATURE_FLAG_OSXFSR);
+ cpu_fpu_present = FPU_XFSR;
+ }
+ else
+ {
+ cpu_fpu_present = FPU_LEGACY;
+ }
+ }
+
+ if (features[3] & CPUID_FEATURE_FLAG_EDX_PGE)
+ {
+ cpu_write_feature_register(cpu_read_feature_register() | CPU_FEATURE_FLAG_PGE);
+ }
+
+ if (features[3] & CPUID_FEATURE_FLAG_EDX_PSE)
+ {
+ cpu_write_feature_register(cpu_read_feature_register() | CPU_FEATURE_FLAG_PSE);
+ }
+
+ if ((features[3] & CPUID_FEATURE_FLAG_EDX_PAE) || (features[3] & CPUID_FEATURE_FLAG_EDX_PSE36))
+ {
+ /* Don't enable PAE here, it might be disabled on the user's request */
+ cpu_max_physical_bits = 36;
+ }
+
+ if (__get_cpuid(CPUID_GET_MISC_INFORMATION, &address_size_info, &features[4], &cpu_count_info, &dummy))
+ {
+ byte_t physical_bits = address_size_info & 0xFF;
+ if (physical_bits > 36) cpu_max_physical_bits = physical_bits;
+ }
+}
{
int i;
word_t *video_mem = (word_t*)(video_initialized ? VIDEO_MEMORY : TEXT_VIDEO_MEMORY);
- disable_ints();
+ cpu_disable_interrupts();
uintptr_t call_stack[MAX_BACKTRACE];
int call_count = 0;
log_write(LOG_CRITICAL, ")\n");
- dword_t cr0, cr2, cr3;
- asm volatile ("movl %%cr0, %0" : "=r"(cr0) ::);
- asm volatile ("movl %%cr2, %0" : "=r"(cr2) ::);
- asm volatile ("movl %%cr3, %0" : "=r"(cr3) ::);
-
- log_write(LOG_CRITICAL, "CR0: 0x%08X\n", cr0);
- log_write(LOG_CRITICAL, "CR2: 0x%08X\n", cr2);
- log_write(LOG_CRITICAL, "CR3: 0x%08X\n", cr3);
+ log_write(LOG_CRITICAL, "CR0: 0x%08X\n", cpu_read_master_control_register());
+ log_write(LOG_CRITICAL, "CR2: 0x%08X\n", cpu_read_faulting_address());
+ log_write(LOG_CRITICAL, "CR3: 0x%08X\n", cpu_read_page_table_register());
+ log_write(LOG_CRITICAL, "CR4: 0x%08X\n", cpu_read_feature_register());
}
else
{
log_write(LOG_CRITICAL, "\n");
}
- halt();
+ cpu_halt();
for(;;);
}
}
else
{
- if (current) enable_ints();
+ if (current) cpu_enable_interrupts();
terminate_thread_internal(thread, 1);
ASSERT(!current);
}
break;
case CPU_EXCEPTION_NM:
- if (cpu_features[0] & CPU_FEATURE_FPU)
+ if (cpu_fpu_present)
{
thread_lazy_fpu();
return;
return;
case CPU_EXCEPTION_GP:
- if (regs->eflags & EFLAGS_VM)
+ if (regs->eflags & CPU_STATUS_FLAG_VM)
{
vm86_handler((registers_ext_vm86_t*)regs);
return;
break;
case CPU_EXCEPTION_PF:
- asm volatile ("movl %%cr2, %0" : "=r"(faulting_address) ::);
+ faulting_address = (void*)cpu_read_faulting_address();
if (memory_fault_handler(faulting_address, regs)) return;
info.number = EXCEPTION_MEMORY_ACCESS;
#include <segments.h>
#include <lock.h>
#include <thread.h>
+#include <cpu.h>
static byte_t isr_stubs[IDT_NUM_INTERRUPTS * ISR_STUB_SIZE];
static idt_entry_t idt[IDT_NUM_INTERRUPTS];
static interrupt_handler_t handlers[IDT_NUM_INTERRUPTS];
-static inline void lidt(dword_t base, dword_t size)
-{
- volatile dword_t idtr[2];
- idtr[0] = size << 16;
- idtr[1] = base;
- asm volatile ("lidt (%0)" :: "r"((byte_t*)idtr + 2));
-}
-
static void idt_main_handler(byte_t interrupt_num, registers_t regs)
{
regs.esp += 16;
thread->in_kernel++;
}
- if (handlers[interrupt_num].interrupts) enable_ints();
+ if (handlers[interrupt_num].interrupts) cpu_enable_interrupts();
handlers[interrupt_num].procedure(®s, interrupt_num);
if (thread)
if (thread->terminated || (thread->frozen > 0))
{
- enable_ints();
+ cpu_enable_interrupts();
syscall_yield_quantum();
}
}
}
- disable_ints();
+ cpu_disable_interrupts();
}
dword_t set_int_handler(byte_t interrupt_num, isr_proc_t proc, bool_t interrupts, bool_t usermode)
isr_stubs[offset++] = 0xCF; // iret
}
- lidt((dword_t)&idt, sizeof(idt));
+ cpu_set_interrupt_table(idt, sizeof(idt));
}
#include <irq.h>
#include <heap.h>
#include <lock.h>
+#include <cpu.h>
static list_entry_t irq_handlers[MAX_IRQ_COUNT];
static dword_t irq_alloc_bitmap = 0xFFFFF3FF;
if (irq_num == 7)
{
- outportb(PRIMARY_PIC_CMD, 0x0B);
+ cpu_write_port_byte(PRIMARY_PIC_CMD, 0x0B);
- byte_t isr = inportb(PRIMARY_PIC_CMD);
+ byte_t isr = cpu_read_port_byte(PRIMARY_PIC_CMD);
if (!(isr & 0x80)) return;
}
if (irq_num == 15)
{
- outportb(SECONDARY_PIC_CMD, 0x0B);
+ cpu_write_port_byte(SECONDARY_PIC_CMD, 0x0B);
- byte_t isr = inportb(SECONDARY_PIC_CMD);
+ byte_t isr = cpu_read_port_byte(SECONDARY_PIC_CMD);
if (!(isr & 0x80))
{
- outportb(PRIMARY_PIC_CMD, 0x20);
+ cpu_write_port_byte(PRIMARY_PIC_CMD, 0x20);
return;
}
}
{
handler = CONTAINER_OF(ptr, irq_handler_t, list);
- enable_ints();
+ cpu_enable_interrupts();
handler->procedure(regs, irq_num);
- disable_ints();
+ cpu_disable_interrupts();
}
- if (irq_num >= 8) outportb(SECONDARY_PIC_CMD, 0x20);
- outportb(PRIMARY_PIC_CMD, 0x20);
+ if (irq_num >= 8) cpu_write_port_byte(SECONDARY_PIC_CMD, 0x20);
+ cpu_write_port_byte(PRIMARY_PIC_CMD, 0x20);
}
dword_t register_irq_handler(byte_t irq_num, irq_handler_proc_t handler_proc, bool_t exclusive)
if (irq_num >= 0 && irq_num < 8)
{
primary_pic_mask &= ~(1 << irq_num);
- outportb(PRIMARY_PIC_DATA, primary_pic_mask);
+ cpu_write_port_byte(PRIMARY_PIC_DATA, primary_pic_mask);
}
else
{
secondary_pic_mask &= ~(1 << (irq_num - 8));
- outportb(SECONDARY_PIC_DATA, secondary_pic_mask);
+ cpu_write_port_byte(SECONDARY_PIC_DATA, secondary_pic_mask);
}
}
else if (exclusive || CONTAINER_OF(irq_handlers[irq_num].next, irq_handler_t, list)->exclusive)
byte_t i;
primary_pic_mask &= ~(1 << PRIMARY_PIC_CASCADE_IRQ);
- outportb(PRIMARY_PIC_CMD, 0x11);
- outportb(SECONDARY_PIC_CMD, 0x11);
- outportb(PRIMARY_PIC_DATA, PRIMARY_IRQ_INT);
- outportb(SECONDARY_PIC_DATA, SECONDARY_IRQ_INT);
- outportb(PRIMARY_PIC_DATA, 1 << PRIMARY_PIC_CASCADE_IRQ);
- outportb(SECONDARY_PIC_DATA, 1 << SECONDARY_PIC_CASCADE_IRQ);
- outportb(PRIMARY_PIC_DATA, PIC_8086_MODE);
- outportb(SECONDARY_PIC_DATA, PIC_8086_MODE);
- outportb(PRIMARY_PIC_DATA, primary_pic_mask);
- outportb(SECONDARY_PIC_DATA, secondary_pic_mask);
+ cpu_write_port_byte(PRIMARY_PIC_CMD, 0x11);
+ cpu_write_port_byte(SECONDARY_PIC_CMD, 0x11);
+ cpu_write_port_byte(PRIMARY_PIC_DATA, PRIMARY_IRQ_INT);
+ cpu_write_port_byte(SECONDARY_PIC_DATA, SECONDARY_IRQ_INT);
+ cpu_write_port_byte(PRIMARY_PIC_DATA, 1 << PRIMARY_PIC_CASCADE_IRQ);
+ cpu_write_port_byte(SECONDARY_PIC_DATA, 1 << SECONDARY_PIC_CASCADE_IRQ);
+ cpu_write_port_byte(PRIMARY_PIC_DATA, PIC_8086_MODE);
+ cpu_write_port_byte(SECONDARY_PIC_DATA, PIC_8086_MODE);
+ cpu_write_port_byte(PRIMARY_PIC_DATA, primary_pic_mask);
+ cpu_write_port_byte(SECONDARY_PIC_DATA, secondary_pic_mask);
for (i = 0; i < MAX_IRQ_COUNT; i++)
{
else count--;
lock_acquire(&dma_lock);
- outportb(ISA_DMA_SINGLE_MASK_REG(channel), ISA_DMA_MASK_ON | (channel & 3));
+ cpu_write_port_byte(ISA_DMA_SINGLE_MASK_REG(channel), ISA_DMA_MASK_ON | (channel & 3));
- outportb(ISA_DMA_FF_RESET_REG(channel), 0xFF);
- outportb(ISA_DMA_SAR(channel), (dword_t)buffer & 0xFF);
- outportb(ISA_DMA_SAR(channel), ((dword_t)buffer >> 8) & 0xFF);
- outportb(ISA_DMA_PAR(channel), ((dword_t)buffer >> 16) & 0xFF);
+ cpu_write_port_byte(ISA_DMA_FF_RESET_REG(channel), 0xFF);
+ cpu_write_port_byte(ISA_DMA_SAR(channel), (dword_t)buffer & 0xFF);
+ cpu_write_port_byte(ISA_DMA_SAR(channel), ((dword_t)buffer >> 8) & 0xFF);
+ cpu_write_port_byte(ISA_DMA_PAR(channel), ((dword_t)buffer >> 16) & 0xFF);
- outportb(ISA_DMA_FF_RESET_REG(channel), 0xFF);
- outportb(ISA_DMA_CNT(channel), count & 0xFF);
- outportb(ISA_DMA_CNT(channel), count >> 8);
+ cpu_write_port_byte(ISA_DMA_FF_RESET_REG(channel), 0xFF);
+ cpu_write_port_byte(ISA_DMA_CNT(channel), count & 0xFF);
+ cpu_write_port_byte(ISA_DMA_CNT(channel), count >> 8);
- outportb(ISA_DMA_MODE_REG(channel), 0x48 | (channel & 3));
+ cpu_write_port_byte(ISA_DMA_MODE_REG(channel), 0x48 | (channel & 3));
- outportb(ISA_DMA_SINGLE_MASK_REG(channel), (channel & 3));
+ cpu_write_port_byte(ISA_DMA_SINGLE_MASK_REG(channel), (channel & 3));
lock_release(&dma_lock);
}
else count--;
lock_acquire(&dma_lock);
- outportb(ISA_DMA_SINGLE_MASK_REG(channel), ISA_DMA_MASK_ON | (channel & 3));
+ cpu_write_port_byte(ISA_DMA_SINGLE_MASK_REG(channel), ISA_DMA_MASK_ON | (channel & 3));
- outportb(ISA_DMA_FF_RESET_REG(channel), 0xFF);
- outportb(ISA_DMA_SAR(channel), (dword_t)buffer & 0xFF);
- outportb(ISA_DMA_SAR(channel), ((dword_t)buffer >> 8) & 0xFF);
- outportb(ISA_DMA_PAR(channel), ((dword_t)buffer >> 16) & 0xFF);
+ cpu_write_port_byte(ISA_DMA_FF_RESET_REG(channel), 0xFF);
+ cpu_write_port_byte(ISA_DMA_SAR(channel), (dword_t)buffer & 0xFF);
+ cpu_write_port_byte(ISA_DMA_SAR(channel), ((dword_t)buffer >> 8) & 0xFF);
+ cpu_write_port_byte(ISA_DMA_PAR(channel), ((dword_t)buffer >> 16) & 0xFF);
- outportb(ISA_DMA_FF_RESET_REG(channel), 0xFF);
- outportb(ISA_DMA_CNT(channel), count & 0xFF);
- outportb(ISA_DMA_CNT(channel), count >> 8);
+ cpu_write_port_byte(ISA_DMA_FF_RESET_REG(channel), 0xFF);
+ cpu_write_port_byte(ISA_DMA_CNT(channel), count & 0xFF);
+ cpu_write_port_byte(ISA_DMA_CNT(channel), count >> 8);
- outportb(ISA_DMA_MODE_REG(channel), 0x44 | (channel & 3));
+ cpu_write_port_byte(ISA_DMA_MODE_REG(channel), 0x44 | (channel & 3));
- outportb(ISA_DMA_SINGLE_MASK_REG(channel), (channel & 3));
+ cpu_write_port_byte(ISA_DMA_SINGLE_MASK_REG(channel), (channel & 3));
lock_release(&dma_lock);
}
#include <thread.h>
#include <lock.h>
+#include <cpu.h>
#define NO_HOLDER ((uintptr_t)0)
#define MULTIPLE_HOLDERS ((uintptr_t)-1)
void enter_critical(critical_t *critical)
{
*critical = 0;
- if (disable_ints()) *critical |= (1 << 0);
+ if (cpu_disable_interrupts()) *critical |= (1 << 0);
if (scheduler_enabled) *critical |= (1 << 1);
-
- disable_ints();
scheduler_enabled = FALSE;
}
void leave_critical(critical_t *critical)
{
if (*critical & (1 << 1)) scheduler_enabled = TRUE;
- if (*critical & (1 << 0)) enable_ints();
+ if (*critical & (1 << 0)) cpu_enable_interrupts();
}
void lock_acquire(lock_t *lock)
static void *evict_page(void);
-static inline void invalidate_tlb(dword_t *addr)
-{
- asm volatile ("invlpg %0" :: "m"(*addr));
-}
-
static inline void *alloc_physical_page(void)
{
void *page = INVALID_PAGE;
reference_page(table_page);
page_directory[pd_index] = (dword_t)table_page | PAGE_PRESENT | PAGE_WRITABLE;
- invalidate_tlb(page_table);
+ cpu_invalidate_tlb(page_table);
for (i = 0; i < PAGE_SIZE / sizeof(dword_t); i++) page_table[i] = 0;
}
reference_page((void*)phys_addr);
page_table[pt_index] = phys_addr | flags | PAGE_PRESENT;
- invalidate_tlb(virtual);
+ cpu_invalidate_tlb(virtual);
done:
leave_critical(&critical);
dereference_page((void*)PAGE_ALIGN(page_table[pt_index]));
page_table[pt_index] = 0;
- invalidate_tlb((dword_t*)virt_addr);
+ cpu_invalidate_tlb((dword_t*)virt_addr);
for (i = 0; i < PAGE_SIZE / sizeof(dword_t); i++) if (page_table[i])
{
{
void *table_page = (void*)PAGE_ALIGN(page_directory[pd_index]);
page_directory[pd_index] = 0;
- invalidate_tlb(page_table);
+ cpu_invalidate_tlb(page_table);
if (dereference_page(table_page) == 0)
{
page_directory[pd_index] |= flags;
page_table[pt_index] = PAGE_ALIGN(page_table[pt_index]) | flags | PAGE_PRESENT;
- invalidate_tlb((void*)virt_addr);
+ cpu_invalidate_tlb((void*)virt_addr);
done:
leave_critical(&critical);
}
table[pt_index] = 0;
- if (space->page_directory == get_page_directory()) invalidate_tlb((void*)address);
+ if (space->page_directory == get_page_directory()) cpu_invalidate_tlb((void*)address);
cleanup:
if (table) unmap_temporary_page(table);
void set_page_directory(void *phys_addr)
{
current_page_directory = phys_addr;
-
- asm volatile ("mov %0, %%eax\n\
- mov %%eax, %%cr3" :: "r"(phys_addr));
+ cpu_write_page_table_register((uintptr_t)phys_addr);
}
void *get_physical_address(void *virtual)
reference_page((void*)PAGE_ALIGN(original_dir[i]));
original_dir[i] &= ~PAGE_WRITABLE;
clone_dir[i] = original_dir[i];
- if (this_directory) invalidate_tlb((void*)(i << 12));
+ if (this_directory) cpu_invalidate_tlb((void*)(i << 12));
}
if (!this_directory) unmap_temporary_page(original_dir);
if (entry->number != INVALID_STORE_NUMBER)
{
- enable_ints();
+ cpu_enable_interrupts();
dword_t ret = syscall_read_file(store->file_handle, buffer, (qword_t)entry->number * (qword_t)PAGE_SIZE, PAGE_SIZE, &bytes_read);
- disable_ints();
+ cpu_disable_interrupts();
if ((page_directory[pd_index] & PAGE_PRESENT) && (page_table[pt_index] & PAGE_PRESENT))
{
if (block->section && block->section->file && offset < (qword_t)block->section->size)
{
- enable_ints();
+ cpu_enable_interrupts();
file_instance_t *file = block->section->file;
lock_acquire_shared(&file->global->volume->lock);
dword_t ret = file->global->volume->driver->read_file(file, buffer, offset, PAGE_SIZE, &bytes_read);
lock_release(&file->global->volume->lock);
- disable_ints();
+ cpu_disable_interrupts();
if (ret != ERR_SUCCESS && ret != ERR_BEYOND) return FALSE;
}
page_directory[pd_index] = PAGE_ALIGN((dword_t)table_copy)
| PAGE_OFFSET(page_directory[pd_index])
| PAGE_WRITABLE;
- invalidate_tlb(page_table);
+ cpu_invalidate_tlb(page_table);
}
else
{
page_directory[pd_index] |= PAGE_WRITABLE;
- invalidate_tlb(page_table);
+ cpu_invalidate_tlb(page_table);
for (i = 0; i < PAGE_SIZE / sizeof(dword_t); i++)
{
page_table[i] &= ~PAGE_WRITABLE;
- invalidate_tlb((void*)((pd_index << 22) | (i << 12)));
+ cpu_invalidate_tlb((void*)((pd_index << 22) | (i << 12)));
}
}
}
page_table[pt_index] = PAGE_ALIGN((dword_t)page_copy)
| PAGE_OFFSET(page_table[pt_index])
| PAGE_WRITABLE;
- invalidate_tlb((void*)aligned_address);
+ cpu_invalidate_tlb((void*)aligned_address);
}
else
{
page_table[pt_index] |= PAGE_WRITABLE;
- invalidate_tlb((void*)aligned_address);
+ cpu_invalidate_tlb((void*)aligned_address);
}
}
{
page_directory[pd_index] = start_addr | PAGE_PRESENT | PAGE_WRITABLE | PAGE_GLOBAL;
start_addr += PAGE_SIZE;
- invalidate_tlb(page_table);
+ cpu_invalidate_tlb(page_table);
memset(page_table, 0, PAGE_SIZE);
total_physical_pages++;
continue;
{
page_table[pt_index] = start_addr | PAGE_PRESENT | PAGE_WRITABLE | PAGE_GLOBAL;
start_addr += PAGE_SIZE;
- invalidate_tlb((void*)stack_address);
+ cpu_invalidate_tlb((void*)stack_address);
total_physical_pages++;
continue;
}
if (!(page_directory[pd_index] & PAGE_PRESENT))
{
page_directory[pd_index] = (uintptr_t)alloc_physical_page() | PAGE_PRESENT | PAGE_WRITABLE | PAGE_GLOBAL;
- invalidate_tlb(page_table);
+ cpu_invalidate_tlb(page_table);
memset(page_table, 0, PAGE_SIZE);
}
if (!(page_table[pt_index] & PAGE_PRESENT))
{
page_table[pt_index] = (uintptr_t)alloc_physical_page() | PAGE_PRESENT | PAGE_WRITABLE | PAGE_GLOBAL;
- invalidate_tlb((void*)i);
+ cpu_invalidate_tlb((void*)i);
}
}
for (i = USER_PAGE_START; i <= USER_PAGE_END; i++) page_directory[i] = 0;
set_page_directory(get_page_directory());
-
- if (cpu_features[0] & CPU_FEATURE_PGE)
- {
- asm volatile ("movl %cr4, %eax\n"
- "orl $0x80, %eax\n"
- "movl %eax, %cr4\n");
- }
}
dword_t pci_read(pci_device_t *device, dword_t reg)
{
- outportl(0x0CF8,
+ cpu_write_port_dword(0x0CF8,
0x80000000
| ((device->bus & 0xFF) << 16)
| ((device->slot & 0x1F) << 11)
| ((device->function & 0x07) << 8)
| ((reg & 0x3F) << 2));
- return inportl(0x0CFC);
+ return cpu_read_port_dword(0x0CFC);
}
void pci_write(pci_device_t *device, dword_t reg, dword_t data)
{
- outportl(0x0CF8,
+ cpu_write_port_dword(0x0CF8,
0x80000000
| ((device->bus & 0xFF) << 16)
| ((device->slot & 0x1F) << 11)
| ((device->function & 0x07) << 8)
| ((reg & 0x3F) << 2));
- outportl(0x0CFC, data);
+ cpu_write_port_dword(0x0CFC, data);
}
list_entry_t *get_pci_device_list_head(void)
#include <power.h>
#include <syscalls.h>
#include <user.h>
+#include <cpu.h>
static power_callbacks_t *power_callbacks = NULL;
if (power_callbacks) power_callbacks->set_state(POWER_STATE_OFF);
case POWER_COMMAND_HALT:
- disable_ints();
- halt();
+ cpu_disable_interrupts();
+ cpu_halt();
break;
case POWER_COMMAND_REBOOT:
- disable_ints();
- while (inportb(0x64) & 0x02) continue;
- outportb(0x64, 0xFE);
- halt();
+ cpu_disable_interrupts();
+ while (cpu_read_port_byte(0x64) & 0x02) continue;
+ cpu_write_port_byte(0x64, 0xFE);
+ cpu_halt();
break;
default:
else
{
initial_state.regs = *get_current_thread()->last_context;
- fpu_save(initial_state.fpu_state);
+ cpu_save_fpu_state(initial_state.fpu_state);
initial_state.regs.eax = CLONE_MAGIC;
}
while (TRUE)
{
syscall_yield_quantum();
- halt();
+ cpu_halt();
}
}
irq_init();
exceptions_init();
object_init();
- enable_ints();
+ cpu_enable_interrupts();
}
static void scan_multiboot_info(multiboot_tag_t *mboot)
void thread_lazy_fpu(void)
{
- if (last_fpu_thread) fpu_save(last_fpu_thread->state.fpu_state);
- fpu_restore(current_thread->state.fpu_state);
+ if (last_fpu_thread) cpu_save_fpu_state(last_fpu_thread->state.fpu_state);
+ cpu_restore_fpu_state(current_thread->state.fpu_state);
last_fpu_thread = current_thread;
asm volatile ("clts");
}
else
{
((thread_state_t*)safe_buffer)->regs = *thread->last_context;
- fpu_save(((thread_state_t*)safe_buffer)->fpu_state);
+ cpu_save_fpu_state(((thread_state_t*)safe_buffer)->fpu_state);
}
}
else
}
else
{
- fpu_restore(new_state->fpu_state);
+ cpu_restore_fpu_state(new_state->fpu_state);
}
if (current_thread->tid != thread->tid) leave_critical(&critical);
qword_t result = total_ticks * 1000000ULL;
- outportb(TIMER_CMD_PORT, 0x00);
- word_t count = inportb(TIMER_CHANNEL_PORT(0));
- count |= inportb(TIMER_CHANNEL_PORT(0)) << 8;
+ cpu_write_port_byte(TIMER_CMD_PORT, 0x00);
+ word_t count = cpu_read_port_byte(TIMER_CHANNEL_PORT(0));
+ count |= cpu_read_port_byte(TIMER_CHANNEL_PORT(0)) << 8;
count = -count;
result += (count * 1000ULL) / (qword_t)TIMER_BASE_FREQUENCY;
if (value == 0) value = 1;
if (value >= 65536) value = 0;
- outportb(TIMER_CMD_PORT, TIMER_RATE_GENERATOR(0));
- outportb(TIMER_CHANNEL_PORT(0), value & 0xFF);
- outportb(TIMER_CHANNEL_PORT(0), (value >> 8) & 0xFF);
+ cpu_write_port_byte(TIMER_CMD_PORT, TIMER_RATE_GENERATOR(0));
+ cpu_write_port_byte(TIMER_CHANNEL_PORT(0), value & 0xFF);
+ cpu_write_port_byte(TIMER_CHANNEL_PORT(0), (value >> 8) & 0xFF);
register_irq_handler(TIMER_IRQ, &timer_irq, FALSE);
}
video_cursor_location_t *location = (video_cursor_location_t*)in_buffer;
word_t index = location->row * TEXT_WIDTH + location->column;
- outportb(VGA_CRTC_INDEX, 0x0F);
- outportb(VGA_CRTC_DATA, (byte_t) (index & 0xFF));
- outportb(VGA_CRTC_INDEX, 0x0E);
- outportb(VGA_CRTC_DATA, (byte_t) ((index >> 8) & 0xFF));
+ cpu_write_port_byte(VGA_CRTC_INDEX, 0x0F);
+ cpu_write_port_byte(VGA_CRTC_DATA, (byte_t) (index & 0xFF));
+ cpu_write_port_byte(VGA_CRTC_INDEX, 0x0E);
+ cpu_write_port_byte(VGA_CRTC_DATA, (byte_t) ((index >> 8) & 0xFF));
}
else
{
#include <thread.h>
#include <memory.h>
+#define PREFIX_LOCK (1 << 0)
+#define PREFIX_OPSIZE (1 << 1)
+#define PREFIX_ADDRSIZE (1 << 2)
+#define PREFIX_REP (1 << 3)
+#define PREFIX_REPNZ (1 << 4)
+#define PREFIX_ES (1 << 5)
+#define PREFIX_SS (1 << 6)
+#define PREFIX_FS (1 << 7)
+#define PREFIX_GS (1 << 8)
+
+#define VM86_MEM_START 0x10000
+#define VM86_MEM_END 0x90000
+#define VM86_MEM_PARAGRAPHS ((VM86_MEM_END - VM86_MEM_START) >> 4)
+
+#define VM86_TRAMPOLINE_CS 0x0000
+#define VM86_TRAMPOLINE_IP 0xE000
+#define VM86_TRAMPOLINE_SS 0x0000
+#define VM86_TRAMPOLINE_SP 0xDFFA
+
extern void vm86_start(vm86_registers_t input_regs, vm86_registers_t *output_regs);
static bool_t vm86_interrupts = TRUE;
{
for (i = 0; i < count; i++)
{
- pokeb(regs->es, regs->edi, inportb(regs->edx));
- if (!(regs->eflags & EFLAGS_DF)) regs->edi++;
+ pokeb(regs->es, regs->edi, cpu_read_port_byte(regs->edx));
+ if (!(regs->eflags & CPU_STATUS_FLAG_DF)) regs->edi++;
else regs->edi--;
}
{
if (!(prefix & PREFIX_OPSIZE))
{
- pokew(regs->es, regs->edi, inportw(regs->edx));
+ pokew(regs->es, regs->edi, cpu_read_port_word(regs->edx));
- if (!(regs->eflags & EFLAGS_DF)) regs->edi += 2;
+ if (!(regs->eflags & CPU_STATUS_FLAG_DF)) regs->edi += 2;
else regs->edi -= 2;
}
else
{
- pokel(regs->es, regs->edi, inportl(regs->edx));
+ pokel(regs->es, regs->edi, cpu_read_port_dword(regs->edx));
- if (!(regs->eflags & EFLAGS_DF)) regs->edi += 4;
+ if (!(regs->eflags & CPU_STATUS_FLAG_DF)) regs->edi += 4;
else regs->edi -= 4;
}
}
{
for (i = 0; i < count; i++)
{
- outportb(regs->edx, peekb(segment, regs->esi));
+ cpu_write_port_byte(regs->edx, peekb(segment, regs->esi));
- if (!(regs->eflags & EFLAGS_DF)) regs->esi++;
+ if (!(regs->eflags & CPU_STATUS_FLAG_DF)) regs->esi++;
else regs->esi--;
}
{
if (!(prefix & PREFIX_OPSIZE))
{
- outportw(regs->edx, peekw(segment, regs->esi));
+ cpu_write_port_word(regs->edx, peekw(segment, regs->esi));
- if (!(regs->eflags & EFLAGS_DF)) regs->esi += 2;
+ if (!(regs->eflags & CPU_STATUS_FLAG_DF)) regs->esi += 2;
else regs->esi -= 2;
}
else
{
- outportl(regs->edx, peekl(segment, regs->esi));
+ cpu_write_port_dword(regs->edx, peekl(segment, regs->esi));
- if (!(regs->eflags & EFLAGS_DF)) regs->esi += 4;
+ if (!(regs->eflags & CPU_STATUS_FLAG_DF)) regs->esi += 4;
else regs->esi -= 4;
}
}
case 0x9C: // pushf
{
operand = regs->eflags;
- operand &= ~EFLAGS_VM;
+ operand &= ~CPU_STATUS_FLAG_VM;
- if (vm86_interrupts) operand |= EFLAGS_IF;
- else operand &= ~EFLAGS_IF;
+ if (vm86_interrupts) operand |= CPU_STATUS_FLAG_IF;
+ else operand &= ~CPU_STATUS_FLAG_IF;
if (!(prefix & PREFIX_OPSIZE))
{
if (!(prefix & PREFIX_OPSIZE))
{
regs->eflags &= 0xFFFF0000;
- regs->eflags |= peekw(regs->ss, regs->esp3) | EFLAGS_VM;
+ regs->eflags |= peekw(regs->ss, regs->esp3) | CPU_STATUS_FLAG_VM;
regs->esp3 += 2;
}
else
{
- regs->eflags = peekl(regs->ss, regs->esp3) | EFLAGS_VM;
+ regs->eflags = peekl(regs->ss, regs->esp3) | CPU_STATUS_FLAG_VM;
regs->esp3 += 4;
}
- vm86_interrupts = (regs->eflags & EFLAGS_IF) ? TRUE : FALSE;
- regs->eflags |= EFLAGS_IF;
+ vm86_interrupts = (regs->eflags & CPU_STATUS_FLAG_IF) ? TRUE : FALSE;
+ regs->eflags |= CPU_STATUS_FLAG_IF;
break;
}
regs->eip++;
regs->esp3 -= 2;
- pokew(regs->ss, regs->esp3, (regs->eflags & (~EFLAGS_VM)) | (vm86_interrupts ? EFLAGS_IF : 0));
+ pokew(regs->ss, regs->esp3, (regs->eflags & (~CPU_STATUS_FLAG_VM)) | (vm86_interrupts ? CPU_STATUS_FLAG_IF : 0));
regs->esp3 -= 2;
pokew(regs->ss, regs->esp3, regs->cs);
regs->cs = peekw(regs->ss, regs->esp3);
regs->esp3 += 2;
- regs->eflags = peekw(regs->ss, regs->esp3) | EFLAGS_VM;
+ regs->eflags = peekw(regs->ss, regs->esp3) | CPU_STATUS_FLAG_VM;
regs->esp3 += 2;
- vm86_interrupts = (regs->eflags & EFLAGS_IF) ? TRUE : FALSE;
- regs->eflags |= EFLAGS_IF;
+ vm86_interrupts = (regs->eflags & CPU_STATUS_FLAG_IF) ? TRUE : FALSE;
+ regs->eflags |= CPU_STATUS_FLAG_IF;
break;
}
operand = peekb(regs->cs, regs->eip);
regs->eip++;
regs->eax &= 0xFFFFFF00;
- regs->eax |= inportb(operand & 0xFF) & 0xFF;
+ regs->eax |= cpu_read_port_byte(operand & 0xFF) & 0xFF;
break;
}
if (!(prefix & PREFIX_OPSIZE))
{
regs->eax &= 0xFFFF0000;
- regs->eax |= inportw(operand & 0xFF) & 0xFFFF;
+ regs->eax |= cpu_read_port_word(operand & 0xFF) & 0xFFFF;
}
- else regs->eax = inportl(operand & 0xFF);
+ else regs->eax = cpu_read_port_dword(operand & 0xFF);
break;
}
{
operand = peekb(regs->cs, regs->eip);
regs->eip++;
- outportb(operand & 0xFF, regs->eax & 0xFF);
+ cpu_write_port_byte(operand & 0xFF, regs->eax & 0xFF);
break;
}
operand = peekb(regs->cs, regs->eip);
regs->eip++;
- if (!(prefix & PREFIX_OPSIZE)) outportw(operand & 0xFF, regs->eax & 0xFFFF);
- else outportl(operand & 0xFF, regs->eax);
+ if (!(prefix & PREFIX_OPSIZE)) cpu_write_port_word(operand & 0xFF, regs->eax & 0xFFFF);
+ else cpu_write_port_dword(operand & 0xFF, regs->eax);
break;
}
case 0xEC: // in al, dx
{
regs->eax &= 0xFFFFFF00;
- regs->eax |= inportb(regs->edx & 0xFFFF) & 0xFF;
+ regs->eax |= cpu_read_port_byte(regs->edx & 0xFFFF) & 0xFF;
break;
}
if (!(prefix & PREFIX_OPSIZE))
{
regs->eax &= 0xFFFF0000;
- regs->eax |= inportw(regs->edx & 0xFFFF) & 0xFFFF;
+ regs->eax |= cpu_read_port_word(regs->edx & 0xFFFF) & 0xFFFF;
}
- else regs->eax = inportl(regs->edx & 0xFFFF);
+ else regs->eax = cpu_read_port_dword(regs->edx & 0xFFFF);
break;
}
case 0xEE: // out dx, al
{
- outportb(regs->edx & 0xFFFF, regs->eax & 0xFF);
+ cpu_write_port_byte(regs->edx & 0xFFFF, regs->eax & 0xFF);
break;
}
case 0xEF: // out dx, (e)ax
{
- if (!(prefix & PREFIX_OPSIZE)) outportw(regs->edx & 0xFFFF, regs->eax & 0xFFFF);
- else outportl(regs->edx & 0xFFFF, regs->eax);
+ if (!(prefix & PREFIX_OPSIZE)) cpu_write_port_word(regs->edx & 0xFFFF, regs->eax & 0xFFFF);
+ else cpu_write_port_dword(regs->edx & 0xFFFF, regs->eax);
break;
}
#ifndef __MONOLITHIUM_CPU_H__
#define __MONOLITHIUM_CPU_H__
+#define CPU_MAX_FPU_DATA_SIZE 512
+
+#define CPU_STATUS_FLAG_CF (1 << 0)
+#define CPU_STATUS_FLAG_PF (1 << 2)
+#define CPU_STATUS_FLAG_AF (1 << 4)
+#define CPU_STATUS_FLAG_ZF (1 << 6)
+#define CPU_STATUS_FLAG_SF (1 << 7)
+#define CPU_STATUS_FLAG_TF (1 << 8)
+#define CPU_STATUS_FLAG_IF (1 << 9)
+#define CPU_STATUS_FLAG_DF (1 << 10)
+#define CPU_STATUS_FLAG_OF (1 << 11)
+#define CPU_STATUS_FLAG_NT (1 << 14)
+#define CPU_STATUS_FLAG_RF (1 << 16)
+#define CPU_STATUS_FLAG_VM (1 << 17)
+#define CPU_STATUS_FLAG_AC (1 << 18)
+#define CPU_STATUS_FLAG_VIF (1 << 19)
+#define CPU_STATUS_FLAG_VIP (1 << 20)
+#define CPU_STATUS_FLAG_ID (1 << 21)
+
typedef struct
{
dword_t data_selector;
#define THREAD_CREATE_FROZEN (1 << 0)
#include "defs.h"
+#include "cpu.h"
typedef dword_t (*thread_procedure_t)(void*);