Wednesday, October 14, 2015

System Service Dispatching

System Service Dispatch ∨ (sysCALL) OS tərəfindən təyin olunmuş kernel əsaslı funksiyaları işə salır (trigger)
(pentium II əvvəlindəki x86 prosesorlar int 0x2e təlimatı əsasında trap handler işə salırdı)
Windows Based
Trap Handler – Trap – interrupt və yaxud exception yarandıqda icrada olan threadi nəzarətə götürür və sabit bir yerə (routine və s.) kontrolun köçürülməsi əməliyyatını yerinə yetirir.
Hardware/Software Interrupts --- > trap handler kontrolu INTERRUPT Service Routines (ISR)-ə transfer edir.
Hardware/Software Exceptions --- > trap handler kontrolu Exception Dispatchers (ED)-ə transfer edir.
System service calls --- > trap handler kontrolu system service function (SSF)-ə transfer edir.
                                                          Trap handler
Interrupt ————— > INTERRUPT SERVICE ROUTINE
System service call ————— > SYSTEM SERVICES
Hardware exceptions|Software Exceptions –> EXCEPTION dispatcher —> Exception handlers
Virtual addr exceptions —- > Virtual memory manager’s pager
Hardware və software exception və interrupt generasiya edə bilir. Misal üçün: ‘Bus error exception’ hardware probleminƏ görə yaranır. ‘divide-by-zero exception’ isə sofware probleminə görə yaranır. Həmçinin I/O cihazları interrupt generasiya edə bilər. Kernel özü də bir software interrupt verə bilər.
Yuxarıdakı schema-da kernel trap işləyicileri interrupts,exceptions və system service çağırışlarını göndərir. System service dispatch, System service dispatchingdə təyin olunmuş təlimatının(instruction) icrası nəticəsində işə düşür.

System Service Dispatching

