Change the timer syscalls so that sysret_t can be 32-bit
authorcoderain <coderain@sdf.org>
Sun, 18 Nov 2018 16:25:31 +0000 (17:25 +0100)
committercoderain <coderain@sdf.org>
Sun, 18 Nov 2018 23:18:27 +0000 (00:18 +0100)
drivers/acpica/src/osmlxf.c
drivers/ps2/src/main.c
kernel/include/timer.h
kernel/src/syscalls.c
kernel/src/thread.c
kernel/src/timer.c
kernel/src/user.c
sdk/defs.h
sdk/timer.h

index c378a499796bf8bb8b5e61b8c262a029139b7eef..d2e9df6cc2ffc411d9f3d93513953d6ce1c43434 100644 (file)
@@ -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)
index 9fffad83d1cc082ef09f3dffaf5651daa58fa1e1..9c64e65432b762e116297a8362790d4dd2c4b766 100644 (file)
@@ -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);
index 939706e71fe2f4d957a23c59040ea898a2721444..526c653e19072b59299633522c117b5bc82b2416 100644 (file)
@@ -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
index 3d80c25670fb5d8dfc688f58e78ad91c752e3311..547e49bce08cff4178697a09fb11d4856babfd17 100644 (file)
@@ -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()
index b8300dbfbaf20e3bbcec12a7ca65a7b2cc3a7da5..f181de8f1ef59be0ad48924156adb22c32f88634 100644 (file)
@@ -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();
 
index acf02fdba4c6e49c11c00e47c854c3c37b2f7a8b..af296b0d6c18382d81707125a55e81dc3c9f0535 100644 (file)
@@ -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);
 }
index c83fbf8b2f4c61ab8683f985831f2ae8fc349c38..29e14b0a6336adbe928e456c3502575dc1105b04 100644 (file)
@@ -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;
     }
 
index 93b84814a44616cf71d20c1d74f2f4b9d91a48dc..4d07d9beff6372ad0e8489c8a6d9cb4cc350a5d8 100644 (file)
@@ -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;
 
index 23c866250b6be93bf8a2ab00d8c5fe937a1ad9ba..9542068e2834c0e81a796060580d094f74ebbaa3 100644 (file)
 
 #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