File: apic.h

package info (click to toggle)
bochs 2.3-2etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 14,116 kB
  • ctags: 16,927
  • sloc: cpp: 130,524; ansic: 18,822; sh: 7,922; makefile: 3,836; yacc: 1,056; asm: 463; perl: 381; lex: 280; csh: 3
file content (215 lines) | stat: -rw-r--r-- 7,296 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/////////////////////////////////////////////////////////////////////////
// $Id: apic.h,v 1.33 2006/06/05 05:39:21 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
/////////////////////////////////////////////////////////////////////////

#ifndef BX_CPU_APIC_H
#  define BX_CPU_APIC_H 1

#if BX_CPU_LEVEL == 6 && BX_SUPPORT_SSE >= 2
  #define BX_IMPLEMENT_XAPIC 1
#endif

#if BX_SUPPORT_APIC

typedef enum {
  APIC_TYPE_IOAPIC,
  APIC_TYPE_LOCAL_APIC
} bx_apic_type_t;

#define APIC_LEVEL_TRIGGERED	1
#define APIC_EDGE_TRIGGERED	0

class BOCHSAPI bx_generic_apic_c : public logfunctions {
protected:
  bx_phy_address base_addr;
  Bit8u id;
#define APIC_UNKNOWN_ID 0xff
public:
  bx_generic_apic_c(bx_phy_address base);
  virtual ~bx_generic_apic_c() { }
  // init is called during RESET and when an INIT message is delivered
  virtual void init() { }
  virtual void reset() { }
  bx_phy_address get_base(void) const { return base_addr; }
  void set_base(bx_phy_address newbase);
  void set_id(Bit8u newid);
  Bit8u get_id() const { return id; }
  bx_bool is_selected(bx_phy_address addr, unsigned len);
  void read(bx_phy_address addr, void *data, unsigned len);
  virtual void read_aligned(bx_phy_address address, Bit32u *data) = 0;
  void write(bx_phy_address address, void *value, unsigned len);
  virtual void write_aligned(bx_phy_address address, Bit32u *data) = 0;
  virtual bx_apic_type_t get_type() = 0;
};

#ifdef BX_INCLUDE_LOCAL_APIC

#define BX_CPU_APIC(i) (&(BX_CPU(i)->local_apic))

#ifdef BX_IMPLEMENT_XAPIC
#  define BX_LAPIC_VERSION_ID 0x00050014  // P4 has 6 LVT entries
#else
#  define BX_LAPIC_VERSION_ID 0x00040010  // P6 has 4 LVT entries
#endif

#define BX_LAPIC_BASE_ADDR  0xfee00000  // default Local APIC address

#define BX_NUM_LOCAL_APICS BX_SMP_PROCESSORS

#define BX_APIC_FIRST_VECTOR	0x10
#define BX_APIC_LAST_VECTOR	0xfe
#define BX_LOCAL_APIC_MAX_INTS  256

class BOCHSAPI bx_local_apic_c : public bx_generic_apic_c 
{
  Bit32u  spurious_vector;
  bx_bool software_enabled;
  bx_bool focus_disable;

  Bit32u task_priority;         // Task priority (TPR)
  Bit32u log_dest;              // Logical destination (LDR)
  Bit32u dest_format;           // Destination format (DFR)

  // ISR=in-service register.  When an IRR bit is cleared, the corresponding
  // bit in ISR is set.
  Bit8u isr[BX_LOCAL_APIC_MAX_INTS];
  // TMR=trigger mode register.  Cleared for edge-triggered interrupts
  // and set for level-triggered interrupts. If set, local APIC must send
  // EOI message to all other APICs.
  Bit8u tmr[BX_LOCAL_APIC_MAX_INTS];
  // IRR=interrupt request register. When an interrupt is triggered by
  // the I/O APIC or another processor, it sets a bit in irr. The bit is
  // cleared when the interrupt is acknowledged by the processor.
  Bit8u irr[BX_LOCAL_APIC_MAX_INTS];

#define APIC_ERR_ILLEGAL_ADDR    0x80
#define APIC_ERR_RX_ILLEGAL_VEC  0x40
#define APIC_ERR_TX_ILLEGAL_VEC  0x20
#define APIC_ERR_RX_ACCEPT_ERR   0x08
#define APIC_ERR_TX_ACCEPT_ERR   0x04
#define APIC_ERR_RX_CHECKSUM     0x02
#define APIC_ERR_TX_CHECKSUM     0x01

  // Error status Register (ESR)
  Bit32u error_status, shadow_error_status;

  Bit32u icr_hi;                // Interrupt command register (ICR)
  Bit32u icr_lo;

#define APIC_LVT_ENTRIES 6
  Bit32u lvt[APIC_LVT_ENTRIES];
#define APIC_LVT_TIMER   0
#define APIC_LVT_THERMAL 1
#define APIC_LVT_PERFORM 2
#define APIC_LVT_LINT0   3
#define APIC_LVT_LINT1   4
#define APIC_LVT_ERROR   5

  Bit32u timer_initial;         // Initial timer count
  Bit32u timer_current;         // current timer count

  Bit32u timer_divconf;         // Timer divide configuration register
  Bit32u timer_divide_factor;

  // Internal timer state, not accessible from bus
  bx_bool timer_active;
  int timer_handle;
  Bit64u ticksInitial;

/* APIC delivery modes */
#define APIC_DM_FIXED	0
#define APIC_DM_LOWPRI	1
#define APIC_DM_SMI	2
/* RESERVED		3 */
#define APIC_DM_NMI	4
#define APIC_DM_INIT	5
#define APIC_DM_SIPI	6
#define APIC_DM_EXTINT	7

  BX_CPU_C *cpu;

  // corresponding BX_CPU_ID for the local APIC
  unsigned cpu_id;

public:
  bx_bool INTR;
  bx_local_apic_c(BX_CPU_C *cpu);
  virtual ~bx_local_apic_c(void) { }
  virtual void reset(void);
  virtual void init(void);
  BX_CPU_C *get_cpu() { return cpu; }
  void set_id(Bit8u newid);   // redefine to set cpu->name
  virtual void write_aligned(bx_phy_address addr, Bit32u *data);
  virtual void read_aligned(bx_phy_address address, Bit32u *data);
  void startup_msg(Bit32u vector);
  // on local APIC, trigger means raise the CPU's INTR line. For now
  // I also have to raise pc_system.INTR but that should be replaced
  // with the cpu-specific INTR signals.
  void trigger_irq(unsigned num, unsigned trigger_mode, bx_bool bypass_irr_isr = 0);
  void untrigger_irq(unsigned num, unsigned trigger_mode);
  Bit8u acknowledge_int(void);  // only the local CPU should call this
  int highest_priority_int(Bit8u *array);
  void receive_EOI(Bit32u value);
  void send_ipi(void);
  void write_spurious_interrupt_register(Bit32u value);
  void service_local_apic(void);
  void print_status(void);
  bx_bool match_logical_addr (Bit8u address);
  virtual bx_apic_type_t get_type(void) { return APIC_TYPE_LOCAL_APIC; }
  bx_bool deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_mode);
  Bit8u get_tpr(void);
  void  set_tpr(Bit8u tpr);
  Bit8u get_ppr(void);
  Bit8u get_apr(void);
  bx_bool is_focus(Bit8u vector);
  static void periodic_smf(void *);
  void periodic(void);
  void set_divide_configuration(Bit32u value);
  void set_initial_timer_count(Bit32u value);
#if BX_SUPPORT_SAVE_RESTORE
  void register_state(bx_param_c *parent);
#endif
};

#endif /* BX_INCLUDE_LOCAL_APIC */

// For P6 and Pentium family processors the local APIC ID feild is 4 bits.
#ifdef BX_IMPLEMENT_XAPIC
  #define APIC_MAX_ID  0xff
  #define APIC_ID_MASK 0xff
#else
  #define APIC_MAX_ID  0x0f
  #define APIC_ID_MASK 0x0f
#endif

int apic_bus_deliver_lowest_priority(Bit8u vector, Bit8u dest, bx_bool trig_mode, bx_bool broadcast);
int apic_bus_deliver_interrupt(Bit8u vector, Bit8u dest, Bit8u delivery_mode, Bit8u dest_mode, bx_bool level, bx_bool trig_mode);
int apic_bus_broadcast_interrupt(Bit8u vector, Bit8u delivery_mode, bx_bool trig_mode, int exclude_cpu);

#endif // if BX_SUPPORT_APIC

#endif