Browse Source

Change the timer syscalls so that sysret_t can be 32-bit

coderain 5 years ago
parent
commit
738cdf14f4
9 changed files with 79 additions and 30 deletions
  1. 3 3
      drivers/acpica/src/osmlxf.c
  2. 4 4
      drivers/ps2/src/main.c
  3. 2 0
      kernel/include/timer.h
  4. 1 2
      kernel/src/syscalls.c
  5. 2 2
      kernel/src/thread.c
  6. 55 13
      kernel/src/timer.c
  7. 3 3
      kernel/src/user.c
  8. 1 1
      sdk/defs.h
  9. 8 2
      sdk/timer.h

+ 3 - 3
drivers/acpica/src/osmlxf.c

@@ -244,7 +244,7 @@ ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
 
 UINT64 AcpiOsGetTimer(void)
 {
-    return syscall_get_nanoseconds() / 100ULL;
+    return timer_get_nanoseconds() / 100ULL;
 }
 
 void AcpiOsSleep(UINT64 Milliseconds)
@@ -254,8 +254,8 @@ void AcpiOsSleep(UINT64 Milliseconds)
 
 void AcpiOsStall(UINT32 Microseconds)
 {
-    qword_t end_time = syscall_get_nanoseconds() + (qword_t)Microseconds * 1000ULL;
-    while (syscall_get_nanoseconds() < end_time) continue;
+    qword_t end_time = timer_get_nanoseconds() + (qword_t)Microseconds * 1000ULL;
+    while (timer_get_nanoseconds() < end_time) continue;
 }
 
 ACPI_THREAD_ID AcpiOsGetThreadId(void)

+ 4 - 4
drivers/ps2/src/main.c

@@ -47,11 +47,11 @@ static ps2_device_t *ps2_devices[2] = { NULL };
 
 static inline bool_t poll_and_read(byte_t *byte)
 {
-    qword_t end_time = syscall_get_milliseconds() + (qword_t)PS2_TIMEOUT;
+    qword_t end_time = timer_get_milliseconds() + (qword_t)PS2_TIMEOUT;
 
     while (!(cpu_read_port_byte(PS2_STATUS_PORT) & PS2_OUTPUT_BUFFER_FULL))
     {
-        if (syscall_get_milliseconds() >= end_time) return FALSE;
+        if (timer_get_milliseconds() >= end_time) return FALSE;
     }
 
     *byte = cpu_read_port_byte(PS2_DATA_PORT);
@@ -60,11 +60,11 @@ static inline bool_t poll_and_read(byte_t *byte)
 
 static inline bool_t poll_and_write(byte_t byte)
 {
-    qword_t end_time = syscall_get_milliseconds() + (qword_t)PS2_TIMEOUT;
+    qword_t end_time = timer_get_milliseconds() + (qword_t)PS2_TIMEOUT;
 
     while (cpu_read_port_byte(PS2_STATUS_PORT) & PS2_INPUT_BUFFER_FULL)
     {
-        if (syscall_get_milliseconds() >= end_time) return FALSE;
+        if (timer_get_milliseconds() >= end_time) return FALSE;
     }
 
     cpu_write_port_byte(PS2_DATA_PORT, byte);

+ 2 - 0
kernel/include/timer.h

@@ -32,6 +32,8 @@
 #define TIMER_RATE_GENERATOR(x) (((x) << 6) | 0x34)
 #define TIMER_SQUARE_WAVE(x) (((x) << 6) | 0x36)
 
+qword_t timer_get_milliseconds(void);
+qword_t timer_get_nanoseconds(void);
 void timer_init(void);
 
 #endif

+ 1 - 2
kernel/src/syscalls.c

@@ -69,8 +69,7 @@ static void system_service_handler(registers_t *regs, byte_t int_num)
     }
 
     sysret_t result = syscall_function(service_table[regs->eax], parameters, sizeof(parameters));
-    regs->eax = (dword_t)result;
-    regs->edx = (dword_t)(result >> 32);
+    regs->eax = result;
 }
 
 processor_mode_t get_previous_mode()

+ 2 - 2
kernel/src/thread.c

