Skip to content

Commit 0b18ada

Browse files
Pull up following revision(s) (requested by bouyer in ticket #1168):
sys/arch/i386/i386/locore.S: revision 1.202 sys/arch/i386/i386/locore.S: revision 1.203 sys/arch/i386/i386/locore.S: revision 1.204 sys/arch/amd64/amd64/locore.S: revision 1.231 sys/arch/amd64/amd64/locore.S: revision 1.232 sys/arch/amd64/amd64/locore.S: revision 1.233 sys/arch/xen/xen/hypervisor.c: revision 1.100 all via patch Our PVH bootstrap code assumed that the hvm_start_info structure provided by Xen is just after the end of the symbol case. With Xen 4.20 it's not always the case, so: - get the symbol table size from the first byte of the symbol table area provided by Xen. As we don't know if there is a symbol table or not, do a minimal sanity check on the size. - if the hvm_start_info structure is not in the page after kernel_end or esym, copy it there (this was already done in the genpvh case). While there, if we copy we can easily compute the size and not assume it all fits in one page. With this, a NetBSD PVH dom0 can boot on Xen 4.20 Fix various typos, mainly in comments. Fix some issues with symbol table detection on Xen PVH: - the stack grows down so the last pushed value is at 0(%esp), not -4(%esp). Pointed out by Joachim Kuebart. - 0x3fffffff is 1GB-1, not 1MB-1. Test the symtab size against 16MB (amd64 generic symbol table is just above 1MB these days) - I got confused by cmp's arguments order between intel and gas syntax, so the tests did the opposite of intended and the symtab was always considered valid. While there use unsigned conditions. Should fix booting in PVH mode with netbsd-INSTALL (which is stripped)
1 parent eecdbb2 commit 0b18ada

3 files changed

Lines changed: 212 additions & 75 deletions

File tree

sys/arch/amd64/amd64/locore.S

Lines changed: 102 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: locore.S,v 1.214.4.3 2025/03/29 10:32:43 martin Exp $ */
1+
/* $NetBSD: locore.S,v 1.214.4.4 2025/10/01 17:19:00 martin Exp $ */
22

33
/*
44
* Copyright-o-rama!
@@ -842,6 +842,7 @@ next: pop %edi
842842
jmp compat
843843
compat:
844844

845+
movl $RELOC(tmpstk),%esp
845846
/*
846847
* 5. Not quite done yet, we're now in a compatibility segment, in
847848
* legacy mode. We must jump to a long mode segment. Need to set up
@@ -1061,7 +1062,6 @@ ENTRY(start_pvh)
10611062
*
10621063
* To distinguish between the 2 cases, we'll use the 'cpuid' instruction
10631064
*/
1064-
10651065
push %ebx
10661066
xorl %eax, %eax
10671067
cpuid
@@ -1084,85 +1084,139 @@ ENTRY(start_pvh)
10841084

10851085
.start_genpvh:
10861086

1087-
/* First, copy the hvm_start_info structure to __kernel_end */
1087+
/* announce ourself */
1088+
movl $VM_GUEST_GENPVH, RELOC(vm_guest)
1089+
1090+
pop %ebx
1091+
movl $RELOC(__kernel_end), %eax
1092+
movl %eax, %ecx
1093+
addl $KERNBASE_LO,%ecx
1094+
movl $RELOC(esym),%ebp
1095+
movl %ecx,(%ebp)
1096+
movl $KERNBASE_HI,4(%ebp)
1097+
1098+
jmp .copy_hvm_info
1099+
1100+
.start_xen32:
1101+
movl $VM_GUEST_XENPVH, RELOC(vm_guest)
1102+
/*
1103+
* Read the size of the symbol table, sanity-check and compute the end
1104+
* We have:
1105+
* | kernel |
1106+
* -------------- kernel_end
1107+
* alignment
1108+
* -------------- bsd_symtab
1109+
* | size (int) |
1110+
* | elf_header |
1111+
*
1112+
*/
1113+
movl $RELOC(__kernel_end), %ebp
1114+
addl $3, %ebp
1115+
andl $~3, %ebp
1116+
movl 0(%ebp), %eax /* read size */
1117+
testl $~0x00ffffff, %eax /* more than 16MB ? */
1118+
jnz .bad_esym
1119+
addl %ebp, %eax /* compute esym */
1120+
/* check if start_info is within symbol table */
1121+
movl 0(%esp), %ebx
1122+
cmp %ebp, %ebx
1123+
jb .save_esym /* %ebx < __kernel_end */
1124+
cmp %eax, %ebx
1125+
jae .save_esym /* %ebx >= esym */
1126+
1127+
.bad_esym:
1128+
movl $RELOC(__kernel_end), %eax
1129+
.save_esym:
1130+
movl %eax, %ebx
1131+
addl $KERNBASE_LO,%ebx
1132+
movl $RELOC(esym),%ebp
1133+
movl %ebx,(%ebp)
1134+
movl $KERNBASE_HI,4(%ebp)
1135+
/* advance to next page boundary, this will be our hvm_start_info */
1136+
addl $PGOFSET,%eax
1137+
andl $~PGOFSET,%eax
10881138
pop %ebx
1139+
1140+
.copy_hvm_info:
1141+
/*
1142+
* %ebx points to physical address provided by Xen
1143+
* %eax points to where we want it to be copied to
1144+
*/
1145+
/* check if %ebx and %eax are in the same page */
1146+
movl %ebx, %esi
1147+
addl $PGOFSET,%esi
1148+
andl $~PGOFSET,%esi
1149+
cmp %esi, %eax
1150+
je .same_hvm_info
1151+
1152+
/* First, copy the hvm_start_info structure to %eax */
10891153
movl %ebx, %esi
1090-
movl $RELOC(__kernel_end), %edi
1154+
movl %eax, %edi
10911155
movl $HVM_START_INFO_SIZE, %ecx
10921156
shrl $2, %ecx
10931157
rep movsl
10941158

10951159
/* Copy cmdline_paddr after hvm_start_info */
10961160
movl CMDLINE_PADDR(%ebx), %esi
1097-
movl $RELOC(__kernel_end), %ecx
1098-
movl %edi, CMDLINE_PADDR(%ecx) /* Set new cmdline_paddr in hvm_start_info */
1099-
.cmdline_copy:
1100-
movb (%esi), %al
1161+
movl %edi, CMDLINE_PADDR(%eax) /* Set new cmdline_paddr in hvm_start_info */
1162+
.cmdline_copy:
1163+
movb (%esi), %cl
11011164
movsb
1102-
cmp $0, %al
1165+
cmp $0, %cl
11031166
jne .cmdline_copy
11041167

11051168
/* Copy memmap_paddr after cmdline (only if hvm_start_info->version != 0) */
1106-
xorl %eax, %eax
1107-
cmpl START_INFO_VERSION(%ebx), %eax
1108-
je .reload_ebx
1169+
xorl %ecx, %ecx
1170+
cmpl START_INFO_VERSION(%ebx), %ecx
1171+
je .save_hvm_info
1172+
pushl %eax
11091173
movl MMAP_PADDR(%ebx), %esi
1110-
movl $RELOC(__kernel_end), %ecx
1111-
movl %edi, MMAP_PADDR(%ecx) /* Set new memmap_paddr in hvm_start_info */
1174+
movl %edi, MMAP_PADDR(%eax) /* Set new memmap_paddr in hvm_start_info */
11121175
movl MMAP_ENTRIES(%ebx), %eax /* Get memmap_entries */
11131176
movl $MMAP_ENTRY_SIZE, %ebx
11141177
mull %ebx /* eax * ebx => edx:eax */
11151178
movl %eax, %ecx
11161179
shrl $2, %ecx
11171180
rep movsl
1181+
popl %eax
11181182

1119-
.reload_ebx:
1120-
movl $RELOC(__kernel_end), %ebx
1121-
1122-
/* announce ourself */
1123-
movl $VM_GUEST_GENPVH, RELOC(vm_guest)
1124-
1125-
jmp .save_hvm_start_paddr
1126-
1127-
.start_xen32:
1128-
pop %ebx
1129-
movl $VM_GUEST_XENPVH, RELOC(vm_guest)
1130-
1131-
.save_hvm_start_paddr:
1132-
/*
1133-
* save addr of the hvm_start_info structure. This is also the end
1134-
* of the symbol table
1183+
.save_hvm_info:
11351184
/*
1136-
* save addr of the hvm_start_info structure. This is also the end
1137-
* of the symbol table
1185+
* %eax points to the start of hvm_start_info
1186+
* %edi points to the end
11381187
*/
1139-
movl %ebx, RELOC(hvm_start_paddr)
1140-
movl %ebx, %eax
1141-
addl $KERNBASE_LO,%eax
1142-
movl $RELOC(esym),%ebp
1188+
addl $KERNBASE_LO,%eax
1189+
movl $RELOC(hvm_start_info),%ebp
11431190
movl %eax,(%ebp)
11441191
movl $KERNBASE_HI,4(%ebp)
1192+
1193+
/* round end to next page boundary */
1194+
addl $PGOFSET,%edi
1195+
andl $~PGOFSET,%edi
1196+
11451197
/* get a page for HYPERVISOR_shared_info */
11461198
/* this is only needed if we are running on Xen */
11471199
cmpl $VM_GUEST_XENPVH, RELOC(vm_guest)
1148-
jne .add_hvm_start_info_page
1149-
addl $PAGE_SIZE, %ebx
1150-
addl $PGOFSET,%ebx
1151-
andl $~PGOFSET,%ebx
1200+
jne .save_eblob
11521201
movl $RELOC(HYPERVISOR_shared_info_pa),%ebp
1153-
movl %ebx,(%ebp)
1202+
movl %edi,(%ebp)
11541203
movl $0,4(%ebp)
1155-
/* XXX assume hvm_start_info+dependant structure fits in a single page */
1156-
.add_hvm_start_info_page:
1157-
addl $PAGE_SIZE, %ebx
1158-
addl $PGOFSET,%ebx
1159-
andl $~PGOFSET,%ebx
1160-
addl $KERNBASE_LO,%ebx
1204+
addl $PAGE_SIZE, %edi
1205+
.save_eblob:
1206+
addl $KERNBASE_LO,%edi
11611207
movl $RELOC(eblob),%ebp
1162-
movl %ebx,(%ebp)
1208+
movl %edi,(%ebp)
11631209
movl $KERNBASE_HI,4(%ebp)
11641210

11651211
jmp .Lbiosbasemem_finished
1212+
1213+
.same_hvm_info:
1214+
/* just use the provided %ebx */
1215+
/* XXX assume hvm_start_info+dependant structure fits in a single page */
1216+
movl %ebx, %eax
1217+
movl %ebx, %edi
1218+
addl $PAGE_SIZE, %edi
1219+
jmp .save_hvm_info
11661220
END(start_pvh)
11671221
.code64
11681222
# endif /* !XENPV */

sys/arch/i386/i386/locore.S

Lines changed: 108 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: locore.S,v 1.190.4.2 2023/10/18 15:19:08 martin Exp $ */
1+
/* $NetBSD: locore.S,v 1.190.4.3 2025/10/01 17:19:00 martin Exp $ */
22

33
/*
44
* Copyright-o-rama!
@@ -128,7 +128,7 @@
128128
*/
129129

130130
#include <machine/asm.h>
131-
__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.190.4.2 2023/10/18 15:19:08 martin Exp $");
131+
__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.190.4.3 2025/10/01 17:19:00 martin Exp $");
132132

133133
#include "opt_copy_symtab.h"
134134
#include "opt_ddb.h"
@@ -1191,31 +1191,118 @@ ENTRY(start_xenpvh)
11911191
rep
11921192
stosb
11931193

1194+
/* push addr of the hvm_start_info structure to stack */
1195+
push %ebx
1196+
movl $VM_GUEST_XENPVH, RELOC(vm_guest)
1197+
/*
1198+
* read the size of the symbol table, sanity-check and compute the end
1199+
* we have:
1200+
* | kernel |
1201+
* -------------- kernel_end
1202+
* alignment
1203+
* -------------- bsd_symtab
1204+
* | size (int) |
1205+
* | elf_header |
1206+
*
1207+
*/
1208+
movl $RELOC(__kernel_end), %ebp
1209+
addl $3, %ebp
1210+
andl $~3, %ebp
1211+
movl 0(%ebp), %eax /* read size */
1212+
testl $~0x00ffffff, %eax /* more than 16MB ? */
1213+
jnz .bad_esym
1214+
addl %ebp, %eax /* compute esym */
1215+
/* check if start_info is within symbol table */
1216+
movl 0(%esp), %ebx
1217+
cmp %ebp, %ebx
1218+
jb .save_esym /* %ebx < __kernel_end */
1219+
cmp %eax, %ebx
1220+
jae .save_esym /* %ebx > esym */
1221+
1222+
.bad_esym:
1223+
movl $RELOC(__kernel_end), %eax
1224+
.save_esym:
1225+
movl %eax, %ebx
1226+
addl $KERNBASE,%ebx
1227+
movl %ebx,RELOC(esym)
1228+
/* advance to next page boundary, this will be our hvm_start_info */
1229+
addl $PGOFSET,%eax
1230+
andl $~PGOFSET,%eax
1231+
pop %ebx
1232+
1233+
.copy_hvm_info:
11941234
/*
1195-
* save addr of the hvm_start_info structure. This is also the end
1196-
* of the symbol table
1235+
* save addr of the hvm_start_info structure.
1236+
* %ebx points to physical address provided by Xen
1237+
* %eax points to we want it to be copied to
11971238
*/
1198-
movl %ebx, RELOC(hvm_start_paddr)
1199-
movl %ebx, %eax
1200-
addl $KERNBASE,%eax
1201-
movl $RELOC(esym),%ebp
1202-
movl %eax,(%ebp)
1239+
/* check if %ebx and %eax are in the same page */
1240+
movl %ebx, %esi
1241+
addl $PGOFSET,%esi
1242+
andl $~PGOFSET,%esi
1243+
cmp %esi, %eax
1244+
je .same_hvm_info
1245+
1246+
/* First, copy the hvm_start_info structure to %eax */
1247+
movl %ebx, %esi
1248+
movl %eax, %edi
1249+
movl $HVM_START_INFO_SIZE, %ecx
1250+
shrl $2, %ecx
1251+
rep movsl
1252+
1253+
/* Copy cmdline_paddr after hvm_start_info */
1254+
movl CMDLINE_PADDR(%ebx), %esi
1255+
movl %edi, CMDLINE_PADDR(%eax) /* Set new cmdline_paddr in hvm_start_info */
1256+
.cmdline_copy:
1257+
movb (%esi), %cl
1258+
movsb
1259+
cmp $0, %cl
1260+
jne .cmdline_copy
1261+
1262+
/* Copy memmap_paddr after cmdline (only if hvm_start_info->version != 0) */
1263+
xorl %ecx, %ecx
1264+
cmpl START_INFO_VERSION(%ebx), %ecx
1265+
je .save_hvm_info
1266+
pushl %eax
1267+
movl MMAP_PADDR(%ebx), %esi
1268+
movl %edi, MMAP_PADDR(%eax) /* Set new memmap_paddr in hvm_start_info */
1269+
movl MMAP_ENTRIES(%ebx), %eax /* Get memmap_entries */
1270+
movl $MMAP_ENTRY_SIZE, %ebx
1271+
mull %ebx /* eax * ebx => edx:eax */
1272+
movl %eax, %ecx
1273+
shrl $2, %ecx
1274+
rep movsl
1275+
popl %eax
1276+
1277+
.save_hvm_info:
1278+
/*
1279+
* %eax points to the start of hvm_start_info
1280+
* %edi points to the end
1281+
*/
1282+
addl $KERNBASE,%eax
1283+
movl %eax,RELOC(hvm_start_info)
1284+
1285+
/* round end to next page boundary */
1286+
addl $PGOFSET,%edi
1287+
andl $~PGOFSET,%edi
1288+
12031289
/* get a page for HYPERVISOR_shared_info */
1204-
addl $PAGE_SIZE, %ebx
1205-
addl $PGOFSET,%ebx
1206-
andl $~PGOFSET,%ebx
12071290
movl $RELOC(HYPERVISOR_shared_info_pa),%ebp
1208-
movl %ebx,(%ebp)
1209-
/* XXX assume hvm_start_info+dependant structure fits in a single page */
1210-
addl $PAGE_SIZE, %ebx
1211-
addl $PGOFSET,%ebx
1212-
andl $~PGOFSET,%ebx
1213-
addl $KERNBASE,%ebx
1291+
movl %edi,(%ebp)
1292+
addl $PAGE_SIZE, %edi
1293+
1294+
addl $KERNBASE,%edi
12141295
movl $RELOC(eblob),%ebp
1215-
movl %ebx,(%ebp)
1216-
/* announce ourself */
1217-
movl $VM_GUEST_XENPVH, RELOC(vm_guest)
1296+
movl %edi,(%ebp)
12181297
jmp .Lstart_common
1298+
1299+
.same_hvm_info:
1300+
/* just use the provided %ebx */
1301+
/* XXX assume hvm_start_info+dependant structure fits in a single page */
1302+
movl %ebx, %eax
1303+
movl %ebx, %edi
1304+
addl $PAGE_SIZE, %edi
1305+
jmp .save_hvm_info
12191306
END(start_xenpvh)
12201307
.align 8
12211308
gdtdesc_xenpvh:

sys/arch/xen/xen/hypervisor.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: hypervisor.c,v 1.96.4.1 2025/03/29 10:32:43 martin Exp $ */
1+
/* $NetBSD: hypervisor.c,v 1.96.4.2 2025/10/01 17:19:00 martin Exp $ */
22

33
/*
44
* Copyright (c) 2005 Manuel Bouyer.
@@ -53,7 +53,7 @@
5353

5454

5555
#include <sys/cdefs.h>
56-
__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.96.4.1 2025/03/29 10:32:43 martin Exp $");
56+
__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.96.4.2 2025/10/01 17:19:00 martin Exp $");
5757

5858
#include <sys/param.h>
5959
#include <sys/systm.h>
@@ -234,8 +234,6 @@ xen_init_hypercall_page(void)
234234
wrmsr(descs[1], (uintptr_t)&hypercall_page - KERNBASE);
235235
}
236236

237-
uint32_t hvm_start_paddr;
238-
239237
void init_xen_early(void);
240238
void
241239
init_xen_early(void)
@@ -244,8 +242,6 @@ init_xen_early(void)
244242
if (!vm_guest_is_pvh())
245243
return;
246244

247-
hvm_start_info = (void *)((uintptr_t)hvm_start_paddr + KERNBASE);
248-
249245
if (hvm_start_info->cmdline_paddr != 0) {
250246
cmd_line =
251247
(void *)((uintptr_t)hvm_start_info->cmdline_paddr + KERNBASE);

0 commit comments

Comments
 (0)