]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/form/VMCPUFlagSelector.js
CPU flags: Add aes flag
[pve-manager.git] / www / manager6 / form / VMCPUFlagSelector.js
1 /*jslint confusion: true*/
2 Ext.define('PVE.form.VMCPUFlagSelector', {
3 extend: 'Ext.grid.Panel',
4 alias: 'widget.vmcpuflagselector',
5
6 mixins: {
7 field: 'Ext.form.field.Field'
8 },
9
10 disableSelection: true,
11 columnLines: false,
12 selectable: false,
13 hideHeaders: true,
14
15 scrollable: 'y',
16 height: 200,
17
18 unkownFlags: [],
19
20 store: {
21 type: 'store',
22 fields: ['flag', { name: 'state', defaultValue: '=' }, 'desc'],
23 data: [
24 // FIXME: let qemu-server host this and autogenerate or get from API call??
25 { flag: 'md-clear', desc: 'Required to let the guest OS know if MDS is mitigated correctly' },
26 { flag: 'pcid', desc: 'Meltdown fix cost reduction on Westmere, Sandy-, and IvyBridge Intel CPUs' },
27 { flag: 'spec-ctrl', desc: 'Allows improved Spectre mitigation with Intel CPUs' },
28 { flag: 'ssbd', desc: 'Protection for "Speculative Store Bypass" for Intel models' },
29 { flag: 'ibpb', desc: 'Allows improved Spectre mitigation with AMD CPUs' },
30 { flag: 'virt-ssbd', desc: 'Basis for "Speculative Store Bypass" protection for AMD models' },
31 { flag: 'amd-ssbd', desc: 'Improves Spectre mitigation performance with AMD CPUs, best used with "virt-ssbd"' },
32 { flag: 'amd-no-ssb', desc: 'Notifies guest OS that host is not vulnerable for Spectre on AMD CPUs' },
33 { flag: 'pdpe1gb', desc: 'Allow guest OS to use 1GB size pages, if host HW supports it' },
34 { flag: 'hv-tlbflush', desc: 'Improve performance in overcommitted Windows guests. May lead to guest bluescreens on old CPUs.' },
35 { flag: 'hv-evmcs', desc: 'Improve performance for nested virtualization. Only supported on Intel CPUs.' },
36 { flag: 'aes', desc: 'Activate AES instruction set for HW acceleration.' }
37 ],
38 listeners: {
39 update: function() {
40 this.commitChanges();
41 }
42 }
43 },
44
45 getValue: function() {
46 var me = this;
47 var store = me.getStore();
48 var flags = '';
49
50 // ExtJS does not has a nice getAllRecords interface for stores :/
51 store.queryBy(Ext.returnTrue).each(function(rec) {
52 var s = rec.get('state');
53 if (s && s !== '=') {
54 var f = rec.get('flag');
55 if (flags === '') {
56 flags = s + f;
57 } else {
58 flags += ';' + s + f;
59 }
60 }
61 });
62
63 flags += me.unkownFlags.join(';');
64
65 return flags;
66 },
67
68 setValue: function(value) {
69 var me = this;
70 var store = me.getStore();
71
72 me.value = value || '';
73
74 me.unkownFlags = [];
75
76 me.getStore().queryBy(Ext.returnTrue).each(function(rec) {
77 rec.set('state', '=');
78 });
79
80 var flags = value ? value.split(';') : [];
81 flags.forEach(function(flag) {
82 var sign = flag.substr(0, 1);
83 flag = flag.substr(1);
84
85 var rec = store.findRecord('flag', flag);
86 if (rec !== null) {
87 rec.set('state', sign);
88 } else {
89 me.unkownFlags.push(flag);
90 }
91 });
92 store.reload();
93
94 var res = me.mixins.field.setValue.call(me, value);
95
96 return res;
97 },
98 columns: [
99 {
100 dataIndex: 'state',
101 renderer: function(v) {
102 switch(v) {
103 case '=': return 'Default';
104 case '-': return 'Off';
105 case '+': return 'On';
106 default: return 'Unknown';
107 }
108 },
109 width: 65
110 },
111 {
112 xtype: 'widgetcolumn',
113 dataIndex: 'state',
114 width: 95,
115 onWidgetAttach: function (column, widget, record) {
116 var val = record.get('state') || '=';
117 widget.down('[inputValue=' + val + ']').setValue(true);
118 // TODO: disable if selected CPU model and flag are incompatible
119 },
120 widget: {
121 xtype: 'radiogroup',
122 hideLabel: true,
123 layout: 'hbox',
124 validateOnChange: false,
125 value: '=',
126 listeners: {
127 change: function(f, value) {
128 var v = Object.values(value)[0];
129 f.getWidgetRecord().set('state', v);
130
131 var view = this.up('grid');
132 view.dirty = view.getValue() !== view.originalValue;
133 view.checkDirty();
134 //view.checkChange();
135 }
136 },
137 items: [
138 {
139 boxLabel: '-',
140 boxLabelAlign: 'before',
141 inputValue: '-'
142 },
143 {
144 checked: true,
145 inputValue: '='
146 },
147 {
148 boxLabel: '+',
149 inputValue: '+'
150 }
151 ]
152 }
153 },
154 {
155 dataIndex: 'flag',
156 width: 100
157 },
158 {
159 dataIndex: 'desc',
160 cellWrap: true,
161 flex: 1
162 }
163 ],
164
165 initComponent: function() {
166 var me = this;
167
168 // static class store, thus gets not recreated, so ensure defaults are set!
169 me.getStore().data.forEach(function(v) {
170 v.state = '=';
171 });
172
173 me.value = me.originalValue = '';
174
175 me.callParent(arguments);
176 }
177 });