@@ -90,7 +90,7 @@ static inline bool_t test_condition(wait_condition_t *condition)
 
 static inline bool_t is_thread_ready(thread_t *thread)
 {
-    qword_t current_time = syscall_get_milliseconds();
+    qword_t current_time = timer_get_milliseconds();
 
     if (thread->terminated) return FALSE;
     if (thread->frozen > 0 && !thread->in_kernel) return FALSE;
@@ -355,7 +355,7 @@ wait_result_t scheduler_wait(wait_condition_t *condition, dword_t timeout)
     if (test_condition(condition)) return WAIT_CONDITION_HIT;
     if (timeout == 0) return WAIT_TIMED_OUT;
 
-    wait_t wait = { .root = condition, .timeout = timeout,  .timestamp = syscall_get_milliseconds(), .result = WAIT_CANCELED };
+    wait_t wait = { .root = condition, .timeout = timeout,  .timestamp = timer_get_milliseconds(), .result = WAIT_CANCELED };
     while (!__sync_bool_compare_and_swap(&current_thread->wait, NULL, &wait)) continue;
     syscall_yield_quantum();
 

+ 55 - 13
kernel/src/timer.c

@@ -1,7 +1,7 @@
 /*
  * timer.c
  *
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
+ * 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
@@ -22,7 +22,9 @@
 
 volatile qword_t total_ticks = 0;
 
-void timer_irq(registers_t *regs, byte_t irq_num)
+static dword_t timer_reload_value;
+
+static void timer_irq(registers_t *regs, byte_t irq_num)
 {
     total_ticks++;
 
@@ -33,12 +35,12 @@ void timer_irq(registers_t *regs, byte_t irq_num)
     }
 }
 
-sysret_t syscall_get_milliseconds(void)
+qword_t timer_get_milliseconds(void)
 {
     return total_ticks;
 }
 
-sysret_t syscall_get_nanoseconds(void)
+qword_t timer_get_nanoseconds(void)
 {
     critical_t critical;
     enter_critical(&critical);
@@ -48,25 +50,65 @@ sysret_t syscall_get_nanoseconds(void)
     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;
+    ASSERT(count <= timer_reload_value);
+    count = timer_reload_value - count;
+
+    result += (count * 1000000000ULL) / (qword_t)TIMER_BASE_FREQUENCY;
 
     leave_critical(&critical);
     return result;
 }
 
+sysret_t syscall_query_timer(long reserved, timer_info_type_t info_type, void *buffer, size_t size)
+{
+    if (get_previous_mode() == USER_MODE && !check_usermode(buffer, size)) return ERR_BADPTR;
+    if (size < sizeof(qword_t)) return ERR_SMALLBUF;
+    qword_t value;
+
+    switch (info_type)
+    {
+    case TIMER_MILLISECONDS:
+        value = timer_get_milliseconds();
+        break;
+
+    case TIMER_NANOSECONDS:
+        value = timer_get_nanoseconds();
+        break;
+
+    case TIMER_PRECISION:
+        value = TIMER_BASE_FREQUENCY;
+        break;
+
+    default:
+        return ERR_INVALID;
+    }
+
+    EH_TRY
+    {
+        *(qword_t*)buffer = value;
+    }
+    EH_CATCH
+    {
+        EH_ESCAPE(return ERR_BADPTR);
+    }
+    EH_DONE;
+
+    return ERR_SUCCESS;
+}
+
 void timer_init(void)
 {
-    dword_t value = TIMER_BASE_FREQUENCY / TIMER_FREQUENCY;
-    dword_t remainder = TIMER_BASE_FREQUENCY - value * TIMER_FREQUENCY;
+    timer_reload_value = TIMER_BASE_FREQUENCY / TIMER_FREQUENCY;
+
+    dword_t remainder = TIMER_BASE_FREQUENCY - timer_reload_value * TIMER_FREQUENCY;
+    if ((remainder * 2) > TIMER_FREQUENCY) timer_reload_value++;
 
-    if ((remainder * 2) > TIMER_FREQUENCY) value++;
-    if (value == 0) value = 1;
-    if (value >= 65536) value = 0;
+    if (timer_reload_value == 0) timer_reload_value = 1;
+    if (timer_reload_value >= 65536) timer_reload_value = 0;
 
     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);
+    cpu_write_port_byte(TIMER_CHANNEL_PORT(0), timer_reload_value & 0xFF);
+    cpu_write_port_byte(TIMER_CHANNEL_PORT(0), (timer_reload_value >> 8) & 0xFF);
     register_irq_handler(TIMER_IRQ, &timer_irq, FALSE);
 }

+ 3 - 3
kernel/src/user.c

@@ -276,7 +276,7 @@ sysret_t syscall_logon_user(uid_t uid, const char *password)
     char *safe_password;
 
     if (user == NULL) return ERR_NOTFOUND;
-    if ((syscall_get_milliseconds() - current_user->last_login_attempt) < LOGIN_ATTEMPT_TIMEOUT) return ERR_BUSY;
+    if ((timer_get_milliseconds() - current_user->last_login_attempt) < LOGIN_ATTEMPT_TIMEOUT) return ERR_BUSY;
 
     if (get_previous_mode() == USER_MODE)
     {
@@ -289,7 +289,7 @@ sysret_t syscall_logon_user(uid_t uid, const char *password)
 
     if (uid == 0)
     {
-        current_user->last_login_attempt = syscall_get_milliseconds();
+        current_user->last_login_attempt = timer_get_milliseconds();
         ret = ERR_INVALID;
         goto cleanup;
     }
@@ -312,7 +312,7 @@ sysret_t syscall_logon_user(uid_t uid, const char *password)
     }
     else
     {
-        user->last_login_attempt = syscall_get_milliseconds();
+        user->last_login_attempt = timer_get_milliseconds();
         ret = ERR_INVALID;
     }
 

+ 1 - 1
sdk/defs.h

@@ -76,7 +76,7 @@ typedef uint32_t dword_t;
 typedef uint64_t qword_t;
 
 /* System call return value */
-typedef qword_t sysret_t;
+typedef dword_t sysret_t;
 
 typedef dword_t timeout_t;
 

+ 8 - 2
sdk/timer.h

@@ -22,7 +22,13 @@
 
 #include "defs.h"
 
-sysret_t syscall_get_milliseconds(void);
-sysret_t syscall_get_nanoseconds(void);
+typedef enum
+{
+    TIMER_MILLISECONDS,
+    TIMER_NANOSECONDS,
+    TIMER_PRECISION,
+} timer_info_type_t;
+
+sysret_t syscall_query_timer(long reserved, timer_info_type_t info_type, void *buffer, size_t size);
 
 #endif