summaryrefslogtreecommitdiff
path: root/i386
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2024-02-05 11:33:39 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2024-02-05 23:04:22 +0100
commita923f97ff290a70fc224ac79ab276feae1cfbf53 (patch)
treef141875ccd99d1bfcd34c5b45d503f4ec56310d8 /i386
parenta59e2ed64ba07d19657b25cbedd25586a912c8ed (diff)
Fix apic_send_ipi function clobbering read only fields
This was the root cause of failing to INIT. We were clobbering remote_read_status. And also, we need to reference the .r register when writing the ICR regs otherwise I think it writes all of the block. Message-ID: <20240205113327.1568218-2-damien@zamaudio.com>
Diffstat (limited to 'i386')
-rw-r--r--i386/i386/apic.c8
-rw-r--r--i386/i386/apic.h2
2 files changed, 7 insertions, 3 deletions
diff --git a/i386/i386/apic.c b/i386/i386/apic.c
index 0cf7c37c..700fafd3 100644
--- a/i386/i386/apic.c
+++ b/i386/i386/apic.c
@@ -290,6 +290,10 @@ void apic_send_ipi(unsigned dest_shorthand, unsigned deliv_mode, unsigned dest_m
IcrLReg icrl_values;
IcrHReg icrh_values;
+ /* Keep previous values and only overwrite known fields */
+ icrl_values.r = lapic->icr_low.r;
+ icrh_values.r = lapic->icr_high.r;
+
icrl_values.destination_shorthand = dest_shorthand;
icrl_values.delivery_mode = deliv_mode;
icrl_values.destination_mode = dest_mode;
@@ -298,8 +302,8 @@ void apic_send_ipi(unsigned dest_shorthand, unsigned deliv_mode, unsigned dest_m
icrl_values.vector = vector;
icrh_values.destination_field = dest_id;
- lapic->icr_high = icrh_values;
- lapic->icr_low = icrl_values;
+ lapic->icr_high.r = icrh_values.r;
+ lapic->icr_low.r = icrl_values.r;
}
void
diff --git a/i386/i386/apic.h b/i386/i386/apic.h
index e410e9c6..e1d49895 100644
--- a/i386/i386/apic.h
+++ b/i386/i386/apic.h
@@ -83,7 +83,7 @@ typedef union u_icr_low
unsigned :1;
unsigned level: 1;
unsigned trigger_mode: 1;
- unsigned :2;
+ unsigned remote_read_status: 2; /* Read-only field */
unsigned destination_shorthand: 2;
unsigned :12;
};