CCF
Loading...
Searching...
No Matches
sev_snp_cpuid.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include "ccf/ds/hex.h"
6#include "ccf/ds/json.h"
7
8#include <cstdint>
9#include <stdexcept>
10#include <string>
11
12namespace ccf::pal::snp
13{
14
15#pragma pack(push, 1)
16 // AMD CPUID specification. Chapter 2 Fn0000_0001_EAX
17 // Milan: 0x00A00F11
18 // Genoa: 0x00A10F11
19 // Turin: 0x00B00F21
20 // Note: The CPUID is little-endian so the hex_string is reversed
21 struct CPUID
22 {
23 uint8_t stepping : 4;
24 uint8_t base_model : 4;
25 uint8_t base_family : 4;
26 uint8_t reserved : 4;
27 uint8_t extended_model : 4;
28 uint8_t extended_family : 8;
29 uint8_t reserved2 : 4;
30
31 bool operator==(const CPUID&) const = default;
32 [[nodiscard]] std::string hex_str() const
33 {
34 CPUID buf = *this;
35 auto* buf_ptr = reinterpret_cast<uint8_t*>(&buf);
36 const std::span<const uint8_t> tcb_bytes{
37 buf_ptr, buf_ptr + sizeof(CPUID)};
38 return fmt::format(
39 "{:02x}", fmt::join(tcb_bytes.rbegin(), tcb_bytes.rend(), ""));
40 }
41 [[nodiscard]] uint8_t get_family_id() const
42 {
43 return this->base_family + this->extended_family;
44 }
45 [[nodiscard]] uint8_t get_model_id() const
46 {
47 return (this->extended_model << 4) | this->base_model;
48 }
49 };
50#pragma pack(pop)
53 CPUID, stepping, base_model, base_family, extended_model, extended_family);
54 static_assert(
55 sizeof(CPUID) == sizeof(uint32_t), "Cannot cast CPUID to uint32_t");
56 static CPUID cpuid_from_hex(const std::string& hex_str)
57 {
58 CPUID ret{};
59 auto* buf_ptr = reinterpret_cast<uint8_t*>(&ret);
60 ccf::ds::from_hex(hex_str, buf_ptr, buf_ptr + sizeof(CPUID));
61 std::reverse(
62 buf_ptr, buf_ptr + sizeof(CPUID)); // fix little endianness of AMD
63 return ret;
64 }
65
66 // On SEVSNP cpuid cannot be trusted and must later be validated against an
67 // attestation.
68 static CPUID get_cpuid_untrusted()
69 {
70 uint32_t ieax = 1;
71 uint64_t iebx = 0;
72 uint64_t iecx = 0;
73 uint64_t iedx = 0;
74 uint32_t oeax = 0;
75 uint64_t oebx = 0;
76 uint64_t oecx = 0;
77 uint64_t oedx = 0;
78 // pass in e{b,c,d}x to prevent cpuid from blatting other registers
79 asm volatile("cpuid"
80 : "=a"(oeax), "=b"(oebx), "=c"(oecx), "=d"(oedx)
81 : "a"(ieax), "b"(iebx), "c"(iecx), "d"(iedx));
82 auto cpuid = *reinterpret_cast<CPUID*>(&oeax);
83 return cpuid;
84 }
85
86 enum class ProductName : uint8_t
87 {
88 Milan,
89 Genoa,
90 Turin
91 };
92
93 inline std::string to_string(ProductName product)
94 {
95 switch (product)
96 {
98 return "Milan";
100 return "Genoa";
102 return "Turin";
103 default:
104 throw std::logic_error("Unknown SEV-SNP product");
105 }
106 }
107
110 {
111 {ProductName::Milan, "Milan"},
112 {ProductName::Genoa, "Genoa"},
113 {ProductName::Turin, "Turin"},
114 });
115
116 using AMDFamily = uint8_t;
117 using AMDModel = uint8_t;
118
120 {
121 constexpr uint8_t milan_family = 0x19;
122 constexpr uint8_t milan_model = 0x01;
123 if (family == milan_family && model == milan_model)
124 {
125 return ProductName::Milan;
126 }
127 constexpr uint8_t genoa_family = 0x19;
128 constexpr uint8_t genoa_model = 0x11;
129 if (family == genoa_family && model == genoa_model)
130 {
131 return ProductName::Genoa;
132 }
133 constexpr uint8_t turin_family = 0x1A;
134 constexpr uint8_t turin_model = 0x02;
135 if (family == turin_family && model == turin_model)
136 {
137 return ProductName::Turin;
138 }
139 throw std::logic_error(fmt::format(
140 "SEV-SNP: Unsupported CPUID family {} model {}", family, model));
141 }
142
144 {
145 return get_sev_snp_product(cpuid.get_family_id(), cpuid.get_model_id());
146 }
147
148 inline std::string get_cpuid_of_snp_sev_product(ProductName product)
149 {
150 switch (product)
151 {
153 return "00a00f11";
155 return "00a10f11";
157 return "00b00f11";
158 default:
159 throw std::logic_error(fmt::format(
160 "SEV-SNP: Unsupported product for CPUID: {}", to_string(product)));
161 }
162 }
163}
#define DECLARE_JSON_REQUIRED_FIELDS(TYPE,...)
Definition json.h:718
#define DECLARE_JSON_TYPE(TYPE)
Definition json.h:667
#define DECLARE_JSON_ENUM(TYPE,...)
Definition json.h:841
Definition attestation_sev_snp.h:24
std::string to_string(ProductName product)
Definition sev_snp_cpuid.h:93
uint8_t AMDModel
Definition sev_snp_cpuid.h:117
ProductName get_sev_snp_product(AMDFamily family, AMDModel model)
Definition sev_snp_cpuid.h:119
uint8_t AMDFamily
Definition sev_snp_cpuid.h:116
ProductName
Definition sev_snp_cpuid.h:87
std::string get_cpuid_of_snp_sev_product(ProductName product)
Definition sev_snp_cpuid.h:148
Definition sev_snp_cpuid.h:22
uint8_t get_family_id() const
Definition sev_snp_cpuid.h:41
uint8_t extended_model
Definition sev_snp_cpuid.h:27
uint8_t extended_family
Definition sev_snp_cpuid.h:28
std::string hex_str() const
Definition sev_snp_cpuid.h:32
uint8_t base_family
Definition sev_snp_cpuid.h:25
uint8_t get_model_id() const
Definition sev_snp_cpuid.h:45
uint8_t reserved
Definition sev_snp_cpuid.h:26
bool operator==(const CPUID &) const =default
uint8_t stepping
Definition sev_snp_cpuid.h:23
uint8_t base_model
Definition sev_snp_cpuid.h:24
uint8_t reserved2
Definition sev_snp_cpuid.h:29