Lưu ý
Mục đích của file này là để độc giả tiếng Việt có thể đọc và hiểu tài liệu nhân kernel dễ dàng hơn, không phải để tạo ra một nhánh tài liệu riêng. Nếu bạn có bất kỳ nhận xét hoặc cập nhật nào cho file này, vui lòng thử cập nhật file tiếng Anh gốc trước. Nếu bạn thấy có sự khác biệt giữa bản dịch và bản gốc, hoặc có vấn đề về bản dịch, vui lòng gửi góp ý hoặc patch cho người dịch của file này, hoặc nhờ người bảo trì và người review tài liệu tiếng Việt giúp đỡ.
- Bản gốc:
- Người dịch:
Google Translate (machine translation)
- Phiên bản gốc:
8541d8f725c6
Cảnh báo
Tài liệu này được dịch tự động bằng máy và chưa được review bởi người dịch. Nội dung có thể không chính xác hoặc khó hiểu ở một số chỗ. Khi có sự khác biệt với bản gốc, bản gốc luôn là chuẩn. Bản dịch chất lượng cao (được review) được đặt trong thư mục vi_VN/.
KVM lồng nhau trên POWER¶
Giới thiệu¶
Tài liệu này giải thích cách một hệ điều hành khách có thể hoạt động như một hypervisor và chạy các máy khách lồng nhau thông qua việc sử dụng hypercalls, nếu hypervisor đã triển khai chúng. Các thuật ngữ L0, L1 và L2 được sử dụng để đề cập đến các thực thể phần mềm khác nhau. L0 là thực thể chế độ ảo hóa thường được gọi là “máy chủ” hoặc “máy ảo hóa”. L1 là một máy ảo khách được chạy trực tiếp dưới L0 và được khởi tạo và được điều khiển bởi L0. L2 là một máy ảo khách được khởi tạo và được điều khiển bởi L1 hoạt động như một bộ ảo hóa.
API hiện có¶
Linux/KVM đã hỗ trợ Nesting dưới dạng L0 hoặc L1 kể từ năm 2018
Mã L0 đã được thêm vào:
- cam kết 8e3f5fc1045dc49fd175b978c5457f5f51e7a2ce
Tác giả: Paul Mackerras <paulus@ozlabs.org> Ngày: Thứ Hai ngày 8 tháng 10 16:31:03 2018 +1100 KVM: PPC: Book3S HV: Sơ khai khung và hcall cho ảo hóa lồng nhau
Mã L1 đã được thêm vào:
- cam kết 360cae313702cdd0b90f82c261a8302fecef030a
Tác giả: Paul Mackerras <paulus@ozlabs.org> Ngày: Thứ Hai ngày 8 tháng 10 16:31:04 2018 +1100 KVM: PPC: Book3S HV: Mục nhập của khách lồng nhau thông qua hypercall
API này hoạt động chủ yếu bằng cách sử dụng một hcall h_enter_nested(). Cái này
lệnh gọi do L1 thực hiện để báo cho L0 khởi động vCPU L2 với thông số đã cho
trạng thái. L0 sau đó khởi động L2 này và chạy cho đến khi có điều kiện thoát L2
đã đạt được. Khi L2 thoát ra, trạng thái của L2 được trả lại cho
L1 bằng L0. Trạng thái vCPU L2 đầy đủ luôn được chuyển từ
và tới L1 khi L2 được chạy. L0 không giữ bất kỳ trạng thái nào trên L2
vCPU (ngoại trừ dãy ngắn ở L0 trên L1 -> L2 entry và L2
-> Lối ra L1).
Trạng thái duy nhất được L0 giữ là bảng phân vùng. Các thanh ghi L1
đó là bảng phân vùng sử dụng hcall h_set_partition_table(). Tất cả
trạng thái khác do L0 nắm giữ về L2 là trạng thái được lưu trong bộ nhớ đệm (chẳng hạn như
bảng trang bóng).
L1 có thể chạy bất kỳ L2 hoặc vCPU nào mà không cần thông báo trước cho L0. Nó
chỉ cần khởi động vCPU bằng h_enter_nested(). Việc tạo ra L2 và
vCPU được thực hiện ngầm bất cứ khi nào h_enter_nested() được gọi.
Trong tài liệu này, chúng tôi gọi API hiện có này là API v1.
PAPR API mới¶
PAPR API mới thay đổi từ v1 API sao cho việc tạo L2 và vCPU liên quan là rõ ràng. Trong tài liệu này, chúng tôi gọi đây là v2 API.
h_enter_nested() được thay thế bằng H_GUEST_VCPU_RUN(). Trước khi điều này có thể
được gọi là L1 phải tạo L2 một cách rõ ràng bằng cách sử dụng h_guest_create()
và mọi vCPU() liên quan được tạo bằng h_guest_create_vCPU(). Bắt
và việc thiết lập trạng thái vCPU cũng có thể được thực hiện bằng cách sử dụng h_guest_{g|s}et
hcall.
Luồng thực thi cơ bản là để L1 tạo L2, chạy nó và xóa nó là:
Khả năng đàm phán L1 và L0 với H_GUEST_{G,S}
ET_CAPABILITIES()(thông thường ở thời điểm khởi động L1).L1 yêu cầu L0 tạo L2 với
H_GUEST_CREATE()và nhận mã thông báoL1 yêu cầu L0 tạo vCPU L2 với
H_GUEST_CREATE_VCPU()L1 và L0 truyền đạt trạng thái vCPU bằng cách sử dụng hcall H_GUEST_{G,S}
ET()L1 yêu cầu L0 chạy vCPU chạy
H_GUEST_VCPU_RUN()hcallL1 xóa L2 bằng
H_GUEST_DELETE()
Thông tin chi tiết về các hcalls riêng lẻ như sau:
Chi tiết HCALL¶
Tài liệu này được cung cấp để cung cấp một cách hiểu tổng thể về API. Nó không nhằm mục đích cung cấp tất cả các chi tiết cần thiết để thực hiện L1 hoặc L0. Phiên bản mới nhất của PAPR có thể tham khảo để biết thêm chi tiết.
Tất cả các HCALL này được tạo bởi L1 đến L0.
H_GUEST_GET_CAPABILITIES()¶
Điều này được gọi để có được khả năng của L0 lồng nhau siêu giám sát. Điều này bao gồm các khả năng như phiên bản CPU (ví dụ: POWER9, POWER10) được hỗ trợ dưới dạng L2:
H_GUEST_GET_CAPABILITIES(cờ uint64)
- Thông số:
- đầu vào:
cờ: Dành riêng
- Đầu ra:
R3: Mã trả về R4: Bitmap khả năng được hỗ trợ của Hypervisor 1
H_GUEST_SET_CAPABILITIES()¶
Điều này được gọi để thông báo cho L0 về khả năng của L1
siêu giám sát. Bộ cờ được truyền ở đây giống như
H_GUEST_GET_CAPABILITIES()
Thông thường, GET sẽ được gọi đầu tiên và sau đó SET sẽ được gọi với tập hợp con của các cờ được trả về từ GET. Quá trình này cho phép L0 và L1 để đàm phán một tập hợp các khả năng đã được thống nhất:
- H_GUEST_SET_CAPABILITIES(cờ uint64,
khả năng của uint64Bitmap1)
- Thông số:
- đầu vào:
cờ: Dành riêng khả năngBitmap1: Chỉ các khả năng được quảng cáo thông qua
H_GUEST_GET_CAPABILITIES
- Đầu ra:
R3: Mã trả về R4: Nếu R3 = H_P2: Số lượng bitmap không hợp lệ R5: Nếu R3 = H_P2: Chỉ số của bitmap không hợp lệ đầu tiên
H_GUEST_CREATE()¶
Điều này được gọi để tạo L2. Một ID duy nhất của L2 đã được tạo (tương tự như LPID) được trả về, có thể được sử dụng trên các HCALL tiếp theo để xác định L2:
- H_GUEST_CREATE(cờ uint64,
uint64 continueToken);
- Thông số:
- đầu vào:
cờ: Dành riêng continueToken: Cuộc gọi ban đầu được đặt thành -1. Những cuộc gọi tiếp theo,
sau khi H_Busy hoặc H_LongBusyOrder đã được được trả về, giá trị được trả về trong R4.
- Đầu ra:
- R3: Mã trả về. Đáng chú ý:
H_Not_Enough_Resources: Không thể tạo Khách VCPU do không đủ bộ nhớ Hypervisor. Xem H_GUEST_CREATE_GET_STATE(cờ = takeOwnershipOfVcpuState)
R4: Nếu R3 = H_Busy hoặc_H_LongBusyOrder -> continueToken
H_GUEST_CREATE_VCPU()¶
Lệnh này được gọi để tạo vCPU được liên kết với L2. Mã L2
(được trả về từ H_GUEST_CREATE()) nên được thông qua. Cũng đã đậu vào
là một vCPUid duy nhất (cho L2 này). vCPUid này được phân bổ bởi
L1:
- H_GUEST_CREATE_VCPU(cờ uint64,
id khách uint64, uint64 vcpuId);
- Thông số:
- đầu vào:
cờ: Dành riêng guestId: ID thu được từ H_GUEST_CREATE vcpuId: ID của vCPU cần tạo. Điều này phải nằm trong
phạm vi từ 0 đến 2047
- Đầu ra:
- R3: Mã trả về. Đáng chú ý:
H_Not_Enough_Resources: Không thể tạo Khách VCPU do không đủ bộ nhớ Hypervisor. Xem H_GUEST_CREATE_GET_STATE(cờ = takeOwnershipOfVcpuState)
H_GUEST_GET_STATE()¶
Lệnh này được gọi để lấy trạng thái liên kết với L2 (Dành riêng cho khách hoặc vCPU). Thông tin này được truyền qua Bộ đệm trạng thái khách (GSB), một định dạng chuẩn như được giải thích sau trong tài liệu này, các chi tiết cần thiết bên dưới:
Điều này có thể nhận được thông tin cụ thể về L2 hoặc vcpu. Ví dụ về Chiều rộng L2 là phần bù cơ sở thời gian hoặc bảng trang trong phạm vi quy trình thông tin. Ví dụ về vCPU cụ thể là GPR hoặc VSR. Một chút trong những lá cờ tham số chỉ định lệnh gọi này có phạm vi rộng L2 hay vCPU cụ thể và ID trong GSB phải khớp với điều này.
L1 cung cấp một con trỏ tới GSB làm tham số cho lệnh gọi này. Ngoài ra được cung cấp là ID L2 và vCPU được liên kết với trạng thái cần đặt.
L1 chỉ ghi ID và kích thước trong GSB. L0 viết các giá trị liên quan cho mỗi ID trong GSB:
- H_GUEST_GET_STATE(cờ uint64,
id khách uint64, uint64 vcpuId, Bộ đệm dữ liệu uint64, uint64 dataBufferSizeInBytes);
- Thông số:
- đầu vào:
- cờ:
- Bit 0: getGuestWideState: Thay vào đó yêu cầu trạng thái của Khách
của một cá nhân VCPU.
- Bit 1: getHostWideState: Yêu cầu số liệu thống kê của Host. Điều này gây ra
các tham số guestId và vcpuId bị bỏ qua và đang cố gắng để có trạng thái VCPU/Khách sẽ gây ra lỗi.
Bit 2-63: Dành riêng
guestId: ID thu được từ H_GUEST_CREATE vcpuId: ID của vCPU chuyển tới H_GUEST_CREATE_VCPU dataBuffer: Địa chỉ thực L1 của GSB.
Nếu takeOwnershipOfVcpuState, kích thước tối thiểu phải bằng kích thước được trả về bởi ID=0x0001
dataBufferSizeInBytes: Kích thước của dataBuffer
- Đầu ra:
R3: Mã trả về R4: Nếu R3 = H_Invalid_Element_Id: Chỉ số mảng của lỗi
ID phần tử.
- Nếu R3 = H_Invalid_Element_Size: Chỉ số mảng của lỗi
kích thước phần tử.
- Nếu R3 = H_Invalid_Element_Value: Chỉ số mảng của lỗi
giá trị phần tử.
H_GUEST_SET_STATE()¶
Lệnh này được gọi để đặt trạng thái L2 rộng của L2 hoặc trạng thái L2 cụ thể của vCPU. Thông tin này là được chuyển qua Bộ đệm trạng thái khách (GSB), các chi tiết cần thiết bên dưới:
Điều này có thể đặt thông tin cụ thể về L2 hoặc vcpu. Ví dụ về Chiều rộng L2 là phần bù cơ sở thời gian hoặc bảng trang trong phạm vi quy trình thông tin. Ví dụ về vCPU cụ thể là GPR hoặc VSR. Một chút trong những lá cờ tham số chỉ định lệnh gọi này có phạm vi rộng L2 hay vCPU cụ thể và ID trong GSB phải khớp với điều này.
L1 cung cấp một con trỏ tới GSB làm tham số cho lệnh gọi này. Ngoài ra được cung cấp là ID L2 và vCPU được liên kết với trạng thái cần đặt.
L1 ghi tất cả các giá trị trong GSB và L0 chỉ đọc GSB cho cuộc gọi này:
- H_GUEST_SET_STATE(cờ uint64,
id khách uint64, uint64 vcpuId, Bộ đệm dữ liệu uint64, uint64 dataBufferSizeInBytes);
- Thông số:
- đầu vào:
- cờ:
- Bit 0: getGuestWideState: Thay vào đó yêu cầu trạng thái của Khách
của một cá nhân VCPU.
- Bit 1: returnOwnershipOfVcpuState Trả về trạng thái Guest VCPU. Xem
GET_STATE takeOwnershipOfVcpuState
Bit 2-63: Dành riêng
guestId: ID thu được từ H_GUEST_CREATE vcpuId: ID của vCPU chuyển tới H_GUEST_CREATE_VCPU dataBuffer: Địa chỉ thực L1 của GSB.
Nếu takeOwnershipOfVcpuState, kích thước tối thiểu phải bằng kích thước được trả về bởi ID=0x0001
dataBufferSizeInBytes: Kích thước của dataBuffer
- Đầu ra:
R3: Mã trả về R4: Nếu R3 = H_Invalid_Element_Id: Chỉ số mảng của lỗi
ID phần tử.
- Nếu R3 = H_Invalid_Element_Size: Chỉ số mảng của lỗi
kích thước phần tử.
- Nếu R3 = H_Invalid_Element_Value: Chỉ số mảng của lỗi
giá trị phần tử.
H_GUEST_RUN_VCPU()¶
Lệnh này được gọi để chạy vCPU L2. ID L2 và vCPU được chuyển vào dưới dạng
các thông số. vCPU chạy với trạng thái được đặt trước đó bằng cách sử dụng
H_GUEST_SET_STATE(). Khi L2 thoát ra, L1 sẽ tiếp tục từ đây
hcall.
hcall này cũng có GSB đầu vào và đầu ra liên quan. Không giống
H_GUEST_{S,G}ET_STATE(), các con trỏ GSB này không được truyền vào dưới dạng
tham số cho hcall (Điều này được thực hiện vì lợi ích của
hiệu suất). Vị trí của các GSB này phải được đăng ký trước bằng cách sử dụng
cuộc gọi H_GUEST_SET_STATE() với ID 0x0c00 và 0x0c01 (xem bảng
bên dưới).
Đầu vào GSB chỉ có thể chứa các phần tử cụ thể VCPU cần được đặt. Cái này GSB cũng có thể chứa các phần tử bằng 0 (tức là 0 trong 4 byte đầu tiên của GSB) nếu không cần thiết lập gì.
Khi thoát khỏi hcall, bộ đệm đầu ra chứa đầy các phần tử
được xác định bởi L0. Lý do thoát được chứa trong GPR4 (tức là
NIP được đặt trong GPR4). Các phần tử được trả về phụ thuộc vào lối ra
loại. Ví dụ: nếu lý do thoát là L2 đang thực hiện hcall (GPR4 =
0xc00), thì GPR3-12 được cung cấp trong đầu ra GSB vì đây là
trạng thái có thể cần thiết để phục vụ hcall. Nếu trạng thái bổ sung là
cần thiết, H_GUEST_GET_STATE() có thể được gọi bởi L1.
Để tổng hợp các ngắt trong L2, khi gọi H_GUEST_RUN_VCPU()
L1 có thể đặt cờ (dưới dạng tham số hcall) và L0 sẽ
tổng hợp ngắt trong L2. Ngoài ra, L1 có thể
tự tổng hợp ngắt bằng cách sử dụng H_GUEST_SET_STATE() hoặc
H_GUEST_RUN_VCPU() nhập GSB để đặt trạng thái phù hợp:
- H_GUEST_RUN_VCPU(cờ uint64,
id khách uint64, uint64 vcpuId, Bộ đệm dữ liệu uint64, uint64 dataBufferSizeInBytes);
- Thông số:
- đầu vào:
- cờ:
Bit 0: generateExternalInterrupt: Tạo ngắt ngoài Bit 1: generatePrivilegedDoorbell: Tạo chuông cửa đặc quyền Bit 2: sendToSystemReset”: Tạo ngắt thiết lập lại hệ thống Bit 3-63: Dành riêng
guestId: ID thu được từ H_GUEST_CREATE vcpuId: ID của vCPU chuyển tới H_GUEST_CREATE_VCPU
- Đầu ra:
R3: Mã trả về R4: Nếu R3 = H_Success: Lý do L1 VCPU thoát (tức là NIA)
- 0x000: VCPU ngừng chạy vì lý do không xác định. Một
ví dụ về điều này là Hypervisor dừng VCPU đang chạy do sự gián đoạn chưa xảy ra đối với Phân vùng máy chủ.
0x980: HDEC 0xC00: HCALL 0xE00: HDSI 0xE20: HISI 0xE40: HEA 0xF80: Mặt HV không có sẵn
- Nếu R3 = H_Invalid_Element_Id, H_Invalid_Element_Size, hoặc
H_Invalid_Element_Value: R4 là phần bù của phần tử không hợp lệ trong bộ đệm đầu vào.
H_GUEST_DELETE()¶
Lệnh này được gọi để xóa L2. Tất cả các vCPU liên quan cũng đã xóa. Không có lệnh gọi xóa vCPU cụ thể nào được cung cấp.
Một lá cờ có thể được cung cấp để xóa tất cả khách. Điều này được sử dụng để thiết lập lại L0 trong trường hợp kdump/kexec:
- H_GUEST_DELETE(cờ uint64,
uint64 guestId)
- Thông số:
- đầu vào:
- cờ:
Bit 0: deleteAllGuests: xóa tất cả khách Bit 1-63: Dành riêng
guestId: ID thu được từ H_GUEST_CREATE
- Đầu ra:
R3: Mã trả về
Bộ đệm trạng thái khách¶
Bộ đệm trạng thái khách (GSB) là phương thức chính để truyền đạt trạng thái
về L2 giữa L1 và L0 thông qua H_GUEST_{G,S}ET() và
Cuộc gọi H_GUEST_VCPU_RUN().
Trạng thái có thể được liên kết với toàn bộ L2 (ví dụ: phần bù cơ sở thời gian) hoặc một
vCPU L2 cụ thể (ví dụ: trạng thái GPR). Chỉ trạng thái L2 VCPU có thể được đặt bởi
H_GUEST_VCPU_RUN().
Tất cả dữ liệu trong GSB đều ở dạng big endian (như tiêu chuẩn trong PAPR)
Bộ đệm trạng thái Khách có tiêu đề cung cấp số lượng các phần tử, theo sau là các phần tử GSB.
Tiêu đề GSB:
ZZ0000ZZ Kích thước ZZ0001ZZ ZZ0002ZZ Byte ZZ0003ZZ +===========+================================================================================================================================ ZZ0004ZZ 4 ZZ0005ZZ +----------+----------+---------------------------------------------+ ZZ0006ZZ ZZ0007ZZ +----------+----------+---------------------------------------------+
Phần tử GSB:
ZZ0000ZZ Kích thước ZZ0001ZZ ZZ0002ZZ Byte ZZ0003ZZ +===========+================================================================================================================================ ZZ0004ZZ 2 ZZ0005ZZ +----------+----------+---------------------------------------------+ ZZ0006ZZ 2 ZZ0007ZZ +----------+----------+---------------------------------------------+ ZZ0008ZZ Như trên ZZ0009ZZ +----------+----------+---------------------------------------------+
ID trong phần tử GSB chỉ định những gì sẽ được đặt. Điều này bao gồm trạng thái được kiến trúc như GPR, VSR, SPR, cùng với một số siêu dữ liệu về phân vùng giống như trang bù trừ cơ sở dữ liệu thời gian và trang có phạm vi phân vùng thông tin bảng.
ID |
Size Bytes |
RW |
(H)ost (G)uest (T)hread Scope |
Details |
|---|---|---|---|---|
0x0000 |
RW |
TG |
NOP element |
|
0x0001 |
0x08 |
R |
G |
Size of L0 vCPU state. See: H_GUEST_GET_STATE: flags = takeOwnershipOfVcpuState |
0x0002 |
0x08 |
R |
G |
Size Run vCPU out buffer |
0x0003 |
0x04 |
RW |
G |
Logical PVR |
0x0004 |
0x08 |
RW |
G |
TB Offset (L1 relative) |
0x0005 |
0x18 |
RW |
G |
Partition scoped page tbl info:
|
0x0006 |
0x10 |
RW |
G |
Process Table Information:
|
0x0007- 0x07FF |
Reserved |
|||
0x0800 |
0x08 |
R |
H |
Current usage in bytes of the L0’s Guest Management Space for an L1-Lpar. |
0x0801 |
0x08 |
R |
H |
Max bytes available in the L0’s Guest Management Space for an L1-Lpar |
0x0802 |
0x08 |
R |
H |
Current usage in bytes of the L0’s Guest Page Table Management Space for an L1-Lpar |
0x0803 |
0x08 |
R |
H |
Max bytes available in the L0’s Guest Page Table Management Space for an L1-Lpar |
0x0804 |
0x08 |
R |
H |
Cumulative Reclaimed bytes from L0 Guest’s Page Table Management Space due to overcommit |
0x0805- 0x0BFF |
Reserved |
|||
0x0C00 |
0x10 |
RW |
T |
Run vCPU Input Buffer:
|
0x0C01 |
0x10 |
RW |
T |
Run vCPU Output Buffer:
|
0x0C02 |
0x08 |
RW |
T |
vCPU VPA Address |
0x0C03- 0x0FFF |
Reserved |
|||
0x1000- 0x101F |
0x08 |
RW |
T |
GPR 0-31 |
0x1020 |
0x08 |
T |
T |
HDEC expiry TB |
0x1021 |
0x08 |
RW |
T |
NIA |
0x1022 |
0x08 |
RW |
T |
MSR |
0x1023 |
0x08 |
RW |
T |
LR |
0x1024 |
0x08 |
RW |
T |
XER |
0x1025 |
0x08 |
RW |
T |
CTR |
0x1026 |
0x08 |
RW |
T |
CFAR |
0x1027 |
0x08 |
RW |
T |
SRR0 |
0x1028 |
0x08 |
RW |
T |
SRR1 |
0x1029 |
0x08 |
RW |
T |
DAR |
0x102A |
0x08 |
RW |
T |
DEC expiry TB |
0x102B |
0x08 |
RW |
T |
VTB |
0x102C |
0x08 |
RW |
T |
LPCR |
0x102D |
0x08 |
RW |
T |
HFSCR |
0x102E |
0x08 |
RW |
T |
FSCR |
0x102F |
0x08 |
RW |
T |
FPSCR |
0x1030 |
0x08 |
RW |
T |
DAWR0 |
0x1031 |
0x08 |
RW |
T |
DAWR1 |
0x1032 |
0x08 |
RW |
T |
CIABR |
0x1033 |
0x08 |
RW |
T |
PURR |
0x1034 |
0x08 |
RW |
T |
SPURR |
0x1035 |
0x08 |
RW |
T |
IC |
0x1036- 0x1039 |
0x08 |
RW |
T |
SPRG 0-3 |
0x103A |
0x08 |
W |
T |
PPR |
0x103B 0x103E |
0x08 |
RW |
T |
MMCR 0-3 |
0x103F |
0x08 |
RW |
T |
MMCRA |
0x1040 |
0x08 |
RW |
T |
SIER |
0x1041 |
0x08 |
RW |
T |
SIER 2 |
0x1042 |
0x08 |
RW |
T |
SIER 3 |
0x1043 |
0x08 |
RW |
T |
BESCR |
0x1044 |
0x08 |
RW |
T |
EBBHR |
0x1045 |
0x08 |
RW |
T |
EBBRR |
0x1046 |
0x08 |
RW |
T |
AMR |
0x1047 |
0x08 |
RW |
T |
IAMR |
0x1048 |
0x08 |
RW |
T |
AMOR |
0x1049 |
0x08 |
RW |
T |
UAMOR |
0x104A |
0x08 |
RW |
T |
SDAR |
0x104B |
0x08 |
RW |
T |
SIAR |
0x104C |
0x08 |
RW |
T |
DSCR |
0x104D |
0x08 |
RW |
T |
TAR |
0x104E |
0x08 |
RW |
T |
DEXCR |
0x104F |
0x08 |
RW |
T |
HDEXCR |
0x1050 |
0x08 |
RW |
T |
HASHKEYR |
0x1051 |
0x08 |
RW |
T |
HASHPKEYR |
0x1052 |
0x08 |
RW |
T |
CTRL |
0x1053 |
0x08 |
RW |
T |
DPDES |
0x1054- 0x1FFF |
Reserved |
|||
0x2000 |
0x04 |
RW |
T |
CR |
0x2001 |
0x04 |
RW |
T |
PIDR |
0x2002 |
0x04 |
RW |
T |
DSISR |
0x2003 |
0x04 |
RW |
T |
VSCR |
0x2004 |
0x04 |
RW |
T |
VRSAVE |
0x2005 |
0x04 |
RW |
T |
DAWRX0 |
0x2006 |
0x04 |
RW |
T |
DAWRX1 |
0x2007- 0x200c |
0x04 |
RW |
T |
PMC 1-6 |
0x200D |
0x04 |
RW |
T |
WORT |
0x200E |
0x04 |
RW |
T |
PSPB |
0x200F- 0x2FFF |
Reserved |
|||
0x3000- 0x303F |
0x10 |
RW |
T |
VSR 0-63 |
0x3040- 0xEFFF |
Reserved |
|||
0xF000 |
0x08 |
R |
T |
HDAR |
0xF001 |
0x04 |
R |
T |
HDSISR |
0xF002 |
0x04 |
R |
T |
HEIR |
0xF003 |
0x08 |
R |
T |
ASDR |
Thông tin khác¶
Trạng thái không có trong ptregs/hvregs¶
Trong v1 API, một số trạng thái không có trong ptregs/hvstate. Điều này bao gồm
thanh ghi vector và một số SPR. Để L1 thiết lập trạng thái này cho
L2, L1 tải các thanh ghi phần cứng này trước
h_enter_nested() và L0 đảm bảo chúng kết thúc ở trạng thái L2
(bằng cách không chạm vào chúng).
Phiên bản v2 API loại bỏ điều này và đặt trạng thái này một cách rõ ràng thông qua GSB.
Chi tiết triển khai L1: Trạng thái bộ nhớ đệm¶
Trong v1 API, tất cả trạng thái được gửi từ L1 đến L0 và ngược lại
trên mỗi h_enter_nested() hcall. Nếu L0 hiện không chạy
bất kỳ L2 nào, L0 không có thông tin trạng thái về chúng. duy nhất
ngoại lệ ở đây là vị trí của bảng phân vùng, đã đăng ký
thông qua h_set_partition_table().
v2 API thay đổi điều này để L0 giữ lại trạng thái L2 ngay cả khi đó là vCPU không còn chạy nữa. Điều này có nghĩa là L1 chỉ cần liên lạc với L0 về trạng thái L2 khi cần sửa đổi L2 trạng thái hoặc khi giá trị của nó đã lỗi thời. Điều này tạo cơ hội để tối ưu hóa hiệu suất.
Khi vCPU thoát khỏi lệnh gọi H_GUEST_RUN_VCPU(), L1 bên trong
đánh dấu tất cả trạng thái L2 là không hợp lệ. Điều này có nghĩa là nếu L1 muốn biết
trạng thái L2 (giả sử thông qua lệnh gọi kvm_get_one_reg()), nó cần gọi
H_GUEST_GET_STATE() để có được trạng thái đó. Sau khi đọc xong, nó được đánh dấu là
hợp lệ trong L1 cho đến khi L2 được chạy lại.
Ngoài ra, khi L1 sửa đổi trạng thái L2 vcpu, nó không cần phải ghi nó
đến L0 cho đến khi vcpu L2 đó chạy lại. Do đó khi L1 cập nhật
trạng thái (giả sử thông qua lệnh gọi kvm_set_one_reg()), nó ghi vào L1 nội bộ
sao chép và chỉ xóa bản sao này vào L0 khi L2 chạy lại thông qua
bộ đệm đầu vào H_GUEST_VCPU_RUN().
Việc cập nhật trạng thái lười biếng này của L1 sẽ tránh được những
Cuộc gọi H_GUEST_{G|S}ET_STATE().