x86 prosessorlarında Pentium II-dən əvvəl Windows int 0x2e (46 onluq) təlimatı (instruction) istifadə edirdi. Bu interrupt vektoru trap ilə nəticələnir. Windows IDT-da (Interrupt Descriptor Table) 46cı entry SSD-ni(System Service dispatcher) göstərir.
Fig 1.0
lkd> !idt 2e
Dumping IDT: 80b95400
898023cf0000002e:    82e9822e nt!KiSystemService
Trap icrada olan thread-in kernel mode keçidinə və system service dispatcher-a daxil olmasına səbəb olur. EAX prosessor registerinə daxil edilmiş rəqəmli arqument istənilən system servis nömrəsini göstərir. İstifadəçi moduna geri dönmək üçün, system service dispatcher iret (interrupt return instruction) istifadə edir.
x86 Pentium II və yüksək prosessorlarda, Windows systen təlimatı(instruction) istifadə edir, İntel bunu xüsusi olaraq daha sürətli system service dispatch üçün təyin edib. Windows boot zamanı kernel system service dispatch routine adresini MSR (Machine specific register-da saxlayır. System servis nömrəsi EAX prosessor registerində qeyd edilir. Bu təlimatın icrasın kernel moda keçişə və system service dispatcher işə düşməsinə səbəb olur. User moda qayitmaq üçün isə sysexit təlimatı istifadə olunur.
  1. Fig 1.0 göstərildiyi kimi 32 bit kernel debugger-da sistemlərdə system call dispatcher handler !idt 2eilə göstərilə bilir.
  2. Handler-in sysenter versiyasına baxmaq üçün rdmsr təlimatından istifadə edərək MSR 0x176 registerindən oxumaq mümkündür.
lkd> rdmsr 176
msr[176] = 00000000`82e5b300
lkd> ln 00000000`82e5b300
(82e5b300)   nt!KiFastCallEntry
SharedUserData strukturunda doğru kod üçün bir pointer saxlanaraq istifadə etmək üçün uyğun system call kodunu təyin edər. User modda NtReadFile üçün system service code buna bənzəyir.
lkd> u ntdll!NtReadFile
ntdll!NtReadFile:
77125700 b811010000      mov     eax,111h
77125705 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
7712570a ff12            call    dword ptr [edx]
7712570c c22400          ret     24h
System service number 0x111-dir(273 onluq), və kernel tərəfindən təyin edilmiş system dispatch code call təlimatı icra edir, onun pointeri 0x7ffe0300adresindədir. (Bu KUSER_SHARED_DATA strukturunun SystemCallStub member-nə qarşılıq gəlir, bu da 0x7FFE0000 adresindən başlayır)
#define MM_SHARED_USER_DATA_VA      0x7FFE0000
#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)MM_SHARED_USER_DATA_VA)
lkd> u 771264f0
ntdll!KiFastSystemCall:
771264f0 8bd4            mov     edx,esp
771264f2 0f34            sysenter
E.g 1.0-da göstərildiyi kimi, kernel system service dispatch table system service (servis) məlumatlarını tapmaq üçün system call number istifadə edir.
E.g 1.0:
User Mode ————-> system call —-(transition to kernel mode)—- > kernel mode
kernel mode: System service dispatcher (2) ——> System service dispatch table (2):
0System service 0
1System service 1
2System service 2
Bu table Interrupt dispatch table bənzəyir ancaq hər giriş system service əvəzinə interrupt-handling routine göstərir.
System service dispatcher KiSystemService, işə salanın argumentlərini user mod stack-dən kernel stack-ə moda copy edir daha sonra system service icra edilir. Kernel nə qədər stack byte olduğunu bilmək üçün second table istifadə edərək kopyalama tələb edir, bu table argument table adlanır.
typedef struct _SYSTEM_SERVICE_TABLE {
    PVOID *ServiceTable; //System Service Dispatch Table
    PVOID *CounterTable; //istifadə edilmir
    ULONG ServiceLimit; // SSDT table dəyərlərinin sayı
    PUCHAR ArgumentTable; // Dispatch table içindəki ki routine-lər üçün argumentləri saxlayır.
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
reference kimi bir şəkildə verirəm: 
(ServiceTable this the array of function pointers to kernel routines)
lkd> dps !KeServiceDescriptorTable
82f809c0  82e876f0 nt!KiServiceTable
82f809c4  00000000 //not used
82f809c8  00000191 //servicelimit
82f809cc  82e87d38 nt!KiArgumentTable
Sistem servisinə daxil edilmiş arqumentlər istifadəçi sahəsindəki buferdədirsə. Kernel-moda kod kopyalamadan öncə giriş imkanı üçün bu bufer problanmalıdır (yoxlanılmalıdır). Bu problama yalnız threadin previous modu user mode təyin edildikdə həyata keçirilir. Previous mode kernelin thread üzərində trap handler icra edildiyində və daxil olan istisnanın,trap,və yaxud syscall (sistem çağırışının) imtiyaz səviyyəsini müəyyən etmək üçün saxladığı bir dəyərdir (kernel və yaxud user). Optimallaşdırma üçün isə system çağırışının driver və yaxud kernel modun özündən gəldiyi halda probing (yoxlama) və capturing parametrləri nəzərə alınmır və bütün parametrlər etibarlı kernel mod buferlərinə işarə edilir. Kernel mode-da system çağırışları edə bilir. Hər sistem çağırışı üçün kod kernel modda olduğundan və caller kernel modda olduğu üçün siz burada interrupt və sysenter əməliyyatlarına ehtiyyac olmadığını görə bilərsiniz. Driver və yaxud kernel yalnız tələb olunan funksiyanı birbaşa işə sala bilər.

Saturday, May 23, 2015

i8042 keyboard controller




I/O Ports and I/O Memory
Every peripheral device is controlled by writing and reading its registers. Most of the time a device has several registers, and they are accessed at consecutive addresses, either in the memory address space or in the I/O address space. At the hardware level, there is no conceptual difference between memory regions and I/O regions: both of them are accessed by asserting electrical signals on the address bus and control bus (i.e., the read and write signals)* and by reading from or writing to the data bus.

Intel reference:
An I/O port can be an input port….Some I/O ports are used for transmitting data,
such as to and from the transmit and receive registers, respectively, of a serial interface device. Other I/O ports are used to control peripheral devices, such as the control registers of a disk controller.


I/O INSTRUCTIONS
The processor’s I/O instructions provide access to I/O ports through the I/O address space. (These instructions cannot be used to access memory-mapped I/O ports.) The register I/O instructions IN (input from I/O port) and OUT (output to I/O port) move data between I/O ports and the EAX register (32-bit I/O), the AX register (16-bit I/O), or the AL (8-bit I/O) register. The address of the I/O port can be given with an immediate value or a value in the DX register.


Kernel implementation:

Each device connected to the I/O bus has its own set of I/O addresses, which are usually called I/O ports.
Any : Understanding kernel - >  subject: I/O Ports page 520

Custom I/O interfaces
Just to give an idea of how much variety is encompassed by custom I/O interfaces— thus by the devices currently installed in a PC—we’ll list some of the most commonly found:
Keyboard interface Connected to a keyboard controller that includes a dedicated microprocessor. This microprocessor decodes the combination of pressed keys, generates an interrupt, and puts the corresponding scan code in an input register.

Receiving data from I/O ports :
the I/O address space provides up to 65,536 8-bit I/O ports. Two signal request 16-bit port. Four special assembly language instructions called in, ins, out, and outs allow the CPU to read from and write into an 
I/O port.
Each device are structured into a set of specialized registers: The CPU writes the commands to be sent to the device into the device control register and reads a value that represents the internal state of the device from the device status register. The CPU also fetches data from the device by reading bytes from the device input register and pushes data to the device by writing bytes into the device output
register.


|||||||||||||| ==> control register ==>
||||||||||||||
||||||||||||||  <== status register <==
|||    CPU    |||
||||||||||||||   
||||||||||||||   <== input register <==
||||||||||||||
|||||||||||||| ==> output  register ==>

||||||||||||||||||
||||||||||||||||||
||||||||||||||||||
|||     I/O DEV   ||||
||||||||||||||||||
||||||||||||||||||
||||||||||||||||||
||||||||||||||||||






readable /proc/interrupts
           CPU0
  0:        168   IO-APIC-edge      timer
  1:         59   IO-APIC-edge      i8042 <<< ====== 1 IRQ keyboard controller
  6:          3   IO-APIC-edge      floppy
  8:          1   IO-APIC-edge      rtc0
  9:          0   IO-APIC-fasteoi   acpi
 12:       5572   IO-APIC-edge      i8042 +++++ 12 IRQ line (mouse)

Dmesg =>
[    0.840639] serio: i8042 KBD port at 0x60,0x64 irq 1
[    0.840651] serio: i8042 AUX port at 0x60,0x64 irq 12
[    1.111561] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1

i8042 keyboard and mouse controller driver for Linux kernel

381  * i8042_start() is called by serio core when port is about to finish
382  * registering. It will mark port as existing so i8042_interrupt can
383  * start sending data through it.
384  */
385 static int i8042_start(struct serio *serio)
386 {
387         struct i8042_port *port = serio->port_data;
388 
389         port->exists = true;
390         mb();
391         return 0;
392 }
Ivoke IRQ (handling)
Reading to header file: drivers/input/serio/i8042-io.h?v=3.4
 45 #define I8042_COMMAND_REG       0x64
 46 #define I8042_STATUS_REG        0x64
 47 #define I8042_DATA_REG          0x60 < =
 
 

49 static inline int i8042_read_data(void)
 50 {
 51         return inb(I8042_DATA_REG);
 52 }

I/O Privilege Level
In systems where I/O protection is used, the IOPL field in the EFLAGS register controls access to the I/O address space by restricting use of selected instructions. This protection mechanism permits the operating system or executive to set the privilege level needed to perform I/O. In a typical protection ring model, access to the I/O address space is restricted to privilege levels 0 and 1.


Change privilege level ring3   
 #include <sys/io.h>

        #include <stdio.h>
    int main()
    {
        int x=0;
            iopl(3);
           //outb(0x42,0x60);
            printf("%x",inb(0x60));
            x++;
return 0 ;
    }
stealing ? :)

Scancodes:
The data from a keyboard comes mainly in the form of scancodes, produced by key presses or used in the protocol with the computer.

Output scancodes but translate to keyscan codes

drivers/tty/vt/keyboard.c

152 /*
153  * Translation of scancodes to keycodes. We set them on only the first
154  * keyboard in the list that accepts the scancode and keycode.
155  * Explanation for not choosing the first attached keyboard anymore:
156  *  USB keyboards for example have two event devices: one for all "normal"
157  *  keys and one for extra function keys (like "volume up", "make coffee",
158  *  etc.). So this means that scancodes for the extra function keys won't
159  *  be valid for the first event device, but will be for the second.
160  */
161 
162 struct getset_keycode_data {
163         struct input_keymap_entry ke;
164         int error;
165 };

Header file : include/uapi/linux/input.h#L91
204 /*
205  * Keys and buttons
206  *
207  * Most of the keys/buttons are modeled after USB HUT 1.12
208  * (see http://www.usb.org/developers/hidpage).
209  * Abbreviations in the comments:
210  * AC - Application Control
211  * AL - Application Launch Button
212  * SC - System Control
213  */
214 
215 #define KEY_RESERVED            0
216 #define KEY_ESC                 1
217 #define KEY_1                   2
218 #define KEY_2                   3
219 #define KEY_3                   4
220 #define KEY_4                   5
221 #define KEY_5                   6
222 #define KEY_6                   7
223 #define KEY_7                   8
224 #define KEY_8                   9
225 #define KEY_9                   10
226 #define KEY_0                   11
227 #define KEY_MINUS               12
228 #define KEY_EQUAL               13
229 #define KEY_BACKSPACE           14
230 #define KEY_TAB                 15
231 #define KEY_Q                   16
232 #define KEY_W                   17
233 #define KEY_E                   18
234 #define KEY_R                   19
235 #define KEY_T                   20
236 #define KEY_Y                   21
237 #define KEY_U                   22
238 #define KEY_I                   23
239 #define KEY_O                   24
240 #define KEY_P                   25