Skip to content

Commit 9f4b048

Browse files
committed
indexed smn
Add commands to read/write other SMN pairs, so that we can try and access things like HSMP. Signed-off-by: Dan Cross <cross@oxidecomputer.com>
1 parent 078a5bc commit 9f4b048

6 files changed

Lines changed: 102 additions & 16 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,12 @@ Supported commands include:
243243
sizes, issue mulitple `unmap` calls.
244244
* `rdsmn <addr>` to read a 32-bit word from the given SMN
245245
address.
246+
* `rdsmni <index> <addr>` like `rdsmn`, but using a specific
247+
address/data register pair.
246248
* `wrsmn <addr> <value>` to write a 32-bit word to the given SMN
247249
address.
250+
* `wrsmni <index> <addr>` like `wrsmn`, but using a spcecific
251+
address/data register pair.
248252
* `cpuid <leaf> <subleaf>` to return the results of the `CPUID`
249253
instruction for the given leaf and subleaf.
250254
* `ecamrd <b/d/f> <offset>` read a 32-bit word from PCIe

src/repl/ecam.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub(super) fn read(
2929
env: &mut Vec<repl::Value>,
3030
) -> Result<repl::Value> {
3131
let usage = |error| {
32-
println!("usage: ecamrd <addr>");
32+
println!("usage: ecamrd b/d/f <offset>");
3333
error
3434
};
3535
let (bus, dev, func) = repl::popenv(env)
@@ -57,7 +57,7 @@ pub(super) fn write(
5757
env: &mut Vec<repl::Value>,
5858
) -> Result<repl::Value> {
5959
let usage = |error| {
60-
println!("usage: ecamwr <addr> <value>");
60+
println!("usage: ecamwr b/d/f <offset> <value>");
6161
error
6262
};
6363
let (bus, dev, func) = repl::popenv(env)

src/repl/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ fn evalcmd(
264264
"push" => Ok(Value::Nil),
265265
"rdmsr" => msr::read(config, env),
266266
"rdsmn" => smn::read(config, env),
267+
"rdsmni" => smn::rdsmni(config, env),
267268
"rx" => rx::run(config, env),
268269
"rz" => rz::run(config, env),
269270
"setbits" => bits::set(config, env),
@@ -274,6 +275,7 @@ fn evalcmd(
274275
"umount" => mount::umount(config, env),
275276
"wrmsr" => msr::write(config, env),
276277
"wrsmn" => smn::write(config, env),
278+
"wrsmni" => smn::wrsmni(config, env),
277279
_ => Err(Error::NoCommand),
278280
}
279281
}

src/repl/reader.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,12 @@ Supported commands include:
443443
sizes, issue mulitple `unmap` calls.
444444
* `rdsmn <addr>` to read a 32-bit word from the given SMN
445445
address.
446+
* `rdsmni <index> <addr>` like `rdsmn`, but using a specific
447+
address/data register pair.
446448
* `wrsmn <addr> <value>` to write a 32-bit word to the given SMN
447449
address.
450+
* `wrsmni <index> <addr>` like `wrsmn`, but using a spcecific
451+
address/data register pair.
448452
* `cpuid <leaf> <subleaf>` to return the results of the `CPUID`
449453
instruction for the given leaf and subleaf.
450454
* `ecamrd <b/d/f> <offset>` read a 32-bit word from PCIe

src/repl/smn.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(super) fn read(
1818
error
1919
};
2020
let addr = repl::popenv(env).as_num::<u32>().map_err(usage)?;
21-
let data = smn::read(addr).map_err(usage)?;
21+
let data = smn::read(smn::Index::Smn0, addr).map_err(usage)?;
2222
println!("{addr:#x} {data:#x}");
2323
Ok(repl::Value::Unsigned(data.into()))
2424
}
@@ -34,7 +34,45 @@ pub(super) fn write(
3434
let addr = repl::popenv(env).as_num::<u32>().map_err(usage)?;
3535
let value = repl::popenv(env).as_num::<u32>().map_err(usage)?;
3636
unsafe {
37-
smn::write(addr, value)?;
37+
smn::write(smn::Index::Smn0, addr, value)?;
38+
}
39+
Ok(repl::Value::Nil)
40+
}
41+
42+
pub(super) fn rdsmni(
43+
_config: &mut bldb::Config,
44+
env: &mut Vec<repl::Value>,
45+
) -> Result<repl::Value> {
46+
let usage = |error| {
47+
println!("usage: rdsmni <index> <addr>");
48+
error
49+
};
50+
let index = repl::popenv(env)
51+
.as_num::<u8>()
52+
.and_then(smn::Index::try_from)
53+
.map_err(usage)?;
54+
let addr = repl::popenv(env).as_num::<u32>().map_err(usage)?;
55+
let data = smn::read(index, addr).map_err(usage)?;
56+
println!("{addr:#x} {data:#x}");
57+
Ok(repl::Value::Unsigned(data.into()))
58+
}
59+
60+
pub(super) fn wrsmni(
61+
_config: &mut bldb::Config,
62+
env: &mut Vec<repl::Value>,
63+
) -> Result<repl::Value> {
64+
let usage = |error| {
65+
println!("usage: wrsmni <index> <addr> <value>");
66+
error
67+
};
68+
let index = repl::popenv(env)
69+
.as_num::<u8>()
70+
.and_then(smn::Index::try_from)
71+
.map_err(usage)?;
72+
let addr = repl::popenv(env).as_num::<u32>().map_err(usage)?;
73+
let value = repl::popenv(env).as_num::<u32>().map_err(usage)?;
74+
unsafe {
75+
smn::write(index, addr, value)?;
3876
}
3977
Ok(repl::Value::Nil)
4078
}

src/smn.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,85 @@
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

55
use crate::pci;
6-
use crate::result::Result;
6+
use crate::result::{Error, Result};
7+
use core::convert::TryFrom;
8+
use spin::Mutex;
79

8-
static SMN_MUTEX: spin::Mutex<()> = spin::Mutex::new(());
9-
const SMN_ADDR_OFFSET: u8 = 0x60;
10-
const SMN_DATA_OFFSET: u8 = 0x64;
10+
pub(crate) enum Index {
11+
Smn0 = 0,
12+
Smn1 = 1,
13+
Smn2 = 2,
14+
Smn3 = 3,
15+
Smn4 = 4,
16+
Smn5 = 5,
17+
Smn6 = 6,
18+
}
19+
20+
impl TryFrom<u8> for Index {
21+
type Error = Error;
22+
fn try_from(f: u8) -> Result<Self> {
23+
match f {
24+
0 => Ok(Index::Smn0),
25+
1 => Ok(Index::Smn1),
26+
2 => Ok(Index::Smn2),
27+
3 => Ok(Index::Smn3),
28+
4 => Ok(Index::Smn4),
29+
5 => Ok(Index::Smn5),
30+
6 => Ok(Index::Smn6),
31+
_ => Err(Error::NumRange),
32+
}
33+
}
34+
}
35+
36+
const NSMN: usize = Index::Smn6 as usize + 1;
37+
38+
static ADDR_DATA_PAIRS: [spin::Mutex<(u8, u8)>; NSMN] = [
39+
Mutex::new((0x60, 0x64)),
40+
Mutex::new((0xA0, 0xA4)),
41+
Mutex::new((0xB8, 0xBC)),
42+
Mutex::new((0xC4, 0xC8)),
43+
Mutex::new((0xD0, 0xD4)),
44+
Mutex::new((0xE0, 0xE4)),
45+
Mutex::new((0xF8, 0xFC)),
46+
];
1147

12-
pub(crate) fn read(addr: u32) -> Result<u32> {
13-
let _lock = SMN_MUTEX.lock();
48+
pub(crate) fn read(k: Index, addr: u32) -> Result<u32> {
49+
let pair = ADDR_DATA_PAIRS[k as usize].lock();
50+
let (addr_off, data_off) = *pair;
1451
let value = unsafe {
1552
pci::cfg::write(
1653
pci::Bus(0),
1754
pci::Device::D0,
1855
pci::Function::F0,
19-
SMN_ADDR_OFFSET,
56+
addr_off,
2057
addr,
2158
)?;
2259
pci::cfg::read(
2360
pci::Bus(0),
2461
pci::Device::D0,
2562
pci::Function::F0,
26-
SMN_DATA_OFFSET,
63+
data_off,
2764
)
2865
}?;
2966
Ok(value)
3067
}
3168

32-
pub(crate) unsafe fn write(addr: u32, data: u32) -> Result<()> {
33-
let _lock = SMN_MUTEX.lock();
69+
pub(crate) unsafe fn write(k: Index, addr: u32, data: u32) -> Result<()> {
70+
let pair = ADDR_DATA_PAIRS[k as usize].lock();
71+
let (addr_off, data_off) = *pair;
3472
unsafe {
3573
pci::cfg::write(
3674
pci::Bus(0),
3775
pci::Device::D0,
3876
pci::Function::F0,
39-
SMN_ADDR_OFFSET,
77+
addr_off,
4078
addr,
4179
)?;
4280
pci::cfg::write(
4381
pci::Bus(0),
4482
pci::Device::D0,
4583
pci::Function::F0,
46-
SMN_DATA_OFFSET,
84+
data_off,
4785
data,
4886
)?;
4987
}

0 commit comments

Comments
 (0)