@ -288,6 +288,13 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode,
apic_bus_deliver ( deliver_bitmask , delivery_mode , vector_num , trigger_mode ) ;
}
bool is_x2apic_mode ( DeviceState * dev )
{
APICCommonState * s = APIC ( dev ) ;
return s - > apicbase & MSR_IA32_APICBASE_EXTD ;
}
static void apic_set_base ( APICCommonState * s , uint64_t val )
{
s - > apicbase = ( val & 0xfffff000 ) |
@ -636,24 +643,19 @@ static void apic_timer(void *opaque)
apic_timer_update ( s , s - > next_time ) ;
}
static uint64_t apic_mem_read ( void * opaque , hwaddr addr , unsigned siz e)
static int apic_register_read ( int index , uint64_t * valu e)
{
DeviceState * dev ;
APICCommonState * s ;
uint32_t val ;
int index ;
if ( size < 4 ) {
return 0 ;
}
int ret = 0 ;
dev = cpu_get_current_apic ( ) ;
if ( ! dev ) {
return 0 ;
return - 1 ;
}
s = APIC ( dev ) ;
index = ( addr > > 4 ) & 0xff ;
switch ( index ) {
case 0x02 : /* id */
val = s - > id < < 24 ;
@ -718,12 +720,46 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size)
default :
s - > esr | = APIC_ESR_ILLEGAL_ADDRESS ;
val = 0 ;
ret = - 1 ;
break ;
}
trace_apic_mem_readl ( addr , val ) ;
trace_apic_register_read ( index , val ) ;
* value = val ;
return ret ;
}
static uint64_t apic_mem_read ( void * opaque , hwaddr addr , unsigned size )
{
uint64_t val ;
int index ;
if ( size < 4 ) {
return 0 ;
}
index = ( addr > > 4 ) & 0xff ;
apic_register_read ( index , & val ) ;
return val ;
}
int apic_msr_read ( int index , uint64_t * val )
{
DeviceState * dev ;
dev = cpu_get_current_apic ( ) ;
if ( ! dev ) {
return - 1 ;
}
if ( ! is_x2apic_mode ( dev ) ) {
return - 1 ;
}
return apic_register_read ( index , val ) ;
}
static void apic_send_msi ( MSIMessage * msi )
{
uint64_t addr = msi - > address ;
@ -737,35 +773,18 @@ static void apic_send_msi(MSIMessage *msi)
apic_deliver_irq ( dest , dest_mode , delivery , vector , trigger_mode ) ;
}
static void apic_mem_write ( void * opaque , hwaddr addr , uint64_t val ,
unsigned size )
static int apic_register_write ( int index , uint64_t val )
{
DeviceState * dev ;
APICCommonState * s ;
int index = ( addr > > 4 ) & 0xff ;
if ( size < 4 ) {
return ;
}
if ( addr > 0xfff | | ! index ) {
/* MSI and MMIO APIC are at the same memory location,
* but actually not on the global bus : MSI is on PCI bus
* APIC is connected directly to the CPU .
* Mapping them on the global bus happens to work because
* MSI registers are reserved in APIC MMIO and vice versa . */
MSIMessage msi = { . address = addr , . data = val } ;
apic_send_msi ( & msi ) ;
return ;
}
dev = cpu_get_current_apic ( ) ;
if ( ! dev ) {
return ;
return - 1 ;
}
s = APIC ( dev ) ;
trace_apic_mem_writel ( addr , val ) ;
trace_apic_register_write ( index , val ) ;
switch ( index ) {
case 0x02 :
@ -839,8 +858,51 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val,
break ;
default :
s - > esr | = APIC_ESR_ILLEGAL_ADDRESS ;
break ;
return - 1 ;
}
return 0 ;
}
static void apic_mem_write ( void * opaque , hwaddr addr , uint64_t val ,
unsigned size )
{
int index = ( addr > > 4 ) & 0xff ;
if ( size < 4 ) {
return ;
}
if ( addr > 0xfff | | ! index ) {
/*
* MSI and MMIO APIC are at the same memory location ,
* but actually not on the global bus : MSI is on PCI bus
* APIC is connected directly to the CPU .
* Mapping them on the global bus happens to work because
* MSI registers are reserved in APIC MMIO and vice versa .
*/
MSIMessage msi = { . address = addr , . data = val } ;
apic_send_msi ( & msi ) ;
return ;
}
apic_register_write ( index , val ) ;
}
int apic_msr_write ( int index , uint64_t val )
{
DeviceState * dev ;
dev = cpu_get_current_apic ( ) ;
if ( ! dev ) {
return - 1 ;
}
if ( ! is_x2apic_mode ( dev ) ) {
return - 1 ;
}
return apic_register_write ( index , val ) ;
}
static void apic_pre_save ( APICCommonState * s )