Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Implemented (but not yet tested) time interface changes for consistency
[palacios.git] / palacios / src / devices / 8254.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_dev_mgr.h>
23 #include <palacios/vmm_time.h>
24 #include <palacios/vmm_util.h>
25 #include <palacios/vmm_intr.h>
26 #include <palacios/vmm_config.h>
27
28
29 #ifndef CONFIG_DEBUG_PIT
30 #undef PrintDebug
31 #define PrintDebug(fmt, args...)
32 #endif
33
34
35
36 // constants
37 #define OSC_HZ 1193182
38
39
40 /* The 8254 has three counters and one control port */
41 #define CHANNEL0_PORT 0x40
42 #define CHANNEL1_PORT 0x41
43 #define CHANNEL2_PORT 0x42
44 #define COMMAND_PORT 0x43
45 #define SPEAKER_PORT 0x61
46
47
48 #define PIT_INTR_NUM 0
49 #define PIT_SPEAKER_GATE 0x01
50
51 /* The order of these typedefs is important because the numerical values correspond to the 
52  * values coming from the io ports
53  */
54 typedef enum {NOT_RUNNING, PENDING, RUNNING} channel_run_state_t;
55 typedef enum {NOT_WAITING, WAITING_LOBYTE, WAITING_HIBYTE} channel_access_state_t;
56 typedef enum {LATCH_COUNT, LOBYTE_ONLY, HIBYTE_ONLY, LOBYTE_HIBYTE} channel_access_mode_t;
57 typedef enum {IRQ_ON_TERM_CNT, ONE_SHOT, RATE_GEN, SQR_WAVE, SW_STROBE, HW_STROBE} channel_op_mode_t;
58
59
60 struct channel {
61     channel_access_mode_t access_mode;
62     channel_access_state_t access_state;
63     channel_run_state_t run_state;
64
65     channel_op_mode_t op_mode;
66
67
68     // Time til interrupt trigger 
69
70     ushort_t counter;
71     ushort_t reload_value;
72
73     ushort_t latched_value;
74   
75     enum {NOTLATCHED, LATCHED} latch_state;
76
77     enum {LSB, MSB} read_state;
78
79     uint_t output_pin : 1;
80     uint_t gate_input_pin : 1;
81 };
82
83
84 struct pit {
85
86     ullong_t pit_counter;
87     ullong_t pit_reload;
88
89
90     struct channel ch_0;
91     struct channel ch_1;
92     struct channel ch_2;
93     uint8_t speaker;
94 };
95
96
97 struct pit_cmd_word {
98     uint_t bcd_mode    : 1;
99     uint_t op_mode     : 3;
100     uint_t access_mode : 2;
101     uint_t channel     : 2;
102 };
103
104 struct pit_rdb_cmd_word {
105     uint_t rsvd         : 1; // SBZ
106     uint_t ch_0         : 1;
107     uint_t ch_1         : 1;
108     uint_t ch_2         : 1;
109     uint_t latch_status : 1;
110     uint_t latch_count  : 1;
111     uint_t readback_cmd : 2; // Must Be 0x3
112 };
113
114 struct pit_rdb_status_word {
115     uint_t bcd_mode     : 1;
116     uint_t op_mode      : 3;
117     uint_t access_mode  : 2;
118     uint_t null_count   : 1;
119     uint_t pin_state    : 1; 
120 };
121
122
123
124 /* 
125  * This should call out to handle_SQR_WAVE_tics, etc... 
126  */
127 // Returns true if the the output signal changed state
128 static int handle_crystal_tics(struct vm_device * dev, struct channel * ch, uint_t oscillations) {
129     uint_t channel_cycles = 0;
130     uint_t output_changed = 0;
131   
132     // PrintDebug("8254 PIT: %d crystal tics\n", oscillations);
133     if (ch->run_state == PENDING) {
134         oscillations--;
135         ch->counter = ch->reload_value;
136
137         if (ch->op_mode == SQR_WAVE) {
138             ch->counter -= ch->counter % 2;
139         }
140
141         ch->run_state = RUNNING;
142     } else if (ch->run_state != RUNNING) {
143         return output_changed;
144     }
145
146     /*
147       PrintDebug("8254 PIT: Channel Run State = %d, counter=", ch->run_state);
148       PrintTraceLL(ch->counter);
149       PrintDebug("\n");
150     */
151     if (ch->op_mode == SQR_WAVE) {
152         oscillations *= 2;
153     }
154
155     if (ch->counter > oscillations) {
156         ch->counter -= oscillations;
157         return output_changed;
158     } else {
159         ushort_t reload_val = ch->reload_value; 
160
161         if (ch->op_mode == SW_STROBE) {
162             reload_val = 0xffff;
163         }
164
165         // TODO: Check this....
166         // Is this correct???
167         if (reload_val == 0) {
168             reload_val = 1;
169         }
170
171         oscillations -= ch->counter;
172         ch->counter = 0;
173         channel_cycles = 1;
174
175         if (ch->op_mode == SQR_WAVE) {
176             reload_val -= reload_val % 2;
177         }
178
179         channel_cycles += oscillations / reload_val;
180         oscillations = oscillations % reload_val;
181
182         ch->counter = reload_val - oscillations;
183     }
184
185     //  PrintDebug("8254 PIT: Channel Cycles: %d\n", channel_cycles);
186   
187
188
189     switch (ch->op_mode) {
190         case IRQ_ON_TERM_CNT:
191             if ((channel_cycles > 0) && (ch->output_pin == 0)) {
192                 ch->output_pin = 1; 
193                 output_changed = 1;
194             }
195             break;
196         case ONE_SHOT:
197             if ((channel_cycles > 0) && (ch->output_pin == 0)) {
198                 ch->output_pin = 1; 
199                 output_changed = 1;
200             }
201             break;
202         case RATE_GEN:
203             // See the data sheet: we ignore the output pin cycle...
204             if (channel_cycles > 0) {
205                 output_changed = 1;
206             }
207             break;
208         case SQR_WAVE:
209             ch->output_pin = (ch->output_pin + 1) % 2;
210
211             if (ch->output_pin == 1) {
212                 output_changed = 1;
213             }
214
215             break;
216         case SW_STROBE:
217
218             if (channel_cycles > 0) {
219                 if (ch->output_pin == 1) {
220                     ch->output_pin = 0;
221                     output_changed = 1;
222                 }
223             }
224             break;
225         case HW_STROBE:
226             PrintError("Hardware strobe not implemented\n");
227             return -1;
228             break;
229         default:
230             break;
231     }
232
233     return output_changed;
234 }
235                                 
236
237 #include <palacios/vm_guest.h>
238
239 static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
240     struct vm_device * dev = (struct vm_device *)private_data;
241     struct pit * state = (struct pit *)dev->private_data;
242     //  ullong_t tmp_ctr = state->pit_counter;
243     ullong_t tmp_cycles;
244     uint_t oscillations = 0;
245
246
247     /*
248       PrintDebug("updating cpu_cycles=");
249       PrintTraceLL(cpu_cycles);
250       PrintDebug("\n");
251     
252       PrintDebug("pit_counter=");
253       PrintTraceLL(state->pit_counter);
254       PrintDebug("\n");
255     
256       PrintDebug("pit_reload=");
257       PrintTraceLL(state->pit_reload);
258       PrintDebug("\n");
259     */
260
261     if (state->pit_counter > cpu_cycles) {
262         // Easy...
263         state->pit_counter -= cpu_cycles;
264     } else {
265         ushort_t reload_val = state->pit_reload;
266         // Take off the first part
267         cpu_cycles -= state->pit_counter;
268         state->pit_counter = 0;
269         oscillations = 1;
270     
271         if (cpu_cycles > state->pit_reload) {
272             // how many full oscillations
273       
274             //PrintError("cpu_cycles = %p, reload = %p...\n", 
275             //   (void *)(addr_t)cpu_cycles, 
276             //   (void *)(addr_t)state->pit_reload);
277
278             // How do we check for a one shot....
279             if (state->pit_reload == 0) {
280                 reload_val = 1;
281             }
282
283             tmp_cycles = cpu_cycles;
284
285       
286 #ifdef __V3_64BIT__
287             cpu_cycles = tmp_cycles % state->pit_reload;
288             tmp_cycles = tmp_cycles / state->pit_reload;
289 #else
290             cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
291 #endif
292         
293             oscillations += tmp_cycles;
294         }
295
296         // update counter with remainder (mod reload)
297         state->pit_counter = state->pit_reload - cpu_cycles;    
298
299         //PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
300         if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) {
301             // raise interrupt
302             PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n");
303             v3_raise_irq(info->vm_info, 0);
304         }
305
306         //handle_crystal_tics(dev, &(state->ch_1), oscillations);
307         handle_crystal_tics(dev, &(state->ch_2), oscillations);
308     }
309   
310
311
312  
313     return;
314 }
315
316 /* This should call out to handle_SQR_WAVE_write, etc...
317  */
318 static int handle_channel_write(struct channel * ch, char val) {
319
320     switch (ch->access_state) {      
321         case WAITING_HIBYTE:
322             {
323                 ushort_t tmp_val = ((ushort_t)val) << 8;
324                 ch->reload_value &= 0x00ff;
325                 ch->reload_value |= tmp_val;
326         
327
328                 if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
329                     ch->run_state = PENDING;  
330                 }
331         
332                 if (ch->access_mode == LOBYTE_HIBYTE) {
333                     ch->access_state = WAITING_LOBYTE;
334                 }
335
336                 PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);        
337                 PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
338                 break;
339             }
340         case WAITING_LOBYTE:
341             ch->reload_value &= 0xff00;
342             ch->reload_value |= val;
343       
344             if (ch->access_mode == LOBYTE_HIBYTE) {
345                 ch->access_state = WAITING_HIBYTE;
346             } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
347                 ch->run_state = PENDING;
348             }
349       
350             PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);
351             PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
352             break;
353         default:
354             PrintError("Invalid Access state\n");
355             return -1;
356     }
357     
358
359     switch (ch->op_mode) {
360         case IRQ_ON_TERM_CNT:
361             ch->output_pin = 0;
362             break;
363         case ONE_SHOT:
364             ch->output_pin = 1;
365             break;
366         case RATE_GEN:
367             ch->output_pin = 1;
368             break;
369         case SQR_WAVE:
370             ch->output_pin = 1;
371             break;
372         case SW_STROBE:
373             ch->output_pin = 1;
374             break;
375         default:
376             PrintError("Invalid OP_MODE: %d\n", ch->op_mode);
377             return -1;
378             break;
379     }
380
381
382     return 0;
383 }
384
385
386 static int handle_channel_read(struct channel * ch, char * val) {
387
388     ushort_t * myval;
389
390     if (ch->latch_state == NOTLATCHED) { 
391         myval = &(ch->counter);
392     } else {
393         myval = &(ch->latched_value);
394     }
395
396     if (ch->read_state == LSB) { 
397         *val = ((char*)myval)[0];  // little endian
398         ch->read_state = MSB;
399     } else {
400         *val = ((char*)myval)[1];
401         ch->read_state = LSB;
402         if (ch->latch_state == LATCHED) { 
403             ch->latch_state = NOTLATCHED;
404         }
405     }
406
407     return 0;
408
409 }
410
411 static int handle_speaker_read(uint8_t *speaker, struct channel * ch, char * val) {
412     *val = *speaker;
413
414     if ((*speaker & PIT_SPEAKER_GATE)) {
415         *val |= (ch->output_pin << 5);
416     }
417     
418     return 0;
419 }
420
421 static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) {
422     *speaker = (val & ~0x20);
423     return 0;
424 }
425
426 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
427     ch->op_mode = cmd.op_mode;
428     ch->access_mode = cmd.access_mode;
429
430
431
432
433     switch (cmd.access_mode) {
434         case LATCH_COUNT:
435             if (ch->latch_state == NOTLATCHED) { 
436                 ch->latched_value = ch->counter;
437                 ch->latch_state = LATCHED;
438             }
439             break;
440         case HIBYTE_ONLY:
441             ch->access_state = WAITING_HIBYTE;
442             break;
443         case LOBYTE_ONLY: 
444         case LOBYTE_HIBYTE:
445             ch->access_state = WAITING_LOBYTE;
446             break;
447     }
448
449
450     switch (cmd.op_mode) {
451         case IRQ_ON_TERM_CNT:
452             ch->output_pin = 0;
453             break;
454         case ONE_SHOT: 
455             ch->output_pin = 1;
456             break;
457         case RATE_GEN: 
458             ch->output_pin = 1;
459             break;
460         case SQR_WAVE:
461             ch->output_pin = 1;
462             break;
463         case SW_STROBE:
464             ch->output_pin = 1;
465             break;
466         default:
467             PrintError("Invalid OP_MODE: %d\n", cmd.op_mode);
468             return -1;
469     }
470
471     return 0;
472     
473 }
474
475
476
477
478 static int pit_read_channel(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
479     struct pit * state = (struct pit *)dev->private_data;
480     char * val = (char *)dst;
481
482     if (length != 1) {
483         PrintError("8254 PIT: Invalid Read Write length \n");
484         return -1;
485     }
486
487     PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
488
489     switch (port) {
490         case CHANNEL0_PORT: 
491             if (handle_channel_read(&(state->ch_0), val) == -1) {
492                 PrintError("CHANNEL0 read error\n");
493                 return -1;
494             }
495             break;
496         case CHANNEL1_PORT:
497             if (handle_channel_read(&(state->ch_1), val) == -1) {
498                 PrintError("CHANNEL1 read error\n");
499                 return -1;
500             }
501             break;
502         case CHANNEL2_PORT:
503             if (handle_channel_read(&(state->ch_2), val) == -1) {
504                 PrintError("CHANNEL2 read error\n");
505                 return -1;
506             }
507             break;
508         case SPEAKER_PORT:
509             if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) {
510                 PrintError("SPEAKER read error\n");
511                 return -1;
512             }
513             break;
514         default:
515             PrintError("8254 PIT: Read from invalid port (%d)\n", port);
516             return -1;
517     }
518
519     return length;
520 }
521
522
523
524 static int pit_write_channel(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
525     struct pit * state = (struct pit *)dev->private_data;
526     char val = *(char *)src;
527
528     if (length != 1) {
529         PrintError("8254 PIT: Invalid Write Length\n");
530         return -1;
531     }
532
533     PrintDebug("8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src);
534
535
536     switch (port) {
537         case CHANNEL0_PORT:
538             if (handle_channel_write(&(state->ch_0), val) == -1) {
539                 PrintError("CHANNEL0 write error\n");
540                 return -1;
541             } 
542             break;
543         case CHANNEL1_PORT:
544             if (handle_channel_write(&(state->ch_1), val) == -1) {
545                 PrintError("CHANNEL1 write error\n");
546                 return -1;
547             }
548             break;
549         case CHANNEL2_PORT:
550             if (handle_channel_write(&(state->ch_2), val) == -1) {
551                 PrintError("CHANNEL2 write error\n");   
552                 return -1;
553             }
554             break;
555         case SPEAKER_PORT:
556             if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) {
557                 PrintError("SPEAKER write error\n");
558                 return -1;
559             }
560             break;
561         default:
562             PrintError("8254 PIT: Write to invalid port (%d)\n", port);
563             return -1;
564     }
565
566     return length;
567 }
568
569
570
571
572 static int pit_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) {
573     struct pit * state = (struct pit *)dev->private_data;
574     struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
575
576     PrintDebug("8254 PIT: Write to PIT Command port\n");
577     PrintDebug("8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
578     if (length != 1) {
579         PrintError("8254 PIT: Write of Invalid length to command port\n");
580         return -1;
581     }
582
583     switch (cmd->channel) {
584         case 0:
585             if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
586                 PrintError("CHANNEL0 command error\n");
587                 return -1;
588             }
589             break;
590         case 1:
591             if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
592                 PrintError("CHANNEL1 command error\n");
593                 return -1;
594             }
595             break;
596         case 2:
597             if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
598                 PrintError("CHANNEL2 command error\n");
599                 return -1;
600             }
601             break;
602         case 3:
603             // Read Back command
604             PrintError("Read back command not implemented\n");
605             return -1;
606             break;
607         default:
608             break;
609     }
610
611
612     return length;
613 }
614
615
616
617
618 static struct vm_timer_ops timer_ops = {
619     .update_timer = pit_update_timer,
620 };
621
622
623 static void init_channel(struct channel * ch) {
624     ch->run_state = NOT_RUNNING;
625     ch->access_state = NOT_WAITING;
626     ch->access_mode = 0;
627     ch->op_mode = 0;
628
629     ch->counter = 0;
630     ch->reload_value = 0;
631     ch->output_pin = 0;
632     ch->gate_input_pin = 0;
633
634     ch->latched_value = 0;
635     ch->latch_state = NOTLATCHED;
636     ch->read_state = LSB;
637
638     return;
639 }
640
641
642
643
644 static int pit_free(struct vm_device * dev) {
645
646     return 0;
647 }
648
649
650 static struct v3_device_ops dev_ops = {
651     .free = pit_free,
652     .reset = NULL,
653     .start = NULL,
654     .stop = NULL,
655
656 };
657
658 #include <palacios/vm_guest.h>
659
660 static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
661     struct pit * pit_state = NULL;
662     struct vm_device * dev = NULL;
663     char * dev_id = v3_cfg_val(cfg, "ID");
664     
665     // PIT is only usable in non-multicore environments
666     // just hardcode the core context
667     struct guest_info * info = &(vm->cores[0]);
668
669     uint_t cpu_khz = V3_CPU_KHZ();
670     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
671
672     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
673     V3_ASSERT(pit_state != NULL);
674     pit_state->speaker = 0;
675
676     dev = v3_allocate_device(dev_id, &dev_ops, pit_state);
677
678     if (v3_attach_device(vm, dev) == -1) {
679         PrintError("Could not attach device %s\n", dev_id);
680         return -1;
681     }
682
683     v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
684     v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
685     v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
686     v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
687     v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
688
689 #ifdef CONFIG_DEBUG_PIT
690     PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
691     //PrintTrace(reload_val);
692     PrintDebug("\n");
693 #endif
694
695     
696     v3_add_timer(info, &timer_ops, dev);
697
698     // Get cpu frequency and calculate the global pit oscilattor counter/cycle
699
700     do_divll(reload_val, OSC_HZ);
701     pit_state->pit_counter = reload_val;
702     pit_state->pit_reload = reload_val;
703
704
705
706     init_channel(&(pit_state->ch_0));
707     init_channel(&(pit_state->ch_1));
708     init_channel(&(pit_state->ch_2));
709
710 #ifdef CONFIG_DEBUG_PIT
711     PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
712     //PrintTraceLL(pit_state->pit_counter);
713     PrintDebug("\n");
714 #endif
715
716     return 0;
717 }
718
719
720 device_register("8254_PIT", pit_init);