Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
8897452d
Commit
8897452d
authored
Apr 02, 2002
by
Dave Jones
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] x86 microcode driver update
From Tigran via 2.4
parent
7e7a44c1
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
68 additions
and
37 deletions
+68
-37
arch/i386/kernel/microcode.c
arch/i386/kernel/microcode.c
+68
-37
No files found.
arch/i386/kernel/microcode.c
View file @
8897452d
...
@@ -51,6 +51,12 @@
...
@@ -51,6 +51,12 @@
* Bugfix for HT (Hyper-Threading) enabled processors
* Bugfix for HT (Hyper-Threading) enabled processors
* whereby processor resources are shared by all logical processors
* whereby processor resources are shared by all logical processors
* in a single CPU package.
* in a single CPU package.
* 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
* Tigran Aivazian <tigran@veritas.com>,
* Serialize updates as required on HT processors due to speculative
* nature of implementation.
* 1.11 22 Mar 2001 Tigran Aivazian <tigran@veritas.com>
* Fix the panic when writing zero-length microcode chunk.
*/
*/
#include <linux/init.h>
#include <linux/init.h>
...
@@ -60,12 +66,16 @@
...
@@ -60,12 +66,16 @@
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
#include <linux/miscdevice.h>
#include <linux/miscdevice.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <asm/msr.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/processor.h>
#define MICROCODE_VERSION "1.09"
static
spinlock_t
microcode_update_lock
=
SPIN_LOCK_UNLOCKED
;
#define MICROCODE_VERSION "1.11"
MODULE_DESCRIPTION
(
"Intel CPU (IA-32) microcode update driver"
);
MODULE_DESCRIPTION
(
"Intel CPU (IA-32) microcode update driver"
);
MODULE_AUTHOR
(
"Tigran Aivazian <tigran@veritas.com>"
);
MODULE_AUTHOR
(
"Tigran Aivazian <tigran@veritas.com>"
);
...
@@ -195,7 +205,8 @@ static void do_update_one(void *unused)
...
@@ -195,7 +205,8 @@ static void do_update_one(void *unused)
struct
cpuinfo_x86
*
c
=
cpu_data
+
cpu_num
;
struct
cpuinfo_x86
*
c
=
cpu_data
+
cpu_num
;
struct
update_req
*
req
=
update_req
+
cpu_num
;
struct
update_req
*
req
=
update_req
+
cpu_num
;
unsigned
int
pf
=
0
,
val
[
2
],
rev
,
sig
;
unsigned
int
pf
=
0
,
val
[
2
],
rev
,
sig
;
int
i
,
found
=
0
;
unsigned
long
flags
;
int
i
;
req
->
err
=
1
;
/* assume update will fail on this cpu */
req
->
err
=
1
;
/* assume update will fail on this cpu */
...
@@ -216,8 +227,9 @@ static void do_update_one(void *unused)
...
@@ -216,8 +227,9 @@ static void do_update_one(void *unused)
for
(
i
=
0
;
i
<
microcode_num
;
i
++
)
for
(
i
=
0
;
i
<
microcode_num
;
i
++
)
if
(
microcode
[
i
].
sig
==
sig
&&
microcode
[
i
].
pf
==
pf
&&
if
(
microcode
[
i
].
sig
==
sig
&&
microcode
[
i
].
pf
==
pf
&&
microcode
[
i
].
ldrver
==
1
&&
microcode
[
i
].
hdrver
==
1
)
{
microcode
[
i
].
ldrver
==
1
&&
microcode
[
i
].
hdrver
==
1
)
{
int
sum
=
0
;
found
=
1
;
struct
microcode
*
m
=
&
microcode
[
i
];
unsigned
int
*
sump
=
(
unsigned
int
*
)(
m
+
1
);
printf
(
"Microcode
\n
"
);
printf
(
"Microcode
\n
"
);
printf
(
" Header Revision %d
\n
"
,
microcode
[
i
].
hdrver
);
printf
(
" Header Revision %d
\n
"
,
microcode
[
i
].
hdrver
);
...
@@ -234,54 +246,69 @@ static void do_update_one(void *unused)
...
@@ -234,54 +246,69 @@ static void do_update_one(void *unused)
printf
(
" Loader Revision %x
\n
"
,
microcode
[
i
].
ldrver
);
printf
(
" Loader Revision %x
\n
"
,
microcode
[
i
].
ldrver
);
printf
(
" Processor Flags %x
\n\n
"
,
microcode
[
i
].
pf
);
printf
(
" Processor Flags %x
\n\n
"
,
microcode
[
i
].
pf
);
req
->
slot
=
i
;
/* serialize access to update decision */
spin_lock_irqsave
(
&
microcode_update_lock
,
flags
);
/* trick, to work even if there was no prior update by the BIOS */
/* trick, to work even if there was no prior update by the BIOS */
wrmsr
(
MSR_IA32_UCODE_REV
,
0
,
0
);
wrmsr
(
MSR_IA32_UCODE_REV
,
0
,
0
);
__asm__
__volatile__
(
"cpuid"
:
:
:
"ax"
,
"bx"
,
"cx"
,
"dx"
);
__asm__
__volatile__
(
"cpuid"
:
:
:
"ax"
,
"bx"
,
"cx"
,
"dx"
);
/* get current (on-cpu) revision into rev (ignore val[0]) */
/* get current (on-cpu) revision into rev (ignore val[0]) */
rdmsr
(
MSR_IA32_UCODE_REV
,
val
[
0
],
rev
);
rdmsr
(
MSR_IA32_UCODE_REV
,
val
[
0
],
rev
);
if
(
microcode
[
i
].
rev
<
rev
)
{
if
(
microcode
[
i
].
rev
<
rev
)
{
spin_unlock_irqrestore
(
&
microcode_update_lock
,
flags
);
printk
(
KERN_ERR
printk
(
KERN_ERR
"microcode: CPU%d not 'upgrading' to earlier revision"
"microcode: CPU%d not 'upgrading' to earlier revision"
" %d (current=%d)
\n
"
,
cpu_num
,
microcode
[
i
].
rev
,
rev
);
return
;
}
else
if
(
microcode
[
i
].
rev
==
rev
)
{
/* notify the caller of success on this cpu */
req
->
err
=
0
;
spin_unlock_irqrestore
(
&
microcode_update_lock
,
flags
);
printk
(
KERN_ERR
"microcode: CPU%d already at revision"
" %d (current=%d)
\n
"
,
cpu_num
,
microcode
[
i
].
rev
,
rev
);
" %d (current=%d)
\n
"
,
cpu_num
,
microcode
[
i
].
rev
,
rev
);
}
else
{
return
;
int
sum
=
0
;
}
struct
microcode
*
m
=
&
microcode
[
i
];
unsigned
int
*
sump
=
(
unsigned
int
*
)(
m
+
1
);
while
(
--
sump
>=
(
unsigned
int
*
)
m
)
sum
+=
*
sump
;
if
(
sum
!=
0
)
{
printk
(
KERN_ERR
"microcode: CPU%d aborting, "
"bad checksum
\n
"
,
cpu_num
);
break
;
}
/* write microcode via MSR 0x79 */
wrmsr
(
MSR_IA32_UCODE_WRITE
,
(
unsigned
int
)(
m
->
bits
),
0
);
/* serialize */
/* Verify the checksum */
__asm__
__volatile__
(
"cpuid"
:
:
:
"ax"
,
"bx"
,
"cx"
,
"dx"
);
while
(
--
sump
>=
(
unsigned
int
*
)
m
)
sum
+=
*
sump
;
if
(
sum
!=
0
)
{
req
->
err
=
1
;
spin_unlock_irqrestore
(
&
microcode_update_lock
,
flags
);
printk
(
KERN_ERR
"microcode: CPU%d aborting, "
"bad checksum
\n
"
,
cpu_num
);
return
;
}
/* write microcode via MSR 0x79 */
wrmsr
(
MSR_IA32_UCODE_WRITE
,
(
unsigned
int
)(
m
->
bits
),
0
);
/* get the current revision from MSR 0x8B
*/
/* serialize
*/
rdmsr
(
MSR_IA32_UCODE_REV
,
val
[
0
],
val
[
1
]
);
__asm__
__volatile__
(
"cpuid"
:
:
:
"ax"
,
"bx"
,
"cx"
,
"dx"
);
/* notify the caller of success on this cpu */
/* get the current revision from MSR 0x8B */
req
->
err
=
0
;
rdmsr
(
MSR_IA32_UCODE_REV
,
val
[
0
],
val
[
1
]);
req
->
slot
=
i
;
printk
(
KERN_INFO
"microcode: CPU%d updated from revision "
/* notify the caller of success on this cpu */
"%d to %d, date=%08x
\n
"
,
req
->
err
=
0
;
cpu_num
,
rev
,
val
[
1
],
m
->
date
);
spin_unlock_irqrestore
(
&
microcode_update_lock
,
flags
);
}
printk
(
KERN_INFO
"microcode: CPU%d updated from revision "
break
;
"%d to %d, date=%08x
\n
"
,
cpu_num
,
rev
,
val
[
1
],
microcode
[
i
].
date
);
return
;
}
}
if
(
!
found
)
printk
(
KERN_ERR
printk
(
KERN_ERR
"microcode: CPU%d no microcode found! (sig=%x, pflags=%d)
\n
"
,
"microcode: CPU%d no microcode found! (sig=%x, pflags=%d)
\n
"
,
cpu_num
,
sig
,
pf
);
cpu_num
,
sig
,
pf
);
}
}
static
ssize_t
microcode_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
static
ssize_t
microcode_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
{
{
ssize_t
ret
=
0
;
ssize_t
ret
=
0
;
...
@@ -305,11 +332,15 @@ static ssize_t microcode_write(struct file *file, const char *buf, size_t len, l
...
@@ -305,11 +332,15 @@ static ssize_t microcode_write(struct file *file, const char *buf, size_t len, l
{
{
ssize_t
ret
;
ssize_t
ret
;
if
(
len
%
sizeof
(
struct
microcode
)
!=
0
)
{
if
(
!
len
||
len
%
sizeof
(
struct
microcode
)
!=
0
)
{
printk
(
KERN_ERR
"microcode: can only write in N*%d bytes units
\n
"
,
printk
(
KERN_ERR
"microcode: can only write in N*%d bytes units
\n
"
,
sizeof
(
struct
microcode
));
sizeof
(
struct
microcode
));
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
((
len
>>
PAGE_SHIFT
)
>
num_physpages
)
{
printk
(
KERN_ERR
"microcode: too much data (max %d pages)
\n
"
,
num_physpages
);
return
-
EINVAL
;
}
down_write
(
&
microcode_rwsem
);
down_write
(
&
microcode_rwsem
);
if
(
!
mc_applied
)
{
if
(
!
mc_applied
)
{
mc_applied
=
kmalloc
(
smp_num_cpus
*
sizeof
(
struct
microcode
),
mc_applied
=
kmalloc
(
smp_num_cpus
*
sizeof
(
struct
microcode
),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment